개요
Pandas에서 DataFrame에 대해 groupby로 여러 컬럼에 여러 연산을 적용하면 멀티 인덱스 컬럼 형태의 결과를 반환받을 수 있다.
df.groupby('a', dropna=False).agg([list, 'count', 'size'])
Pandas 공식 문서 https://pandas.pydata.org/docs/user_guide/advanced.html를 보면 멀티 인덱스 컬럼을 사용한 인덱싱 방법을 상세하게 설명하고 있지만, 아무래도 다소 복잡한 것 같아 그룹 연산한 결과를 단일 인덱스 컬럼 형태로 반환받고 싶다.
방법을 적어둔다.
named aggregation
Pandas에서 agg 함수를 사용할 때 컬럼에 대한 연산 출력 이름을 제어할 수 있도록 named aggregation을 지원하고 있다. agg 함수에 키워드 매개 변수로 결과 컬럼의 이름과 연산 대상이 되는 컬럼, 그리고 연산할 함수를 지정하면 된다.
df.groupby("<그룹화 기준 컬럼>").agg(
<결과 컬럼 이름>=pd.NamedAgg(column="<연산 대상 컬럼>", aggfunc="<연산 함수>"),
<결과 컬럼 이름>=pd.NamedAgg(column="<연산 대상 컬럼>", aggfunc="<연산 함수>")
)
NamdeAgg 튜플 대신 일반 튜플로 지정해도 된다.
df.groupby("<그룹화 기준 컬럼>").agg(
<결과 컬럼 이름>=(column="<연산 대상 컬럼>", aggfunc="<연산 함수>"),
<결과 컬럼 이름>=(column="<연산 대상 컬럼>", aggfunc="<연산 함수>")
)
사용 예시
예시 데이터
df = pd.DataFrame({
'a': ['A', 'A', 'B', 'B', 'B', None],
'b': [1, 2, 5, None, 4, 6],
'c': ['x', 'y', 'z', 'x', 'y', 'z']
})
a 컬럼을 기준으로 그룹화하여 다른 컬럼을 리스트로 변환하고, count, size 함수를 적용하면 아래 사진과 같은 결과를 얻을 수 있다.
df.groupby('a', dropna=False).agg([list, 'count', 'size'])
각 멀티 인덱스 컬럼을 다음과 같이 지정해 본다.
df['b']['list'] -> df['list_b']
df['b']['count'] -> df['cnt_b']
df['b']['size'] -> df['size_b']
컬럼 c에 대해서도 동일한 형식으로 지정하려고 한다.
NamedAgg 튜플 사용
df.groupby('a', dropna=False).agg(list_b=pd.NamedAgg('b', list), cnt_b=pd.NamedAgg('b', 'count'), size_b=pd.NamedAgg('b', 'size'),
list_c=pd.NamedAgg('c', list), cnt_c=pd.NamedAgg('c', 'count'), size_c=pd.NamedAgg('c', 'size'))
일반 튜플 사용
df.groupby('a', dropna=False).agg(list_b=('b', list), cnt_b=('b', 'count'), size_b=('b', 'size'),
list_c=('c', list), cnt_c=('c', 'count'), size_c=('c', 'size'))
보다 간결하게 표현할 때는 일반 튜플을 사용하는 것이 좋을 거 같다.
참고 문서
https://pandas.pydata.org/docs/reference/api/pandas.core.groupby.DataFrameGroupBy.agg.html