Python Library/Pandas

[Pandas - Python] GroupBy Mechanics - groupby() (그룹으로 묶기)

바보1 2022. 6. 15. 22:57

우선 데이터를 생성하겠습니다.

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

인덱스 레벨로 그룹화할 수 있습니다.