반응형

02-11. 그룹화 계산 (groupby)

DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=NoDefault.no_default, observed=False, dropna=True)

 

개요


groupby 메서드는 데이터를 그룹화하여 연산을 수행하는 메서드 입니다.

 

사용법


기본 사용법
※ 자세한 내용은 아래 예시를 참고 바랍니다.
df.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=NoDefault.no_default, observed=False, dropna=True)
by : 그룹화할 내용입니다. 함수, 축, 리스트 등등이 올 수 있습니다.
axis : 그룹화를 적용할 축입니다.
level : 멀티 인덱스의 경우 레벨을 지정할 수 있습니다.
as_index : 그룹화할 내용을 인덱스로 할지 여부입니다. False이면 기존 인덱스가 유지됩니다.
sort : 그룹키를 정렬할지 여부입니다.
group_keys : apply메서드 사용시 결과에따라 그룹화 대상인 열이 인덱스와 중복(group key)이 될 수 있습니다. 이 때, group_keys=False로 인덱스를 기본값으로 지정할 수 있습니다.
squeeze : 결과가 1행 or 1열짜리 데이터일 경우 Series로, 1행&1열 짜리 데이터일 경우 스칼라로 출력합니다.
observed : Categorical로 그룹화 할 경우 Categorical 그룹퍼에 의해 관찰된 값만 표시할 지 여부입니다.
dropna : 결측값을 계산에서 제외할지 여부입니다.

반응형

 

예시


먼저 기본적인 사용법 예시를위하여 데이터를 만들어 보겠습니다.

idx=['A','A','B','B','B','C','C','C','D','D','D','D','E','E','E']
col=['col1','col2','col3']
data = np.random.randint(0,9,(15,3))
df = pd.DataFrame(data=data, index=idx, columns=col).reset_index()
print(df)
>>
   index  col1  col2  col3
0      A     5     0     7
1      A     2     6     2
2      B     1     1     8
3      B     1     6     6
4      B     3     2     3
5      C     1     0     8
6      C     8     4     1
7      C     1     5     5
8      D     3     3     7
9      D     5     7     7
10     D     1     6     5
11     D     4     0     0
12     E     0     5     6
13     E     2     7     7
14     E     0     7     0

 

 

기본적인 사용법
추가 메서드 없이 groupby 메서드를 실행하면 DataFrameGroupBy 오브젝트가 생성이 됩니다.

print(df.groupby('index')) # index 컬럼에 대해서 groupby 수행

여기에 추가 연산 메서드를 입력하면, 해당 열의 그룹화된 데이터에 대해서 연산이 수행됩니다.

print(df.groupby('index').mean())
>>
           col1      col2      col3
index                              
A      3.500000  3.000000  4.500000
B      1.666667  3.000000  5.666667
C      3.333333  3.000000  4.666667
D      3.250000  4.000000  4.750000
E      0.666667  6.333333  4.333333



추가 메서드의 적용
추가 메서드로는 단순 연산 메서드가 아닌 agg나 apply 메서드 등 여러 메서드의 적용이 가능합니다.

print(df.groupby('index').count())
>>
       col1  col2  col3
index                  
A         2     2     2
B         3     3     3
C         3     3     3
D         4     4     4
E         3     3     3

agg메서드를 이용해 여러 연산을 수행할 경우 MultiColumns 형태로 출력됩니다.

print(df.groupby('index').agg(['sum','mean']))
>>
      col1           col2           col3          
       sum      mean  sum      mean  sum      mean
index                                             
A        7  3.500000    6  3.000000    9  4.500000
B        5  1.666667    9  3.000000   17  5.666667
C       10  3.333333    9  3.000000   14  4.666667
D       13  3.250000   16  4.000000   19  4.750000
E        2  0.666667   19  6.333333   13  4.333333



group_keys 인수의 사용
apply 메서드를 이용해 groupby연산을 수행할 경우, groupkey가 설정되기 때문에 때에따라 컬럼과 인덱스가 중복될 수 있습니다. 이 때 group_keys=False를 통해 기본 인덱스로 출력이 가능합니다.

def top (df,n=2,col='col1'):
    return df.sort_values(by=col)[-n:] #상위 n개 열을 반환하는 함수 top 생성
print(df.groupby('index').apply(top))
>>
         index  col1  col2  col3 # 인덱스와 index열이 중복
index                           
A     1      A     2     6     2
      0      A     5     0     7
B     3      B     1     6     6
      4      B     3     2     3
C     7      C     1     5     5
      6      C     8     4     1
D     11     D     4     0     0
      9      D     5     7     7
E     14     E     0     7     0
      13     E     2     7     7
print(df.groupby('index',group_keys=False).apply(top))
>>
   index  col1  col2  col3 # 인덱스와의 중복이 제거
