[전처리/복습] 데이터 전처리 부실공사 보수하고 기초부터 탄탄하게!(3) - 그룹화 및 Aggregation | 문자열 처리 | 시간 데이터 처리 | 데이터 결합 | apply &map & lambda 활용


1. 그룹화 및 Aggregation

 

< 🎯퀴즈 >

# titanic_df 데이터 사용

titanic_df.groupby('Embarked')['Survived'].mean()

>>> 값이 0, 1로만 이루어져 있어서 평균값은 생존자 비율과 같다.

# 객실등급(Pclass)별 최고령 승객의 나이(Age)
titanic_df.groupby('Pclass')['Age'].max()


2. 문자열 처리

문자열 데이터 처리는 매우 중요. Series.str  ➡️  df['컬럼'].str.매서드( ) 형식으로 사용

  ▶ 대소문자 변환: .lower(), .upper(), .capitalize(), .title() 등
  ▶ 공백 제거: .strip() (문자열 양 끝 공백 제거), .lstrip(), .rstrip()
  ▶ 길이 계산: .len() 각 문자열의 길이 반환
  ▶ 검색/포함 여부: .contains("문자열") 부분 문자열 포함 여부 (True/False 시리즈 반환), .startswith(), .endswith()
  ▶ 치환: .replace("기존", "새로운") 문자열 치환 (정규표현식 사용 가능)
  ▶ 분할: .split("구분자") 구분자를 기준으로 문자열을 나누어 리스트로 반환; 이후 [index]로 각 부분 추출 가능
  ▶ 이 외에도 .find(), .isdigit(), .join() 등 다양한 메서드 활용 가능

🚨 주의: Series.str 메서드는 NaN (결측치)가 있으면 작업이 불가능하므로, 먼저 결측치를 처리하거나 제거해야 함.

< 🎯퀴즈 >

# 문자열을 , 구분으로 나누고 인덱스 1 ➡️ . 구분으로 나누고 인덱스 0
titanic_df['name_title'] = titanic_df['Name'].str.split(',').str[1].str.split('.').str[0]
titanic_df['name_title']

# Embarked 값(S, C, Q)을 모두 소문자로!
titanic_df['Embarked'] = titanic_df['Embarked'].str.lower()

# Embarked 열 고유값 추출
titanic_df['Embarked'].unique()

3. 시간 데이터 처리

< 🎯 예제 >

# 최초 탑승시각 이후 얼마나 후에 탑승했는지 계산
titanic_df['hour_after_boarding'] = titanic_df['BoardTime'] - titanic_df['BoardTime'].min()
titanic_df['hour_after_boarding']

>>> 출력:
---------------------
0     0 days 00:00:00
1     0 days 06:00:00
2     0 days 00:00:00
3     0 days 00:00:00
4     0 days 00:00:00
         ...
----------------------
Name: hour_after_boarding, Length: 891, dtype: timedelta64[ns]
# 시간(hour) 단위로 변환 🚨
titanic_df['hour_after_boarding'] = titanic_df['hour_after_boarding'].dt.total_seconds()/3600
# 보기좋게 출력
titanic_df[['Embarked', 'BoardTime', 'hour_after_boarding']].head()

>>> 출력:
-------------------------------------------
Embarked	BoardTime	hour_after_boarding
0	s	1912-04-10 12:00:00	   0.0
1	c	1912-04-10 18:00:00	   6.0
2	s	1912-04-10 12:00:00	   0.0
3	s	1912-04-10 12:00:00	   0.0
4	s	1912-04-10 12:00:00	   0.0
-------------------------------------------

< 🎯 퀴즈 >

# 우선 'BoardHour'열이 datetime 형식 확인 후, .dt.hour 사용하여 시간 추출
titanic_df['BoardHour'] = titanic_df['BoardTime'].dt.hour

# 보기좋게 출력
titanic_df[['BoardHour','BoardTime', 'hour_after_boarding']].head()

>>> 출력:
----------------------------------------------------
  BoardHour	       BoardTime	 hour_after_boarding
