일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- google apps script
- Github
- list
- dataframe
- numpy
- string
- Mac
- PANDAS
- PostgreSQL
- Google Excel
- array
- gas
- SQL
- 파이썬
- Kotlin
- Java
- Tkinter
- Excel
- Python
- c#
- math
- Google Spreadsheet
- matplotlib
- Redshift
- Apache
- GIT
- PySpark
- hive
- django
- Today
- Total
달나라 노트
Python Pandas : pandas.pivot_table (pivot, 세로 데이터를 가로 데이터로 변경) 본문
Python Pandas : pandas.pivot_table (pivot, 세로 데이터를 가로 데이터로 변경)
CosmosProject 2020. 11. 25. 16:04
pandas.pivot_table
pivot_table은 세로 데이터를 가로 데이터로 변경해주는 역할을 합니다.
먼저 테스트용 DataFrame을 생성합시다.
import pandas as pd
dict_1 = {
'dt': [20201201, 20201201, 20201201, 20201201, 20201202, 20201202, 20201202, 20201202, 20201203, 20201203, 20201203, 20201203],
'item_id': [1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2],
'item_name': ['a', 'a', 'b', 'b', 'a', 'a', 'b', 'b', 'a', 'a', 'b', 'b'],
'price': [1000, 1100, 10000, 10010, 1100, 1070, 10500, 10700, 1050, 950, 10300, 1150]
}
df_1 = pd.DataFrame(dict_1)
print(df_1)
print(type(df_1))
-- Output
dt item_id item_name price
0 20201201 1 a 1000
1 20201201 1 a 1100
2 20201201 2 b 10000
3 20201201 2 b 10010
4 20201202 1 a 1100
5 20201202 1 a 1070
6 20201202 2 b 10500
7 20201202 2 b 10700
8 20201203 1 a 1050
9 20201203 1 a 950
10 20201203 2 b 10300
11 20201203 2 b 1150
<class 'pandas.core.frame.DataFrame'>
이 데이터는 각 item들의 일자별 가격정보를 담고 있습니다.
a와 b 두 종류의 아이템이 있으며 총 3일간의 가격 변화 데이터입니다.
거기에 각 아이템들이 단 하루에도 가격 변화가 있었네요.
또한 위 데이터는 날짜 컬럼인 dt컬럼이 존재하며 이 날짜는 위에서 아래로 내려가며 점점 증가합니다.(세로 데이터)
근데 만약 각각의 날짜를 컬럼으로 하여 각 아이템들의 날짜별 가격 평균 가격을 알고싶으면 어떻게 해야할까요?
그 해답이 바로 다음 예시에 있습니다.
아래처럼 pivot_table method를 이용하면 날짜가 컬럼이 되며 가로 데이터로 바뀌었습니다.
import pandas as pd
import numpy as np
dict_1 = {
'dt': [20201201, 20201201, 20201201, 20201201, 20201202, 20201202, 20201202, 20201202, 20201203, 20201203, 20201203, 20201203],
'item_id': [1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2],
'item_name': ['a', 'a', 'b', 'b', 'a', 'a', 'b', 'b', 'a', 'a', 'b', 'b'],
'price': [1000, 1100, 10000, 10010, 1100, 1070, 10500, 10700, 1050, 950, 10300, 1150]
}
df_1 = pd.DataFrame(dict_1)
new_table = pd.pivot_table(df_1,
index=['item_id', 'item_name'],
columns=['dt'],
values='price',
aggfunc=np.mean,
fill_value=0)
print(new_table)
print(type(new_table))
-- Output
dt 20201201 20201202 20201203
item_id item_name
1 a 1050 1085 1000
2 b 10005 10600 5725
<class 'pandas.core.frame.DataFrame'>
pivot_table에 적용된 각각의 인자에 대해서 알아봅시다.
df_1: pivot_table을 적용할 대상 DataFrame을 적어줬습니다.
index=['item_id', 'item_name']: pivot_table이 적용된 후 row name으로 나타낼 정보가 담긴 컬럼을 적어주면 됩니다.
저는 item_id와 item_name을 적어주었기 때문에 위 예시의 결과에서 index가 item_id, item_name으로 존재함을 알 수 있습니다.
columns=['dt']: pivot_table이 적용된 후 column name으로 나타낼 정보가 담긴 컬럼을 적어주면 됩니다.
저는 dt를 적어주었기 때문에 위 예시의 결과에서 20201201, 20201202, 20201203의 세 날짜 컬럼이 생성되었음을 알 수 있습니다.
columns paramter로서 어떤 column name을 전달하면 해당 column에 있는 unique한 값들을 컬럼값으로 사용하라는 의미입니다.
이 값은 생략할 수 있습니다.
values='price': value는 pivot_table이 적용된 후 테이블의 값이 될 정보를 담은 컬럼을 적어주면 됩니다.
결과데이터에서 우리는 '가격'의 평균을 구한다고 하였으므로 가격 정보를 담고있는 price 컬럼을 적어주었습니다.
aggfunc=np.mean: df_1을 보면 item_id = 1 그리고 item_name = 'a' 그리고 dt = 20201201인 price 정보는 1000, 1100의 2개가 존재합니다.
pivot_table을 적용시키면 이 두 데이터를 합쳐야하는데 합칠 때 어떤 연산을 적용할지를 의미합니다.
저는 np 패키지로부터의 mean(평균) 연산을 적어주었습니다.
fill_value=0: pivot_table을 적용한 후 비어있는 칸이 있다면 그 칸을 어떤 값으로 채울지에 대한 내용입니다.
위 원본 데이터에는 비어있게 되는 부분이 없으므로 0으로 채워진 곳은 없습니다.
import pandas as pd
import numpy as np
dict_1 = {
'dt': [20201201, 20201201, 20201201, 20201201, 20201202, 20201202, 20201202, 20201202, 20201203, 20201203, 20201203, 20201203],
'item_id': [1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2],
'item_name': ['a', 'a', 'b', 'b', 'a', 'a', 'b', 'b', 'a', 'a', 'b', 'b'],
'price': [1000, 1100, 10000, 10010, 1100, 1070, 10500, 10700, 1050, 950, 10300, 1150]
}
df_1 = pd.DataFrame(dict_1)
new_table = pd.pivot_table(df_1,
index=['item_id', 'item_name'],
columns=['dt'],
values='price',
aggfunc=np.mean,
fill_value=0,
margins=True,
margins_name='__total__')
print(new_table)
print(type(new_table))
-- Output
dt 20201201 20201202 20201203 __total__
item_id item_name
1 a 1050.0 1085.0 1000.0 1045.000000
2 b 10005.0 10600.0 5725.0 8776.666667
__total__ 5527.5 5842.5 3362.5 4910.833333
<class 'pandas.core.frame.DataFrame'>
위 예시에는 margins 옵션을 추가하였습니다.
margins 옵션은 pivot_table에서 총계(Grand Total)를 계산해주는 기능을 가집니다.
- margins=True
margins=True -> 총계를 계산하여 나타내줍니다.
margins=False -> 총계를 나타내주지 않습니다.
- margins_name='~~'
총계를 나타낼 행/열의 이름을 정해줍니다.
주의할 점은 총계의 계산 방식은 pivot_table을 구성하는 aggfunc에 따라 달라진다는 것입니다.
위 예시에서 aggfunc=np.mean 평균이므로 총계도 값들의 평균으로 나타내지는 것을 볼 수 있습니다.
import pandas as pd
dict_1 = {
'dt': [20201201, 20201201, 20201201, 20201201, 20201202, 20201202, 20201202, 20201202, 20201203, 20201203, 20201203, 20201203],
'item_id': [1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2],
'item_name': ['a', 'a', 'b', 'b', 'a', 'a', 'b', 'b', 'a', 'a', 'b', 'b'],
'price': [1000, 1100, 10000, 10010, 1100, 1070, 10500, 10700, 1050, 950, 10300, 1150]
}
df_1 = pd.DataFrame(dict_1)
new_table = pd.pivot_table(df_1,
index=['item_id', 'item_name'],
columns=['dt'],
values='price',
aggfunc='sum',
fill_value=0,
margins=True,
margins_name='__total__')
print(new_table)
print(type(new_table))
-- Output
dt 20201201 20201202 20201203 __total__
item_id item_name
1 a 2100 2170 2000 6270
2 b 20010 21200 11450 52660
__total__ 22110 23370 13450 58930
<class 'pandas.core.frame.DataFrame'>
aggfunc을 sum으로 바꿨더니 총계 또한 sum으로 계산됩니다.
import pandas as pd
import numpy as np
dict_1 = {
'dt': [20201201, 20201201, 20201201, 20201201, 20201202, 20201202, 20201202, 20201202, 20201203, 20201203, 20201203, 20201203],
'item_id': [1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2],
'item_name': ['a', 'a', 'b', 'b', 'a', 'a', 'b', 'b', 'a', 'a', 'b', 'b'],
'price': [1000, 1100, 10000, 10010, 1100, 1070, 10500, 10700, 1050, 950, 10300, 1150]
}
df_1 = pd.DataFrame(dict_1)
new_table = pd.pivot_table(df_1,
index=['item_id', 'item_name'],
columns=['dt'],
values='price',
aggfunc=np.mean,
fill_value=0,
dropna=False)
print(new_table)
print(type(new_table))
-- Output
dt 20201201 20201202 20201203
item_id item_name
1 a 1050.0 1085.0 1000.0
b NaN NaN NaN
2 a NaN NaN NaN
b 10005.0 10600.0 5725.0
<class 'pandas.core.frame.DataFrame'>
두 번째 예시입니다.
df_1: pivot_table을 적용할 대상 DataFrame을 적어줬습니다.
index=['item_id', 'item_name']: pivot_table이 적용된 후 row name으로 나타낼 정보가 담긴 컬럼을 적어주면 됩니다.
저는 item_id와 item_name을 적어주었기 때문에 위 예시의 결과에서 index가 item_id, item_name으로 존재함을 알 수 있습니다.
columns=['dt']: pivot_table이 적용된 후 column name으로 나타낼 정보가 담긴 컬럼을 적어주면 됩니다.
저는 dt를 적어주었기 때문에 위 예시의 결과에서 20201201, 20201202, 20201203의 세 날짜 컬럼이 생성되었음을 알 수 있습니다.
values='price': value는 pivot_table이 적용된 후 테이블의 값이 될 정보를 담은 컬럼을 적어주면 됩니다.
결과데이터에서 우리는 '가격'의 평균을 구한다고 하였으므로 가격 정보를 담고있는 price 컬럼을 적어주었습니다.
aggfunc=np.mean: df_1을 보면 item_id = 1 그리고 item_name = 'a' 그리고 dt = 20201201인 price 정보는 1000, 1100의 2개가 존재합니다.
pivot_table을 적용시키면 이 두 데이터를 합쳐야하는데 합칠 때 어떤 연산을 적용할지를 의미합니다.
저는 np 패키지에서 mean(평균) 연산을 적어주었습니다.
dropna=False: 혹시나 결과 pivot table에 값이 없어 NaN값으로 출력되어야 하는 경우(e.g. 특정 item_id, item_name, dt에 해당하는 price값이 하나도 없어서 pivot_table method의 결과에서 하나의 row 전체가 NaN값으로 출력되는 경우 등) 그것을 없애고 출력할지 말지를 알려주는 인자입니다.
False일 경우 NaN값도 모두 출력합니다.
위 예시에선 두 번째, 세 번째 행의 값이 모두 NaN인데 이 행이 dropna=False라는 option을 설정해줬기 때문에 output에서 사라지지 않고 존재하는 것입니다.
pivot table에서 명시된 index는 단순히 명시된 index의 unique한 값을 다루는게 아니라 index에 명시된 컬럼의 모든 값의 조합을 index로 만듭니다.
예를들어 index로 ['col1', 'col2']가 명시되었고 col1에는 1, 2라는 값이, col2에는 a, b라는 값이 있다고 가정해봅시다.
이 경우 dropna=False라고 명시하면 output에는 (1, a), (1, b), (2, a), (2, b)의 총 4쌍의 index를 볼 수 있습니다
import pandas as pd
import numpy as np
dict_1 = {
'dt': [20201201, 20201201, 20201201, 20201201, 20201202, 20201202, 20201202, 20201202, 20201203, 20201203, 20201203, 20201203],
'item_id': [1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2],
'item_name': ['a', 'a', 'b', 'b', 'a', 'a', 'b', 'b', 'a', 'a', 'b', 'b'],
'price': [1000, 1100, 10000, 10010, 1100, 1070, 10500, 10700, 1050, 950, 10300, 1150],
'quantity': [10, 11, 5, 100, 2, 4, 29, 83, 20, 74, 10, 1]
}
df_1 = pd.DataFrame(dict_1)
df_pivoted = pd.pivot_table(df_1,
index=['item_id', 'item_name'],
columns=['dt'],
values=['price', 'quantity'],
aggfunc={
'price': np.mean,
'quantity': np.sum
},
fill_value=0)
print(df_pivoted)
print(type(df_pivoted))
-- Output
price quantity
dt 20201201 20201202 20201203 20201201 20201202 20201203
item_id item_name
1 a 1050 1085 1000 21 6 94
2 b 10005 10600 5725 105 112 11
<class 'pandas.core.frame.DataFrame'>
위 예시는 동일하게 pivot_table method를 사용한 예시입니다.
다만, values 인자를 보면 컬럼이 2개가 들어가있습니다.
pivot_table method는 값을 aggregate할 때 단순히 하나의 컬럼이 아니라 여러 개의 컬럼을 동시에 aggregate할 수 있습니다.
위 예시는 보면
values=['price', 'quantity'] -> price 컬럼과 quantity 컬럼 2개의 컬럼에 대해 각각 aggregate을 진행한다는 의미입니다.
aggfunc={
'price': np.mean,
'quantity': np.sum
},
-> 이 부분은 aggregate할 각각의 컬럼에 대해 어떤 방식으로 aggreate을 할지를 결정하는 부분입니다.
price 컬럼에 대해선 값들을 평균(mean)내어 aggregate한다는 의미이고,
quantity 컬럼에 대해선 값들을 합(sum)하여 aggregate한다는 의미입니다.
import pandas as pd
import numpy as np
dict_1 = {
'dt': [20201201, 20201201, 20201201, 20201201, 20201202, 20201202, 20201202, 20201202, 20201203, 20201203, 20201203, 20201203],
'item_id': [1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2],
'item_name': ['a', 'a', 'b', 'b', 'a', 'a', 'b', 'b', 'a', 'a', 'b', 'b'],
'price': [1000, 1100, 10000, 10010, 1100, 1070, 10500, 10700, 1050, 950, 10300, 1150],
'quantity': [10, 11, 5, 100, 2, 4, 29, 83, 20, 74, 10, 1]
}
df_1 = pd.DataFrame(dict_1)
df_pivoted = pd.pivot_table(df_1,
index=['item_id', 'item_name'],
values=['price', 'quantity'],
aggfunc={
'price': np.mean,
'quantity': np.sum
},
fill_value=0)
print(df_pivoted)
print(type(df_pivoted))
-- Output
price quantity
item_id item_name
1 a 1045.000000 121
2 b 8776.666667 228
<class 'pandas.core.frame.DataFrame'>
이 예시는 바로 예전 예시와 동일하지만 columns parameter를 생략한 경우입니다.
columns = ['dt'] 인자 명시한 경우
price quantity
dt 20201201 20201202 20201203 20201201 20201202 20201203
item_id item_name
1 a 1050 1085 1000 21 6 94
2 b 10005 10600 5725 105 112 11
columns = ['dt'] 인자 생략한 경우
price quantity
item_id item_name
1 a 1045.000000 121
2 b 8776.666667 228
columns = ['dt'] 인자를 명시한 경우와 그렇지 않은 경우의 결과 비교입니다.
비교하니까 무슨 차이인지를 아시겠죠.
columns 인자를 명시하면 해당 columns 인자에 명시된 컬럼에 있는 unique한 값들이 결과 pivot table의 column으로서 생성됩니다.
여기서는 20201201, 20201202, 20201203이 되겠죠.
이 각 날짜에 대한 price, quantity 컬럼 값에 대한 aggregate이 진행됩니다.
하지만 columns 인자를 명시하지 않으면 그냥 price, quantity 컬럼값에 대한 aggregate만 진행됩니다.
'Python > Python Pandas' 카테고리의 다른 글
Python Pandas : value_counts (Series에 들어있는 값 개수 세기) (0) | 2021.01.05 |
---|---|
Python Pandas : pandas.to_numeric (data type을 숫자로 바꾸기) (0) | 2020.11.25 |
Python Pandas : pandas.DataFrame.rename (0) | 2020.11.24 |
Python Pandas : pandas.to_datetime (0) | 2020.11.23 |
Python Pandas : DataFrame.to_excel & DataFrame.to_csv & pandas.ExcelWriter (0) | 2020.11.09 |