아래와 같이 두 함수 모두 그룹별 함수 반환값을 반환합니다. 하지만 apply는 그룹의 개수만큼의 길이를 가지는 Series를 반환한다면, transform 함수는 input과 동일한 길이의 Series 반환합니다.
defgroup_sum(x):return x.sum()
df.groupby('key')['A'].transform(group_sum)
# 결과
```
091122153941251569712815
Name: A, dtype: int32
```
df.groupby('key')['A'].apply(group_sum)
# 결과
```
key
a 9
b 12
c 15
Name: A, dtype: int64
```
바로 전에 살펴본 대로 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')
# 결과
```
055815582558333433536636
Name: city_total_sales, dtype: int64
```
Tip
위의 반환값을 Series가 아닌 DataFrame으로 반환받고 싶다면 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
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에 작업을 한 번에 적용할 수 없습니다.