import pandas as pd
import numpy as np
07wk-2: Pandas – pivot_table
, groupby
+agg
1. 강의영상
2. Imports
3. pivot_table, groupby+agg
A. intro
-
개념: 그룹화 \(\to\) 집계
# 예제1
: 아래의 예제에서 (학과,성별)로 count의 합계를 구하라.
=pd.read_csv("https://raw.githubusercontent.com/guebin/DV2022/master/posts/Simpson.csv",index_col=0,header=[0,1])\
df\
.stack().stack().reset_index()'level_0':'department','level_1':'result','level_2':'gender',0:'count'},axis=1)
.rename({ df
department | result | gender | count | |
---|---|---|---|---|
0 | A | fail | male | 314 |
1 | A | fail | female | 19 |
2 | A | pass | male | 511 |
3 | A | pass | female | 89 |
4 | B | fail | male | 208 |
5 | B | fail | female | 7 |
6 | B | pass | male | 352 |
7 | B | pass | female | 18 |
8 | C | fail | male | 204 |
9 | C | fail | female | 391 |
10 | C | pass | male | 121 |
11 | C | pass | female | 202 |
12 | D | fail | male | 279 |
13 | D | fail | female | 244 |
14 | D | pass | male | 138 |
15 | D | pass | female | 131 |
16 | E | fail | male | 137 |
17 | E | fail | female | 299 |
18 | E | pass | male | 54 |
19 | E | pass | female | 94 |
20 | F | fail | male | 149 |
21 | F | fail | female | 103 |
22 | F | pass | male | 224 |
23 | F | pass | female | 238 |
=['department','gender'],values='count',aggfunc='sum') df.pivot_table(index
count | ||
---|---|---|
department | gender | |
A | female | 108 |
male | 825 | |
B | female | 25 |
male | 560 | |
C | female | 593 |
male | 325 | |
D | female | 375 |
male | 417 | |
E | female | 393 |
male | 191 | |
F | female | 341 |
male | 373 |
#
-
예시에서 본 작업은 아래의 작업들로 세분화 할 수 있다.
- 그룹화(쿼리): 하나의 dataframe을 sub-dataframe으로 나누는 과정 – 전체자료를 (학과,성별)로 묶어 총 10개의 sub-dataframe을 만듦
- 각각집계(각각계산): 나누어진 sub-dataframe에서 어떠한 계산을 각각 수행함. – 나누어진 sub-dataframe에서 지원자수의 합계를 각각 구함
-
위의 같은 작업을 하려면 아래와 같은 요소들이 필요하다.
- 그룹변수1 – 그룹화를 위해 필요한 변수, dataframe을 sub-dataframe으로 나누는 역할.
- 집계변수2 – 집계함수의 대상이 되는 변수.
- 집계변수 – 그룹화된 데이터프레임에 수행하는 계산을 정의하는 함수.
1 이건 없는 용어에요
2 이것도 없는 용어에요
B. pivot_table
의 문법
-
pivot_table의 문법
df.pivot_table(= 그룹변수
index = 그룹변수
colums = 집계변수
values = 집계함수
aggfunc )
-
그룹변수: string, 혹은 list of string 으로 전달한다.
- 예시: ‘department’, [‘department’], [‘department’,‘gender’]
-
집계변수: string, 혹은 list of string 으로 전달한다.
- 예시: ‘CANCELLED’, [‘CANCELLED’], [‘CANCELLED’,‘AIR_TIME’]
-
집계함수: 함수자체3를 전달하거나, 함수를 의미하는 문자열4, 혹은 그것들의 리스트형태로 전달한다.
3 np.mean
,sum
4 ‘count’, ‘sum’, ‘mean’, ‘median’, ‘min’, ‘max’, ‘std’, ‘var’
# 예시
: 집계합수를 전달하는 방법
data
= pd.DataFrame({'category':['A']*5+['B']*5, 'value':np.concatenate([np.random.randn(5), np.random.randn(5)+10])})
df df
category | value | |
---|---|---|
0 | A | -1.522629 |
1 | A | 0.525883 |
2 | A | 0.285563 |
3 | A | -1.219968 |
4 | A | 1.523162 |
5 | B | 9.942545 |
6 | B | 10.811401 |
7 | B | 9.817500 |
8 | B | 10.062780 |
9 | B | 11.450590 |
방법1 – 함수자체를 전달
=['category'],values='value',aggfunc=np.sum) # 함수자체 df.pivot_table(index
/tmp/ipykernel_3437616/3923531937.py:1: FutureWarning: The provided callable <function sum at 0x7f2bb810b1c0> is currently using DataFrameGroupBy.sum. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string "sum" instead.
df.pivot_table(index=['category'],values='value',aggfunc=np.sum) # 함수자체
value | |
---|---|
category | |
A | -0.407990 |
B | 52.084817 |
방법2 – 함수를 의미하는 문자열을 전달
=['category'],values='value',aggfunc='sum') # 리스트 df.pivot_table(index
value | |
---|---|
category | |
A | -0.407990 |
B | 52.084817 |
방법3 – 리스트를 전달
df.pivot_table(=['category'],
index='value',
values=['sum','min',np.mean,np.max,'count']
aggfunc )
/tmp/ipykernel_3437616/1880687379.py:1: FutureWarning: The provided callable <function mean at 0x7f2bb8110670> is currently using DataFrameGroupBy.mean. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string "mean" instead.
df.pivot_table(
/tmp/ipykernel_3437616/1880687379.py:1: FutureWarning: The provided callable <function amax at 0x7f2bb810ba30> is currently using DataFrameGroupBy.max. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string "max" instead.
df.pivot_table(
sum | min | mean | amax | count | |
---|---|---|---|---|---|
value | value | value | value | value | |
category | |||||
A | -0.407990 | -1.522629 | -0.081598 | 1.523162 | 5 |
B | 52.084817 | 9.817500 | 10.416963 | 11.450590 | 5 |
C. groupby
+ aggregate
의 문법
-
groupby + aggregate 의 문법
df.groupby(그룹변수).aggregate({집계변수:집계함수})
4. AIRLINE 자료로 연습
=pd.read_csv('https://raw.githubusercontent.com/PacktPublishing/Pandas-Cookbook/master/data/flights.csv')
df df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 58492 entries, 0 to 58491
Data columns (total 14 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 MONTH 58492 non-null int64
1 DAY 58492 non-null int64
2 WEEKDAY 58492 non-null int64
3 AIRLINE 58492 non-null object
4 ORG_AIR 58492 non-null object
5 DEST_AIR 58492 non-null object
6 SCHED_DEP 58492 non-null int64
7 DEP_DELAY 57659 non-null float64
8 AIR_TIME 57474 non-null float64
9 DIST 58492 non-null int64
10 SCHED_ARR 58492 non-null int64
11 ARR_DELAY 57474 non-null float64
12 DIVERTED 58492 non-null int64
13 CANCELLED 58492 non-null int64
dtypes: float64(3), int64(8), object(3)
memory usage: 6.2+ MB
-
각 변수들에 대한 설명은 아래와 같다. (ChatGPT의 도움을 받아 정리함)
MONTH
: 비행이 이루어진 월을 나타냄. 1에서 12 사이의 값을 갖음.DAY
: 비행이 이루어진 일자를 나타냄. 월에 따라 1~28/29/30/31 사이의 값을 가질 수 있음.WEEKDAY
: 비행이 이루어진 요일을 나타냄. 일반적으로 1(일요일)부터 7(토요일)까지의 값을 갖음.AIRLINE
: 해당 항공편을 운영하는 항공사의 약어나 코드를 나타냄.ORG_AIR
: 비행기가 출발하는 공항의 약어나 코드를 나타냄.DEST_AIR
: 비행기가 도착하는 공항의 약어나 코드를 나타냄.SCHED_DEP
: 원래의 예정된 출발 시간을 나타냄. 시간은 일반적으로 HHMM 형식으로 표시될 수 있음.DEP_DELAY
: 출발 지연 시간을 나타냄. 음수 값은 조기 출발, 양수 값은 지연을 의미함.AIR_TIME
: 실제 공중에서 비행한 시간을 분 단위로 나타냄.DIST
: 비행 거리를 나타냄. 일반적으로 마일 또는 킬로미터로 표시됨.SCHED_ARR
: 원래의 예정된 도착 시간을 나타냄.SCHED_DEP
와 같은 형식으로 표시될 수 있음.ARR_DELAY
: 도착 지연 시간을 나타냄. 음수는 조기 도착, 양수는 지연을 의미함.DIVERTED
: 항공편이 다른 곳으로 우회되었는지를 나타냄. 1은 우회, 0은 정상 경로를 의미함.CANCELLED
: 항공편이 취소되었는지 여부를 나타냄. 1은 취소, 0은 취소되지 않음을 의미함.
# 예제1
: 항공사별로 도착지연시간의 평균을 구하라.
-
풀이1
='AIRLINE',values='ARR_DELAY') df.pivot_table(index
ARR_DELAY | |
---|---|
AIRLINE | |
AA | 5.542661 |
AS | -0.833333 |
B6 | 8.692593 |
DL | 0.339691 |
EV | 7.034580 |
F9 | 13.630651 |
HA | 4.972973 |
MQ | 6.860591 |
NK | 18.436070 |
OO | 7.593463 |
UA | 7.765755 |
US | 1.681105 |
VX | 5.348884 |
WN | 6.397353 |
-
풀이2
="AIRLINE").aggregate({'ARR_DELAY':np.mean}) df.groupby(by
/tmp/ipykernel_3437616/4188396604.py:1: FutureWarning: The provided callable <function mean at 0x7f2bb8110670> is currently using SeriesGroupBy.mean. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string "mean" instead.
df.groupby(by="AIRLINE").aggregate({'ARR_DELAY':np.mean})
ARR_DELAY | |
---|---|
AIRLINE | |
AA | 5.542661 |
AS | -0.833333 |
B6 | 8.692593 |
DL | 0.339691 |
EV | 7.034580 |
F9 | 13.630651 |
HA | 4.972973 |
MQ | 6.860591 |
NK | 18.436070 |
OO | 7.593463 |
UA | 7.765755 |
US | 1.681105 |
VX | 5.348884 |
WN | 6.397353 |
#
# 예제2
: 항공사별로 비행취소건수의 합계를 구하라. 취소건수가 높은 항공사순으로 정렬하라.
-
풀이1: .pivot_table()
을 이용
='AIRLINE',values='CANCELLED',aggfunc='sum').sort_values('CANCELLED',ascending=False) df.pivot_table(index
CANCELLED | |
---|---|
AIRLINE | |
AA | 154 |
MQ | 152 |
EV | 146 |
OO | 142 |
UA | 93 |
WN | 93 |
DL | 38 |
NK | 25 |
US | 21 |
F9 | 10 |
VX | 6 |
B6 | 1 |
AS | 0 |
HA | 0 |
-
풀이2: .groupby()
+.aggregate()
를 이용
'AIRLINE').aggregate({'CANCELLED':'sum'}).sort_values('CANCELLED',ascending=False) df.groupby(
CANCELLED | |
---|---|
AIRLINE | |
AA | 154 |
MQ | 152 |
EV | 146 |
OO | 142 |
UA | 93 |
WN | 93 |
DL | 38 |
NK | 25 |
US | 21 |
F9 | 10 |
VX | 6 |
B6 | 1 |
AS | 0 |
HA | 0 |
# 예제3
: 항공사별로 비행취소율을 구하라. 비행취소율이 가장 높은 항공사 순으로 정렬하라.
-
풀이1: .pivot_table()
을 이용
='AIRLINE',values='CANCELLED',aggfunc='mean').sort_values('CANCELLED',ascending=False) df.pivot_table(index
CANCELLED | |
---|---|
AIRLINE | |
MQ | 0.043791 |
EV | 0.024923 |
OO | 0.021554 |
AA | 0.017303 |
NK | 0.016491 |
US | 0.013003 |
UA | 0.011935 |
WN | 0.011048 |
F9 | 0.007593 |
VX | 0.006042 |
DL | 0.003585 |
B6 | 0.001842 |
AS | 0.000000 |
HA | 0.000000 |
-
풀이2: .groupby()
+.aggregate()
를 이용
'AIRLINE').aggregate({'CANCELLED':'mean'}).sort_values('CANCELLED',ascending=False) df.groupby(
CANCELLED | |
---|---|
AIRLINE | |
MQ | 0.043791 |
EV | 0.024923 |
OO | 0.021554 |
AA | 0.017303 |
NK | 0.016491 |
US | 0.013003 |
UA | 0.011935 |
WN | 0.011048 |
F9 | 0.007593 |
VX | 0.006042 |
DL | 0.003585 |
B6 | 0.001842 |
AS | 0.000000 |
HA | 0.000000 |
# 예제4
(항공사,요일)별 비행취소건수와 비행취소율을 조사하라.
-
풀이1: .pivot_table()
을 이용
=['AIRLINE','WEEKDAY'],values='CANCELLED',aggfunc=[np.mean,sum]) df.pivot_table(index
/tmp/ipykernel_3437616/757677508.py:1: FutureWarning: The provided callable <function mean at 0x7f2bb8110670> is currently using DataFrameGroupBy.mean. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string "mean" instead.
df.pivot_table(index=['AIRLINE','WEEKDAY'],values='CANCELLED',aggfunc=[np.mean,sum])
/tmp/ipykernel_3437616/757677508.py:1: FutureWarning: The provided callable <built-in function sum> is currently using DataFrameGroupBy.sum. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string "sum" instead.
df.pivot_table(index=['AIRLINE','WEEKDAY'],values='CANCELLED',aggfunc=[np.mean,sum])
mean | sum | ||
---|---|---|---|
CANCELLED | CANCELLED | ||
AIRLINE | WEEKDAY | ||
AA | 1 | 0.032106 | 41 |
2 | 0.007341 | 9 | |
3 | 0.011949 | 16 | |
4 | 0.015004 | 20 | |
5 | 0.014151 | 18 | |
... | ... | ... | ... |
WN | 3 | 0.014118 | 18 |
4 | 0.007911 | 10 | |
5 | 0.005828 | 7 | |
6 | 0.010132 | 10 | |
7 | 0.006066 | 7 |
98 rows × 2 columns
-
풀이2: .groupby()
+.aggregate()
를 이용
'AIRLINE','WEEKDAY']).aggregate({'CANCELLED':[np.mean,sum]}) df.groupby([
/tmp/ipykernel_3437616/1354178761.py:1: FutureWarning: The provided callable <function mean at 0x7f2bb8110670> is currently using SeriesGroupBy.mean. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string "mean" instead.
df.groupby(['AIRLINE','WEEKDAY']).aggregate({'CANCELLED':[np.mean,sum]})
/tmp/ipykernel_3437616/1354178761.py:1: FutureWarning: The provided callable <built-in function sum> is currently using SeriesGroupBy.sum. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string "sum" instead.
df.groupby(['AIRLINE','WEEKDAY']).aggregate({'CANCELLED':[np.mean,sum]})
CANCELLED | |||
---|---|---|---|
mean | sum | ||
AIRLINE | WEEKDAY | ||
AA | 1 | 0.032106 | 41 |
2 | 0.007341 | 9 | |
3 | 0.011949 | 16 | |
4 | 0.015004 | 20 | |
5 | 0.014151 | 18 | |
... | ... | ... | ... |
WN | 3 | 0.014118 | 18 |
4 | 0.007911 | 10 | |
5 | 0.005828 | 7 | |
6 | 0.010132 | 10 | |
7 | 0.006066 | 7 |
98 rows × 2 columns
# 예제4
: (항공사,요일)별로 CANCELLED
는 평균과 합계를 구하고 (즉 비행취소건수와 취소율을 구하고), AIR_TIME
은 평균과 표준편차를 구하여라.
-
풀이1: .pivot_table()
–> 이거 제가 수업할때는 못한다고 했는데 찾아보니까 아래처럼 할 수 있습니다.
df.pivot_table(=['AIRLINE', 'WEEKDAY'],
index={'CANCELLED': [np.mean, sum], 'AIR_TIME': ['mean','std']}
aggfunc )
/tmp/ipykernel_3437616/2860571331.py:1: FutureWarning: The provided callable <function mean at 0x7f2bb8110670> is currently using SeriesGroupBy.mean. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string "mean" instead.
df.pivot_table(
/tmp/ipykernel_3437616/2860571331.py:1: FutureWarning: The provided callable <built-in function sum> is currently using SeriesGroupBy.sum. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string "sum" instead.
df.pivot_table(
AIR_TIME | CANCELLED | ||||
---|---|---|---|---|---|
mean | std | mean | sum | ||
AIRLINE | WEEKDAY | ||||
AA | 1 | 147.610569 | 73.442540 | 0.032106 | 41 |
2 | 143.851852 | 73.211275 | 0.007341 | 9 | |
3 | 144.514005 | 73.340675 | 0.011949 | 16 | |
4 | 141.124618 | 69.220840 | 0.015004 | 20 | |
5 | 145.430966 | 76.711095 | 0.014151 | 18 | |
... | ... | ... | ... | ... | ... |
WN | 3 | 104.219920 | 53.869040 | 0.014118 | 18 |
4 | 107.200800 | 54.466218 | 0.007911 | 10 | |
5 | 107.893635 | 57.172695 | 0.005828 | 7 | |
6 | 109.247433 | 56.149388 | 0.010132 | 10 | |
7 | 107.602273 | 56.419207 | 0.006066 | 7 |
98 rows × 4 columns
-
풀이2: .groupby()
+.aggregate()
를 이용
'AIRLINE','WEEKDAY'])\
df.groupby(['CANCELLED': [np.mean,sum],'AIR_TIME': ['mean','std']}) .aggregate({
/tmp/ipykernel_3437616/2787668343.py:2: FutureWarning: The provided callable <function mean at 0x7f2bb8110670> is currently using SeriesGroupBy.mean. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string "mean" instead.
.aggregate({'CANCELLED': [np.mean,sum],'AIR_TIME': ['mean','std']})
/tmp/ipykernel_3437616/2787668343.py:2: FutureWarning: The provided callable <built-in function sum> is currently using SeriesGroupBy.sum. In a future version of pandas, the provided callable will be used directly. To keep current behavior pass the string "sum" instead.
.aggregate({'CANCELLED': [np.mean,sum],'AIR_TIME': ['mean','std']})
CANCELLED | AIR_TIME | ||||
---|---|---|---|---|---|
mean | sum | mean | std | ||
AIRLINE | WEEKDAY | ||||
AA | 1 | 0.032106 | 41 | 147.610569 | 73.442540 |
2 | 0.007341 | 9 | 143.851852 | 73.211275 | |
3 | 0.011949 | 16 | 144.514005 | 73.340675 | |
4 | 0.015004 | 20 | 141.124618 | 69.220840 | |
5 | 0.014151 | 18 | 145.430966 | 76.711095 | |
... | ... | ... | ... | ... | ... |
WN | 3 | 0.014118 | 18 | 104.219920 | 53.869040 |
4 | 0.007911 | 10 | 107.200800 | 54.466218 | |
5 | 0.005828 | 7 | 107.893635 | 57.172695 | |
6 | 0.010132 | 10 | 109.247433 | 56.149388 | |
7 | 0.006066 | 7 | 107.602273 | 56.419207 |
98 rows × 4 columns
#
# 예제5
: 운행구간을 그룹화하고, 운행구간별 비행취소건수와 취소율을 구하여라.
-
풀이1
= pd.qcut(df.DIST,q=4)).pivot_table(
df.assign(DIST_CUT= ['DIST_CUT'],
index= 'CANCELLED',
values= ['mean','sum']
aggfunc )
mean | sum | |
---|---|---|
CANCELLED | CANCELLED | |
DIST_CUT | ||
(66.999, 391.0] | 0.022659 | 334 |
(391.0, 690.0] | 0.013503 | 196 |
(690.0, 1199.0] | 0.013637 | 203 |
(1199.0, 4502.0] | 0.010313 | 148 |
-
풀이2
= pd.qcut(df.DIST,q=4))\
df.assign(DIST_CUT'DIST_CUT')\
.groupby('CANCELLED':['mean','sum']}) .aggregate({
/tmp/ipykernel_3437616/402182245.py:2: FutureWarning: The default of observed=False is deprecated and will be changed to True in a future version of pandas. Pass observed=False to retain current behavior or observed=True to adopt the future default and silence this warning.
.groupby('DIST_CUT')\
CANCELLED | ||
---|---|---|
mean | sum | |
DIST_CUT | ||
(66.999, 391.0] | 0.022659 | 334 |
(391.0, 690.0] | 0.013503 | 196 |
(690.0, 1199.0] | 0.013637 | 203 |
(1199.0, 4502.0] | 0.010313 | 148 |
#
5. HW
43052)
np.random.seed(= pd.DataFrame({'X1':['A']*5+['B']*5, 'X2':np.concatenate([np.random.randn(5), np.random.randn(5)+10])})
df df
X1 | X2 | |
---|---|---|
0 | A | 0.383420 |
1 | A | 1.084175 |
2 | A | 1.142778 |
3 | A | 0.307894 |
4 | A | 0.237787 |
5 | B | 10.355951 |
6 | B | 8.336925 |
7 | B | 8.617227 |
8 | B | 8.073155 |
9 | B | 8.513784 |
위의 자료에서 X1을 기준으로 그룹화한뒤 X2에 대하여 아래의 함수를 적용하라.
\[\max(\text{X2})-\min(\text{X2})\]
출력결과는 아래와 같아야 한다 .
#
X2 | |
---|---|
X1 | |
A | 0.904991 |
B | 2.282796 |