22. pandas 추가 – 데이터 그룹화 함수 이해하기
Series를 데이터 그룹화(groupby)하기
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)})
위 DataFrame에 key1과 key2에는 중복된 값이 있는 것을 확인할 수 있다.
이 때, key1열이 a인 행들에 대해, data1의 평균을 구하고 싶다고 가정하자.
(이전까지는 key1의 유니크한 값으로 마스크 –> 반복문 (df.loc( 마스크, data1열)) 을 통해 평균을 계산했었다. 하지만, 데이터 그룹화를 통해 더 쉽게 할 수 있다)
데이터 그룹화를 하기 위해서는, Series나 DataFrame에 groupby()함수를 실행할 수 있다.
- 통계량을 계산할 열(Series) . groupby( 기준이 될 열(Series) ) 형식으로 실행하게 되는데,
grouped = df["data1"].groupby( df["key1"])를 통해
key1열을 데이터그룹화를 한 다음, data1열의 통계량을 계산할 준비를 한다.
값을 확인할 수 없는 이유는 , key1열을 기준으로 data1열을 그룹화만 했을 뿐이며, 통계함수는 사용하지 않았기 때문이다.
grouped에는 ket1의 값인 a를 포함하는 행과 b를 포함하는 행을 각각 그룹화하여 동시에 가지고 있다. - 이렇게 그룹화까지만 된 것인 grouped 를 이용해서, 통계함수로 통계량을 계산한다.
grouped.mean()
이러한 groupby()함수의 절차를 [ split – apply – combine ] 이라고 한다.
기준열을 지정하여 특정열을 그룹별로 나누고 – 각 그룹에 통계함수를 적용하고 – 최종적인 통계량이 산출된 것은 통합해서 표시해주기 때문이다.
(my : groupby로 데이터를 그룹화 했으면, 반드시 통계함수를 적용시켜야하는구나. 통계량 구할라고 하는 거구나!)
이제 그룹화의 기준이 될 열을 2개 이상 지정할 수도 있다. 2개 열의 성분이 모두 같은 것만 하나의 그룹이 된다.
이 때, 그룹화의 기준열이 2개이면, 계층적 인덱스로 적용된 Series가 나온다.
- means = df["data1"].groupby( [ df["key1"], df["key2"]]).mean() 를 통해, 기준열2개로 data1열을 그룹화 후 평균까지 구하자.
나온 결과에서, 기준열이 2개면, 계층적 인덱스가 적용된 Series가 나온다.
이 때, unstactk()함수를 적용해서 최하위 인덱스를 칼럼으로 올린 뒤, 데이터를 분석해도 된다.
DataFrame을 데이터그룹화(groupby)하기
지금까지는 데이터 그룹화(groupby)를 적용시키는 것에 특정열 1개를 Series로 주었는데,
DataFrame에 대해서도 groupby()를 적용시킬 수 있다.
Series에서 했던 것과는 방식이 조금 달라진다.
- Series 의 데이터 그룹화 : 특정열인덱싱.groupby ( 기준열인덱싱 )
- DataFrame의 데이터 그룹화 : df . groupby ( “기준이 될 컬럼명”) 를 통해 특정열이 아닌, df의 모든 열에 대해서 통계량이 계산된다.
- df.groupby("key1").mean() 를 적용시켜보자.
- df.groupby("key1").count() 를 통해, 각 key1열의 값을 가지는 행들의 갯수를 세서 산출해줄 수 있다.
- 2개의 열을 기준으로 할 수도 있다. 마찬가지로 인자에, 리스트형식으로 칼럼명을 넣어준다.
DataFrame을 데이터 그룹화 해서, 특정열x 전체 열을 그룹화 하더라도, 특정열에 대한 통계량만 산출할 수 도 있다.
그룹화결과물에, 통계함수를 적용하기 전에 [ “컬럼명”]으로 뽑아내면된다.
반복문을 이용하여, 그룹화 직후의 결과물 확인해보기(통계함수 적용하기전에)
그룹화를 수행한 직후의 결과물을 확인할 수 없었으나, 반복문을 통해 그룹화에 대한 결과물 확인이 가능하다.
key1 이라는 열에 대해, name, group이라 2변수로 매 반복문마다 값을 받아서, 각각의 print해보자.
- for name, group in df.groupby("key1") :
print(name)
print(group)
key1이라는 열의 각 성분 별로 그룹화를 시켰는데,
name이라는 변수에는 각 그룹으로 나뉘는 기준열의 성분이 들어가서 출력되며, group에서는 기준성분을 포함하는 행들을, 모든 열별로 출력이 된다.
만약 기준열이 2개라면, name변수 자리에 소괄호()를 이용해서 2개의 변수에 각 기준열의 성분을 받아야한다.
딕셔너리를 이용해서 그룹화 직후의 결과물 보기
df.groupby( “key1”)의 결과물은 2개의 변수로 받을 수 있었다.
이것을 list()함수를 씌워서, 순서대로 짤라서 넣게 되고, dict()함수를 이용해서 딕셔너리 형태로 담는다.
이 때, 그룹화된 결과물에 list()함수를 입히면, list의 형태가 [ ( 성분1, group1) , (성분2, group2) , … ]형태로 담길 것이다.
이것을 dict()함수를 이용하면 { 성분1 : group1, 성분2 : group2 }의 딕셔너리 형태로 넣을 수 있는 것이다.
(my : 아! name , group을 한번에 딕셔너리에 담을 수 없어서 그룹화결과물 –> list로 쪼개어 담기 – >dictionary에 한꺼번에 담아주기 )
- pieces = dict ( list( df.groupby("key1") ) ) 를 통해, 그룹화결과물을 딕셔너리의 형태로 살펴보자.
{ a라는 키값 : 그룹화된 결과물 } 형태로 나타난다. - 이것을 딕셔너리 열인덱싱(키 인덱싱) 하여 b에 대한 그룹화 결과물만 볼 수 있다.
pieces["b"]
기준열 대신 별로도 정의된 Series나 딕셔너리를 이용하여, 매핑 & 데이터 그룹화
df2 = pd.DataFrame(np.random.randn(5, 5),
columns=['a', 'b', 'c', 'd', 'e'],
index=['Joe', 'Steve', 'Wes', 'Jim', 'Travis'])
5 x 5 DataFrame이 있는 상태에서, df2의 컬럼(a,b,c,d,e)를 다른 값으로 매핑하기 위한 딕셔너리를 생성할 것이다.
딕셔너리의 {키값 = 매핑시킬 칼럼들 : 밸류값 = 매핑할 더 작은 종류의 값들} 형태로 만들어야한다.
(21강에서는 특정열의 성분들을 매핑해서, 더 적은 수의 성분들로 치환했었다. 이 때, m to n 딕셔너러+ apply()함수가 이용됬었음
키값 : 특정열의성분들 –> 밸류값 : 매핑할 더 작은 종류의 값들)
map_dict = {'a': 'red', 'b': 'red', 'c': 'blue',
'd': 'blue', 'e': 'red', 'f' : 'orange'}
이제 groupby를 통화 그룹화를 할 때, 기준이 되는 인자에 딕셔너리를 넣고, axis를 1로 주어, 열 방향(→)으로 지정하여
(위에서 특정열에 대한 성분을 기준으로, 그 값을 포함하는 <index(행들)>를 그룹화 했던 것과는 다르게,)
컬럼들을 그룹화한다. 이 때, 딕셔너리의 키값을 가진 컬럼들이, 밸류값들로 더 작게 매핑되서 컬럼들을 그룹화 한다.
(axis 인자를 안 주었을 때는, 기준열의 성분을 포함하는 행들을, 그룹화하였고
딕셔너리로 매핑 + aixs =1을 준 경우에는, 해당 매핑값을 기준으로 해당 값에 속하는 칼럼들을 모아놓는다.
- dict( list( df2.groupby(map_dict, axis=1) ) ) 를 통해,
axis=1으로 컬럼들을 그룹화 할 것이고, 딕셔너리를 통해 매핑하면서 그룹화한다.
그룹화된 결과물을 보기 위해서, list로 쪼개고, 딕셔너리에 담았다. - 그룹화결과물을 바로 보지 말고, 통계함수를 적용해서 합계를 보자.
df2.groupby(map_dict, axis=1).sum()
a부터 e의 열을 red, blue로 매핑한 뒤, 각 red, blue에 해당하는 칼럼들을 그룹화하고 나서, 합을 구한 것이다.
Series를 가지고 매핑 한뒤, 그룹화 할 수 있다. 위에서 사용한 딕셔너리를 이용해서, Series를 만들어서 해보자.
map_s = pd.Series(map_dict)
- df2.groupby(map_s, axis=1).count() 를 통해, 딕셔너리와 마찬가지로, 첫번째 인자에 Series를 넣고 axis=1로 준다.
.count()를 통해 그룹화된 열의 갯수를 확인할 수 있다.
이렇게 그룹화된 데이터에 적용할 수 있는 통계함수는 아래와 같다.
데이터 그룹화 결과물에 통계함수가 아닌, 사용자 정의 함수 적용하기
데이터 그룹화를 통해 얻어진 결과물에, 통계함수 외 사용자 정의함수를 적용할 수 도 있다.
먼저, df의 key1열을 기준으로 데이터그룹화 시켜놓고 변수에 저장한 뒤, 함수를 새로 정의할 것이다.
peak_to_peak()함수를 정의하는데, 받은 array의 < 각 열>마다 최대값 – 최소값을 반환하는 함수다.
grouped = df.groupby("key1")
def peak_to_peak(arr):
return arr.max() - arr.min()
그룹화된 결과물에 agg()함수를 적용하게 되면, 그룹화된 각 그룹마다 사용자 정의함수(각 열의 최소-최대)를 적용할 수 있게 해준다.
데이터 그룹화의 결과물에 .agg()를 이용해서, 일반적인 통계함수도 적용시킬 수 있다.
이 때, 인자에 “문자열”로 해당 함수를 호출하게 된다.
그룹화된 결과물에 대한 전체 통계량 보기
그룹화된 결과물에 .describe()를 통해 전체 통계량을 확인할 수 있다.
'빅데이터 관련 프로그래밍 > Python - bigdata(pandas 기초)' 카테고리의 다른 글
참고 : pandas 추가 - 데이터분석3 요약 정리 (0) | 2018.03.11 |
---|---|
23. pandas 추가 – 데이터 분석 by 그룹화 +피벗 테이블(pivot_table) (0) | 2018.03.06 |
21. pandas 추가 – DataFrame 데이터 변형(중복행 제거/ 매핑/ 치환/ 카테고리 자료형) (1) | 2018.03.03 |
20. pandas 추가 – 계층적 인덱싱(정렬함수, 통계함수적용, 인덱스와 칼럼 전환(stack,unstack)) (3) | 2018.03.02 |
19. pandas 추가 – 데이터 합치기 2가지 방식(merging, concatenating) (1) | 2018.03.01 |