판다스에서 제공하는 transform() 함수에 대해서 알아보겠습니다. 그리고 apply 함수와의 차이점도 알아보겠습니다.
transform()과 apply() 함수는 보통 아래와 같은 경우에 사용하면 유용합니다.
- Transforming values (값 변환)
- Combining groupby() results (groupby를 사용하여 집계 함수 적용 시)
- Filtering data (데이터 필터링)
- Handling missing value at the group level (그룹별 특정 값으로 null 값 채울 때)
하나씩 코드로 살펴보겠습니다.
Transform
1. Transforming values: 값 변환
아래와 같은 데이터프레임으로 실습해 보겠습니다.
import pandas as pd
import numpy as np
df = pd.DataFrame({'A': [1,2,3], 'B': [10,20,30] })
df
아래 두 함수는 같은 결과를 나타냅니다. transform 함수로 각 속성 값에 10을 더하는 코드입니다.
apply 함수도 동일한 결과를 출력합니다.
def plus_10(x):
return x+10
df.transform(plus_10) # df.apply(plus_10)
df.transform(lambda x: x+10) # df.apply(lambda x: x+10)
아래와 같이 column 별로 다른 함수를 적용할 수 있습니다.
# column 별로 다른 함수 적용 apply 도 가능
df.transform({
'A': np.sqrt,
'B': np.exp
})
apply 함수와의 차이 1
아래와 같이 string형 함수로 인자를 넘겨줄 때, transform 함수는 결과를 잘 출력하지만 apply 함수는 오류가 발생합니다.
# String function: apply 불가
df.transform('sqrt')
또한, list형 함수도 transform에는 적용가능하지만, apply 함수는 불가합니다.
# List of functions: apply 불가
df.transform([np.sqrt, np.exp])
2. groupby 함수로 집계할 때
아래와 같은 데이터프레임으로 실습을 진행해 보겠습니다.
df = pd.DataFrame({
'key': ['a','b','c'] * 3,
'A': np.arange(9),
'B': [1,2,3] * 3,
})
df
apply 함수와의 차이 2
아래와 같이 두 함수 모두 그룹별 함수 반환값을 반환합니다. 하지만 apply는 그룹의 개수만큼의 길이를 가지는 Series를 반환한다면, transform 함수는 input과 동일한 길이의 Series 반환합니다.
def group_sum(x):
return x.sum()
df.groupby('key')['A'].transform(group_sum)
# 결과
```
0 9
1 12
2 15
3 9
4 12
5 15
6 9
7 12
8 15
Name: A, dtype: int32
```
df.groupby('key')['A'].apply(group_sum)
# 결과
```
key
a 9
b 12
c 15
Name: A, dtype: int64
```
아래와 같은 데이터프레임으로 더 실습해 보겠습니다.
df = pd.DataFrame({
'restaurant_id': [101,102,103,104,105,106,107],
'address': ['A','B','C','D', 'E', 'F', 'G'],
'city': ['London','London','London','Oxford','Oxford', 'Durham', 'Durham'],
'sales': [10,500,48,12,21,22,14]
})
df
바로 전에 살펴본 대로 apply 함수 적용 시 그룹의 개수를 길이로 가지는 Series를 반환하고, transform 함수 적용 시, input 길이의 Series를 반환하고 있습니다.
# city 별 sales 합
df.groupby('city')['sales'].sum().rename('city_total_sales') # apply와 같은 역할
# 결과
```
city
Durham 36
London 558
Oxford 33
Name: city_total_sales, dtype: int64
```
df.groupby('city')['sales'].transform(sum).rename('city_total_sales')
# 결과
```
0 558
1 558
2 558
3 33
4 33
5 36
6 36
Name: city_total_sales, dtype: int64
```
Tip
위의 반환값을 Series가 아닌 DataFrame으로 반환받고 싶다면 reset_index()를 추가하면 됩니다.
# dataframe으로 출력하려면 df.groupby('city')['sales'].sum().rename('city_total_sales').reset_index()
apply 함수로 groupby 함수를 적용하고 원래 데이터프레임에 그룹별 값을 할당하고 싶을 때는 merge나 join으로 처리해 줄 수 있습니다. 하지만 transform 함수는 원래 데이터프레임의 길이와 동일한 Series가 반환되기 때문에 바로 원래 데이터프레임에 값을 넣을 수 있습니다.
1. Apply
city_sales= df.groupby('city')['sales'].sum().rename('city_total_sales').reset_index() # apply와 동일
# merge로 해도 mapping 하는 효과
df_new = pd.merge(df, city_sales, how='left') # on=None(default)이면 두 데이터프레임의 공통 열
df_new['pct'] = df_new['sales'] / df_new['city_total_sales']
df_new['pct'] = df_new['pct'].apply(lambda x: format(x, '.2%'))
df_new
2. Transform
# groupby & transform
df['city_total_sales'] = df.groupby('city')['sales'].transform('sum')
df['pct'] = df['sales'] / df['city_total_sales']
df['pct'] = df['pct'].transform(lambda x: format(x, '.2%'))
df
3. Filtering data: 데이터 필터링
# filtering data
df[df.groupby('city')['sales'].transform('sum') > 40]
4. Handling missing value at the group level: group 별로 특정 값으로 null 값 채우기
아래와 같은 데이터프레임을 이용하여 transform 함수로 그룹별로 null 값을 채워보겠습니다.
# group level로 null 값 채우기
df = pd.DataFrame({
'name': ['A', 'A', 'B', 'B', 'B', 'C', 'C', 'C'],
'value': [1, np.nan, np.nan, 2,8,2,np.nan, 3]
})
df
df.groupby('name').transform(lambda x:x.fillna(x.mean())) # 데이터프레임으로 출력
df.groupby('name')['value'].transform(lambda x:x.fillna(x.mean())) # Series로 출력
마지막으로 apply 함수와 transform 함수의 차이점 1가지를 더 알아보겠습니다.
아래와 같이, apply 함수는 여러 개의 series와 한 번에 작업 가능하지만, transform 함수는 여러 개 series에 작업을 한 번에 적용할 수 없습니다.
def subtract_two(x):
return x['B'] - x['A']
df = pd.DataFrame({'A': [1,2,3], 'B': [10,20,30] })
# transform 불가
df.apply(subtract_two, axis=1) # df.apply(lambda x: x['B'] - x['A'], axis=1)
# 결과
```
0 9
1 18
2 27
dtype: int64
```
정리하면, apply함수와 transform 함수의 차이는 아래와 같습니다.
- transform: input과 동일한 길이의 Series 반환, 여러 개 series와 작업 한 번에 불가
- apply: 여러 개의 series와 한 번에 작업 가능
'Data Science > Pandas' 카테고리의 다른 글
Sort 커스터마이징 (범주형 변수) (0) | 2023.09.07 |
---|---|
Pandas로 datetime 다루기 (0) | 2023.09.04 |
데이터 분석 및 학습 (전체 과정) (0) | 2023.09.03 |
GridSearch를 이용한 model training (0) | 2023.09.01 |
결측치 처리 - KNNImputer (0) | 2023.09.01 |