이번 포스팅에서는 Python pandas의 GroupBy operation을 이용해서 그룹 별 가중평균(Group weighted average)을 구하는 방법을 소개하겠습니다.
앞서 GroupBy 연산자의 원리에서 소개드렸던 것처럼, Split => Apply => Combine 의 절차를 거치면서 각 그룹별 GroupBy 연산을 실행하게 됩니다.
[GroupBy 를 이용한 그룹별 가중 평균 구하기 절차]
예제로 사용할 'a'와 'b'의 두 개 그룹별로 'value 값'과 'weight 가중치'를 가지고 있는 간단한 데이터 프레임을 만들어보겠습니다.
import pandas as pd import numpy as np df = pd.DataFrame({'grp_col' : ['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'b'], 'val' : np.arange(10)+1, 'weight' : [0.0, 0.1, 0.2, 0.3, 0.4, 0.0, 0.1, 0.2, 0.3, 0.4]}) df
|
(1) GroupBy 를 활용하여 그룹 별 가중 평균 구하기 |
이제 (1) GroupBy 객체를 만들고, (2) 가중평균을 구하는 lambda 함수를 정의한 후에, (3) grouped.apply(function) 로 그룹별 가중평균을 구해보겠습니다.
# group weighted average by category grouped = df.groupby('grp_col') weighted_avg_func = lambda g:np.average(g['val'], weights=g['weight']) grouped.apply(weighted_avg_func) grp_col
a 4.0
b 9.0
dtype: float64 |
(2) 수작업으로 그룹 별 가중 평균 구하기 (Split -> Apply -> Combine) |
위에서 처럼 GroupBy 를 사용하지 않는 다면 아래에 소개한 것처럼 각 그룹별로 하나씩 Split -> Apply 하고 마지막에 Combine 을 해주는 단순 반복작업을 그룹의 개수만큼 해주어야 합니다.
그룹의 개수가 적으면 할만 한데요, 그룹의 개수가 많아지면 수고롭기도 하고, 자칫 실수도 유발할 수 있으니 위의 (1)번 GroupBy 연산자를 사용하는 방법이 좀더 추천할만 하다고 하겠습니다. 비교를 위해서 소개합니다.
- (a) Split
# split df_a = df[df['grp_col']=='a'] df_b = df[df['grp_col']=='b']
|
df_a
|
df_b
|
- (b) Apply
# apply weighted_avg_a = sum((df_a['val']*df_a['weight']))/sum(df_a['weight']) weighted_avg_b = sum((df_b['val']*df_b['weight']))/sum(df_b['weight']) |
weighted_avg_a 4.0 |
weighted_avg_b 9.0 |
- (c) Combine
# combine weighted_avg_ab = pd.DataFrame({'grp_col': ['a', 'b'], 'weighted_average': [weighted_avg_a, weighted_avg_b]}) weighted_avg_ab
|
많은 도움이 되었기를 바랍니다.