-
10 minutes to pandas - Group by (split - apply - combine)데이터 분석/Pandas 2022. 3. 29. 23:00
Group By 개요
Splitting the data into groups based on some criteria
Applying a function to each group independently
- Aggregation: 각 그룹에 대하여 요약통계를 처리할 수 있다.
- Transformation: 그룹 특화 연산을 수행하고, 전체 데이터에 대해 그 값을 적용할 수 있다.
- Filtration: 그룹 단위 연산으로 T/F 를 평가한다. True 인 대상을 추출할 수 있다.Combining the results into a data structure.
Splitting an object into groups
Groupby 를 독립적으로 이해하는 것이 중요하다.
주요기능
# 컬럼명의 값 기준으로 그룹핑하기 grouped = df.groupby("A") grouped = df.groupby(["A", "B"]) grouped = df.groupby("first") grouped = df.groupby(["first", "second"]) grouped = df.groupby(["first", "A"]) # 인덱스 명/위치를 통해 인덱스의 값을 기준으로 그룹핑하기 grouped = df.groupby(level=0) grouped = df.groupby(level=["first", "second"]) # 컬럼 및 인덱스의 값 기준으로 그룹핑하기 grouped = df.groupby([pd.Grouper(level=0), "A"]) grouped = df.groupby([pd.Grouper(freq="1M", key="Date"), "Buyer"]).sum() # Date 컬럼으로 그룹핑할 경우, index 로 옮긴후 그룹핑하기 grouped = df.groupby([df.index.year, df.index.month])
주의. 만약 그룹의 기준에 NaN 또는 NaT 가 있다면, 자동적으로 배제된다. 즉 NA 그룹이나 NaT 그룹은 없다!
만약 NA 그룹이나 NaT 그룹이 필요하면 dropna = False 를 사용하자!참고. pd.Grouper 는 특히 datetime-like object 에 대한 다양한 기능을 제공한다. 필요할 경우 더 공부해보자.
부가기능
# group by 속성 grouped = df.groupby("A", dropna=False) grouped = df.groupby("A", as_index=False) # Groupby Object 상세 확인 grouped.groups #그룹 이름과 행의 인덱스 배열 딕셔너리 grouped.ngroups # 몇 개의 그룹 grouped.get_group("bar") # 'bar 라는 이름을 가지는 그룹 for name, group in grouped: #그룹 이름과 그룹의 DataFrame Chunk print(name) print(group)
Applying
Aggregation
각 그룹에 대해 연산 (주로 통계치 계산) 을 수행할 수 있다. 스프레드시트의 Pivot Table 기능과 흡사하다!
주의. 그룹의 연산 대상에 NaN 값이 있을 경우 연산대상에서 제외된다.grouped = df.groupby("A") # 연산이 가능한 모든 컬럼에 대해서 다음 연산을 수행한다. grouped.sum() grouped.mean() grouped.size() grouped.describe() grouped.nunique() grouped.nlargest(3) # 연산이 가능한 모든 컬럼에 대해서 연산을 1개 또는 N개 수행한다. grouped.aggregate(np.sum) grouped.aggregate([np.sum, np.mean, np.std]) # 사용자정의 함수를 수행한다. grouped.agg(lambda x: x.max() - x.min()) grouped.agg([lambda x: x.max() - x.min(), lambda x: x.median() - x.mean()]) # df 의 특정 컬럼에 대해서만 연산을 수애한다. grouped["C"].agg([np.sum, np.mean, np.std]) grouped[["C", "D"]].agg([np.sum, np.mean, np.std]) # df 의 컬럼마다 다른 연산을 수행한다. grouped.agg({"C": np.sum, "D": lambda x: np.std()})
Transformation
전체 데이터에 그룹 단위의 연산값을 활용하여 특정 값을 변환할 수 있다.
# z score : 그룹의 평균과 표준편차 값을 가지고 z score 를 구한다. index = pd.date_range("10/1/1999", periods=1100) ts = pd.Series(np.random.normal(0.5, 2, 1100), index) grouped = ts.groupby(lambda x: x.year) grouped.transform(lambda x: (x - x.mean()) / x.std()) # fillna : NA 를 각 그룹의 평균값으로 채운다. grouped = df.groupby('A') grouped.transform(lambda x: x.fillna(x.mean())) grouped.ffill()
Filteration
특정 조건을 만족하는 subset 만 추출할 수 있다.
# 그룹에 속한 값의 합이 4 초과인 그룹만 남긴다. sf = pd.Series([1, 2, 2, 3, 3, 3, 4, 4, 4, 4]) sf.groupby(sf).filter(lambda x : x.sum() > 4) # 그룹 크기가 2 초과인 그룹만 남긴다. dff = pd.DataFrame({"A": np.arange(8), "B": list("aabbbbcc")}) dff.groupby('B').filter(lambda x : len(x) > 2)
응용
Flexible Apply
하나의 컬럼에 대해 값을 다양하게 변환하고 싶은 경우 다음과 같이 적용할 수 있다.
# A 컬럼 값을 기준으로 그룹핑한다. 그 중 C 컬럼에 대해 관심이 있다. grouped = df.groupby('A')['C'] # group 을 인자로 받고, 새로운 DataFrame 을 제공하는 함수이다. def f(group): return pd.DataFrame({'original': group, # 원래값 'demeaned': group - group.mean()}) # 평균과의 거리(편차) # GroupBy Object 에 대해 f 함수를 호출한다. grouped.apply(f) ''' original demeaned 0 -0.575247 -0.215962 1 0.254161 0.123181 2 -1.143704 -0.784420 3 0.215897 0.084917 4 1.193555 1.552839 '''
Piping Function Calls
Functions that take GroupBy objects can be chained together using a pipe method to allow for a cleaner, more readable syntax.
GroupBy Object 를 인자로 받아서 함수를 수행할 수 있다.
n = 1000 df = pd.DataFrame( { "Store": np.random.choice(["Store_1", "Store_2"], n), "Product": np.random.choice(["Product_1", "Product_2"], n), "Revenue": (np.random.random(n) * 50 + 10).round(2), "Quantity": np.random.randint(1, 10, size=n), } ) ''' Store Product Revenue Quantity 0 Store_2 Product_1 26.12 1 1 Store_2 Product_1 28.86 1 ''' # 여러 컬럼의 값에 대한 연산을 활용하여 결과를 제공한다. df.groupby(["Store", "Product"]).pipe( lambda grp: grp.Revenue.sum() / grp.Quantity.sum() ).unstack().round(2) ''' Product Product_1 Product_2 Store Store_1 6.82 7.05 Store_2 6.30 6.64 ''' # GroupBy Object 에 대해 사용자 정의 함수를 처리할 수 있다. def mean(groupby): return groupby.mean() df.groupby(["Store", "Product"]).pipe(mean) ''' Revenue Quantity Store Product Store_1 Product_1 34.622727 5.075758 Product_2 35.482815 5.029630 Store_2 Product_1 32.972837 5.237589 Product_2 34.684360 5.224000 '''
'데이터 분석 > Pandas' 카테고리의 다른 글
10 minutes to pandas - Pivot Tables (0) 2022.04.01 10 minutes to pandas - Reshaping (0) 2022.03.30 10 minutes to pandas - Merge & Join (0) 2022.03.27 10 minutes to pandas - 결측치 처리 (0) 2022.03.20 10 minutes to pandas - 생성 & 조회/변경 (0) 2022.03.19