1      A     2     6     2
0      A     5     0     7
3      B     1     6     6
4      B     3     2     3
7      C     1     5     5
6      C     8     4     1
11     D     4     0     0
9      D     5     7     7
14     E     0     7     0
13     E     2     7     7



observed 인수의 사용
Categorical 객체를 생성할 때, 그룹화(groupby)할 열에 있는 값이 아닌 값을 포함하게되면, 그룹화 할 때 해당 값을 표시할지 여부를 선택할 수 있습니다.

df_cat = pd.Categorical(df['index'], categories=['A','B','C','D','E','F']) # df의 index열에 대해서 A,B,C,D,E,F 로 Categorical을 하여 df_cat 생성
print(df_cat)
>>
['A', 'A', 'B', 'B', 'B', ..., 'D', 'D', 'E', 'E', 'E']
Length: 15
Categories (6, object): ['A', 'B', 'C', 'D', 'E', 'F'] # 값은 A~E 까지 있지만, 카테고리는 F까지 지정함.

위 catrory 객체에 대해서 col1열을 groupby 하면 아래와 같이 카테고리에만 존재하는 F에대한 groupby 값이 출력됩니다.

print(df['col1'].groupby(df_cat).count())
>>
A    2
B    3
C    3
D    4
E    3
F    0 # index열에는 없지만, F까지 category 되었음. observed=False(기본값)인 경우 카테고리 전체가 표시됨.
Name: col1, dtype: int64

observed=True로 할경우 관찰되지 않는값 (카테고리에만 존재하는값)은 표시되지 않습니다.

print(df['col1'].groupby(df_cat,observed=True).count())
>>
A    2
B    3
C    3
D    4
E    3
Name: col1, dtype: int64



as_index인수의 사용
특정 열을 지정하여 groupby할 경우 해당 열이 인덱스가 되는데, as_index=False로 하여 기존 인덱스의 유지가 가능합니다.

print(df.groupby(['index'],as_index=False).sum())
>>
  index  col1  col2  col3
0     A     7     6     9
1     B     5     9    17
2     C    10     9    14
3     D    13    16    19
4     E     2    19    13



dropna인수의 사용
dropna인수를 통해 결측값(NaN)이 포함된 경우 그룹화에서 제외할지 여부를 정할 수 있습니다.
먼저 index열의 6번행을 결측값(NaN)으로 변경해보겠습니다.

df.loc[6,'index'] = np.NaN
print(df)
>>
   index  col1  col2  col3
0      A     5     0     7
1      A     2     6     2
2      B     1     1     8
3      B     1     6     6
4      B     3     2     3
5      C     1     0     8
6    NaN     8     4     1
7      C     1     5     5
8      D     3     3     7
9      D     5     7     7
10     D     1     6     5
11     D     4     0     0
12     E     0     5     6
13     E     2     7     7
14     E     0     7     0


일반적인 사용시 NaN은 계산에서 제외되어 인덱스에 표시되지 않은것을 확인할 수 있습니다.

print(df.groupby('index').sum())
>>
       col1  col2  col3
index                  
A         7     6     9
B         5     9    17
C         2     5    13
D        13    16    19
E         2    19    13


dropna=False인 경우 인덱스에 NaN이 포함되어 계산된 것을 알 수 있습니다.

print(df.groupby('index',dropna=False).sum())
>>
       col1  col2  col3
index                  
A         7     6     9
B         5     9    17
C         2     5    13
D        13    16    19
E         2    19    13
NaN       8     4     1 # NaN이 표시됩니다.



level인수의 사용 (Multi Index)
Multi Index의 경우 level을 숫자나 str 형태로 지정해주어 groupby를 실행할 수 있습니다.
먼저 Multi Index 객체를 생성해보겠습니다.

idx = [['idx1','idx1','idx2','idx2','idx2'],['row1','row2','row1','row2','row3']]
col = ['col1','col2','col2']
data = np.random.randint(0,9,(5,3))
df = pd.DataFrame(data=data, index = idx, columns = col).rename_axis(index=['lv0','lv1'])
print(df)
>>
           col1  col2  col2
lv0  lv1                   
idx1 row1     7     3     7
     row2     2     1     6
idx2 row1     1     7     2
     row2     3     5     7
     row3     5     1     8


level을 int로 지정해주는 경우

print(df.groupby(level=1).sum())
>>
      col1  col2  col2
lv1                   
row1     8    10     9
row2     5     6    13
row3     5     1     8


level을 str로 지정해주는경우 + (여러개 지정시 순차적으로 groupby 됩니다.)

print(df.groupby(['lv1','lv0']).sum())
>>
           col1  col2  col2
lv1  lv0                   
row1 idx1     7     3     7
     idx2     1     7     2
row2 idx1     2     1     6
     idx2     3     5     7
row3 idx2     5     1     8
반응형

+ 최근 글