0	12.0	1912-04-10 12:00:00	   0.0
1	18.0	1912-04-10 18:00:00	   6.0
2	12.0	1912-04-10 12:00:00	   0.0
3	12.0	1912-04-10 12:00:00	   0.0
4	12.0	1912-04-10 12:00:00	   0.0
----------------------------------------------------
🚨 생각보다 시간 데이터 처리하는 게 쉽지는 않은 것 같다. 꼼꼼히 학습해두고 자주 보자!!🚨

4. 데이터 결합 기법

< 🎯 예제 >

#1. 항구 코드 -> 이름 대응되는 새로운 데이터프레임 생성
df = pd.DataFrame({
    'Embarked' : ['s', 'c', 'q'],
    'PortName': ['Southampton', 'Cherbourg', 'Queenstown']
})

#2. Embarked 열 기준 병합
add_portname = pd.merge(titanic_df, df, on='Embarked', how='left'
add_portname[['Embarked', 'PortName']].head()

>>> 출력:
---------------------------------
	Embarked	PortName
0	   s	    Southampton
1	   c	    Cherbourg
2	   s	    Southampton
3	   s	    Southampton
4	   s	    Southampton
---------------------------------

< 🎯 퀴즈 >

# 퀴즈 1 정답: df1과 df2를 ID 열 기준으로 병합
merged_df = pd.merge(df1, df2, on='ID', how='inner')  # how는 필요에 따라 'left', 'right', 'outer' 등 변경
print("병합 결과:\n", merged_df)

# 퀴즈 2 정답: df1과 df2 세로 연결
concatenated_df = pd.concat([df1, df2], axis=0, ignore_index=True)
print("세로 연결 결과:\n", concatenated_df)

5. map / apply / lambda 함수 활용

💡 반복적인 데이터 처리를 위해 apply와 map 매서드, 그리고 lambda 함수를 활용한다!

< 🎯예제 >

#예제1: map을 사용한 값 치환
titanic_df['mapping_sur'] = titanic_df['Survived'].map({0:'사망', 1:'생존'})
titanic_df[['Survived', 'mapping_sur']].head()

>>> 출력:
------------------------
  Survived	mapping_sur
0	 0	      사망
1	 1	      생존
2	 1	      생존
3 	 1	      생존
4	 0	      사망
------------------------
#예제2: apply와 lambda를 사용한 나이대 분류
titanic_df['AgeGroup']= titanic_df['Age'].apply(lambda x: '미성년자' if x < 18 else '성인')
titanic_df[['Age', 'AgeGroup']].head()

>>> 출력:
-----------------
	Age	AgeGroup
0	22.0	성인
1	38.0	성인
2	26.0	성인
3	35.0	성인
4	35.0	성인
-----------------
#예제3: DataFrame.apply를 사용한 가족 규모 계산
titanic_df[['SibSp', 'Parch']].head()    # 기존 수 확인!

FamilySize = titanic_df.apply(lambda row: row['SibSp'] + row['Parch'] + 1, axis=1)
titanic_df['FamilySize'] = FamilySize
titanic_df[['SibSp', 'Parch', 'FamilySize']].head()

>>> 출력:
--------------------------------------
	SibSp	Parch	    FamilySize
0	  1	      0	        2
1	  1	      0	        2
2	  0	      0	        1
3	  1	      0	        2
4	  0	      0	        1
--------------------------------------

< 🎯 퀴즈 >

titanic_df['Pclasslabel'] = titanic_df['Pclass'].map({1:'1등석',2:'2등석', 3:'3등석'})
titanic_df[['Pclass', 'Pclasslabel']].head()

# 방법1 : lambda 활용
titanic_df['NameLength'] = titanic_df['Name'].apply(lambda x: len(x))
titanic_df[['Name', 'NameLength']]

# 방법2 : 문자열 기능
titanic_df['namelength'] = titanic_df['Name'].str.len()
titanic_df[['Name', 'namelength']].head()

>>> 출력:
--------------------------------------------------------------------
	Name	                                          namelength
0	Braund, Mr. Owen Harris	                              23
1	Cumings, Mrs. John Bradley (Florence Briggs Th...     51
2	Heikkinen, Miss. Laina	                              22
3	Futrelle, Mrs. Jacques Heath (Lily May Peel)	      44
4	Allen, Mr. William Henry	                      24
--------------------------------------------------------------------

끝.