우선 데이터를 생성하겠습니다.
df = pd.DataFrame({'key1' : ['a', 'a', 'b', 'b', 'a'],
'key2' : ['one', 'two', 'one', 'two', 'one'],
'data1' : np.random.randn(5),
'data2' : np.random.randn(5)})
df
key1 key2 data1 data2
0 a one -0.204708 1.393406
1 a two 0.478943 0.092908
2 b one -0.519439 0.281746
3 b two -0.555730 0.769023
4 a one 1.965781 1.246435
이때 data1열을 key1을 기준으로 그룹으로 묶겠습니다.
grouped = df['data1'].groupby(df['key1'])
grouped
<pandas.core.groupby.generic.SeriesGroupBy object at 0x000002296478CB20>
이때 생성되는 것은 groupby 객체이므로 이렇게 나옵니다.
하지만 여기서 groupby 메소드를 사용하여 연산을 할 수 있습니다.
grouped.mean()
key1
a 0.746672
b -0.537585
Name: data1, dtype: float64
또한 두 가지 열을 기준으로 그룹을 묶을 수 있습니다.
means = df['data1'].groupby([df['key1'], df['key2']]).mean()
means
key1 key2
a one 0.880536
two 0.478943
b one -0.519439
two -0.555730
Name: data1, dtype: float64
만약 이를 unstack() 한다면,
means.unstack()
key2 one two
key1
a 0.880536 0.478943
b -0.519439 -0.555730
이렇게 이름을 지정할 수도 있겠네요
states = np.array(['Ohio', 'California', 'California', 'Ohio', 'Ohio'])
years = np.array([2005, 2005, 2006, 2005, 2006])
df['data1'].groupby([states, years]).mean()
California 2005 0.478943
2006 -0.519439
Ohio 2005 -0.380219
2006 1.965781
Name: data1, dtype: float64
이런 식으로도 그룹화 할 수 있습니다.
df.groupby('key1').mean()
data1 data2
key1
a 0.746672 0.910916
b -0.537585 0.525384
df.groupby(['key1', 'key2']).mean()
data1 data2
key1 key2
a one 0.880536 1.319920
two 0.478943 0.092908
b one -0.519439 0.281746
two -0.555730 0.769023
df.groupby(['key1', 'key2']).size()
key1 key2
a one 2
two 1
b one 1
two 1
dtype: int64
Iterating Over Groups
for name, group in df.groupby('key1'):
print(name)
print(group)
a
key1 key2 data1 data2
0 a one -0.204708 1.393406
1 a two 0.478943 0.092908
4 a one 1.965781 1.246435
b
key1 key2 data1 data2
2 b one -0.519439 0.281746
3 b two -0.555730 0.769023
key1을 기준으로 그룹화 한 내용을 반복하여 출력할 수도 있습니다.
이때 key1, key2를 기준으로도 반복문을 사용할 수 있습니다.
for (k1, k2), group in df.groupby(['key1', 'key2']):
print((k1, k2))
print(group)
('a', 'one')
key1 key2 data1 data2
0 a one -0.204708 1.393406
4 a one 1.965781 1.246435
('a', 'two')
key1 key2 data1 data2
1 a two 0.478943 0.092908
('b', 'one')
key1 key2 data1 data2
2 b one -0.519439 0.281746
('b', 'two')
key1 key2 data1 data2
3 b two -0.55573 0.769023
이때 딕셔너리로도 나타낼 수 있습니다.
pieces = dict(list(df.groupby('key1')))
pieces['b']
key1 key2 data1 data2
2 b one -0.519439 0.281746
3 b two -0.555730 0.769023
df의 타입을 알아봅시다.
df.dtypes
key1 object
key2 object
data1 float64
data2 float64
dtype: object
이때 타입에 따라서 그룹화 할 수 있습니다.
grouped = df.groupby(df.dtypes, axis=1)
for dtype, group in grouped:
print(dtype)
print(group)
float64
data weights
0 1.561587 0.957515
1 1.219984 0.347267
2 -0.482239 0.581362
3 0.315667 0.217091
4 -0.047852 0.894406
5 -0.454145 0.918564
6 -0.556774 0.277825
7 0.253321 0.955905
object
category
0 a
1 a
2 a
3 a
4 b
5 b
6 b
7 b
Selecting a Column or Subset of Columns
key1, key2를 기준으로 그룹화한 다음에 data2에 해당하는 컬럼의 평균을 구했습니다.
df.groupby(['key1', 'key2'])[['data2']].mean()
data2
key1 key2
a one 1.319920
two 0.092908
b one 0.281746
two 0.769023
따로 처리할 수도 있습니다.
s_grouped = df.groupby(['key1', 'key2'])['data2']
s_grouped.mean()
key1 key2
a one 1.319920
two 0.092908
b one 0.281746
two 0.769023
Name: data2, dtype: float64
Grouping with Dicts and Series
우선 데이터를 생성해봅시다.
people = pd.DataFrame(np.random.randn(5, 5),
columns=['a', 'b', 'c', 'd', 'e'],
index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis'])
people.iloc[2:3, [1, 2]] = np.nan # Add a few NA values
people
a b c d e
Joe 1.007189 -1.296221 0.274992 0.228913 1.352917
Steve 0.886429 -2.001637 -0.371843 1.669025 -0.438570
Wes -0.539741 NaN NaN -1.021228 -0.577087
Jim 0.124121 0.302614 0.523772 0.000940 1.343810
Travis -0.713544 -0.831154 -2.370232 -1.860761 -0.860757
그리고 mapping하기 위해 딕셔너리를 하나 만듭시다.
mapping = {'a': 'red', 'b': 'red', 'c': 'blue',
'd': 'blue', 'e': 'red', 'f' : 'orange'}
by_column = people.groupby(mapping, axis=1)
by_column.sum()
blue red
Joe 0.503905 1.063885
Steve 1.297183 -1.553778
Wes -1.021228 -1.116829
Jim 0.524712 1.770545
Travis -4.230992 -2.405455
매핑하여 그룹화했습니다. 이때는 열을 기준으로 그룹화했네요
이렇게 딕셔너리를 Series로 만들어서도 할 수 있습니다.
map_series = pd.Series(mapping)
map_series
people.groupby(map_series, axis=1).count()
blue red
Joe 2 3
Steve 2 3
Wes 1 2
Jim 2 3
Travis 2 3
Grouping with Functions
이름의 길이를 기준으로 그룹화해보겠습니다.
people.groupby(len).sum()
a b c d e
3 0.591569 -0.993608 0.798764 -0.791374 2.119639
5 0.886429 -2.001637 -0.371843 1.669025 -0.438570
6 -0.713544 -0.831154 -2.370232 -1.860761 -0.860757
이때,
key_list = ['one', 'one', 'one', 'two', 'two']
people.groupby([len, key_list]).min()
a b c d e
3 one -0.539741 -1.296221 0.274992 -1.021228 -0.577087
two 0.124121 0.302614 0.523772 0.000940 1.343810
5 one 0.886429 -2.001637 -0.371843 1.669025 -0.438570
6 two -0.713544 -0.831154 -2.370232 -1.860761 -0.860757
내부적으로 알아서 변환돼서 들어가기 때문에, 이름이 3글자인 데이터 중 두 개가 one one이므로 이런 결과가 나옵니다.
Grouping by Index Levels
columns = pd.MultiIndex.from_arrays([['US', 'US', 'US', 'JP', 'JP'],
[1, 3, 5, 1, 3]],
names=['cty', 'tenor'])
hier_df = pd.DataFrame(np.random.randn(4, 5), columns=columns)
hier_df
cty US JP
tenor 1 3 5 1 3
0 0.560145 -1.265934 0.119827 -1.063512 0.332883
1 -2.359419 -0.199543 -1.541996 -0.970736 -1.307030
2 0.286350 0.377984 -0.753887 0.331286 1.349742
3 0.069877 0.246674 -0.011862 1.004812 1.327195
hier_df.groupby(level='cty', axis=1).count()
cty JP US
0 2 3
1 2 3
2 2 3
3 2 3
인덱스 레벨로 그룹화할 수 있습니다.