[Python pandas] 데이터 재구조화(reshaping data) : pd.DataFrame.stack(), pd.DataFrame.unstack()
Python 분석과 프로그래밍/Python 데이터 전처리 2016. 12. 24. 23:29데이터 재구조화(reshaping data)를 위해 사용할 수 있는 Python pandas의 함수들에 대해서 아래의 순서대로 나누어서 소개해보겠습니다.
- (1) pivot(), pd.pivot_table()
- (2) stack(), unstack()
이번 포스팅에서는 두번째로 pd.DataFrame.stack(), pd.DataFrame.unstack()에 대해서 알아보겠습니다.
stack을 영어사전에서 찾아보면 뜻이
stack[stӕk]~ (sth) (up) (깔끔하게 정돈하여) 쌓다[포개다]; 쌓이다, 포개지다
~ sth (with sth) (어떤 곳에 물건을 쌓아서) 채우다
라는 뜻입니다.
stack이 (위에서 아래로 길게, 높게) 쌓는 것이면, unstack은 쌓은 것을 옆으로 늘어놓는것(왼쪽에서 오른쪽으로 넓게) 라고 연상이 될 것입니다.
Python pandas의 stack(), unstack() 실습에 필요한 모듈을 불러오고, 예제로 사용할 hierarchical index를 가진 DataFrame을 만들어보겠습니다.
In [1]: import numpy as np In [2]: import pandas as pd In [3]: from pandas import DataFrame In [4]: mul_index = pd.MultiIndex.from_tuples([('cust_1', '2015'), ('cust_1', '2016'), ...: ('cust_2', '2015'), ('cust_2', '2016')]) ...: In [5]: data = DataFrame(data=np.arange(16).reshape(4, 4), ...: index=mul_index, ...: columns=['prd_1', 'prd_2', 'prd_3', 'prd_4'], ...: dtype='int') ...: In [6]: data Out[6]: prd_1 prd_2 prd_3 prd_4
|
stack() method 를 사용해서 위의 예제 데이터셋을 위에서 아래로 길게(높게) 쌓아(stack) 보겠습니다. 칼럼의 level은 1개 밖에 없으므로 stack(level=-1) 을 별도로 명기하지 않아도 됩니다.
(1) pd.DataFrame.stack(level=-1, dropna=True) |
DataFrame을 stack() 후에 index를 확인해보고, indexing 해보겠습니다.
DataFrame을 stack() 하면 Series 를 반환합니다.
# stack() In [7]: data_stacked = data.stack()
# DataFrame.stack() => returns Series In [8]: data_stacked Out[8]: cust_1 2015 prd_1 0 dtype: int32
In [9]: data_stacked.index Out[9]: MultiIndex(levels=[['cust_1', 'cust_2'], ['2015', '2016'], ['prd_1', 'prd_2', 'prd_3', 'prd_4']], labels=[[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1], [0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3]])
In [10]: data_stacked['cust_2']['2015'][['prd_1', 'prd_2']] Out[10]: prd_1 8 prd_2 9 dtype: int32
|
결측값이 있는 데이터셋을 stack() 할 때 결측값을 제거할지(dropna=True), 아니면 결측값을 NaN으로 유지할지(dropna=False) 설정할 수 있는 stack(dropna=True, False)를 예를 들어 설명해보겠습니다.
# # putting NaN to DataFrame In [11]: data.ix['cust_2', 'prd_4'] = np.nan In [12]: data Out[12]: prd_1 prd_2 prd_3 prd_4
In [13]: data.stack(dropna=False) Out[13]: cust_1 2015 prd_1 0.0 dtype: float64
In [14]: data.stack(dropna=True) # by default Out[14]: cust_1 2015 prd_1 0.0 dtype: float64
|
stack()으로 위에서 아래로 길게(높게) 쌓아 올린 데이터셋을 이번에는 거꾸로 왼쪽으로 오른쪽으로 넓게 unstack()으로 풀어보겠습니다.
stack() 후의 data_stacked 데이터셋이 아래에 보는 것처럼 level이 3개 있는 MultiIndex 입니다. 이럴 경우 unstack(level=-1), unstack(level=0), unstack(level=1) 별로 어떤 level이 칼럼으로 이동해서 unstack() 되는지 유심히 살펴보시기 바랍니다.
(2) pd.DataFrame.unstack(level=-1, fill_value=None) |
In [15]: data_stacked Out[15]: cust_1 2015 prd_1 0 dtype: int32 In [16]: data_stacked.unstack(level=-1) Out[16]: prd_1 prd_2 prd_3 prd_4 In [17]: data_stacked.unstack(level=0) Out[17]: cust_1 cust_2
In [18]: data_stacked.unstack(level=1) Out[18]: 2015 2016
|
unstack() 한 후의 데이터셋도 역시 Series 인데요, 이것을 DataFrame으로 변환해보겠습니다.
# converting Series to DataFrame In [19]: data_stacked_unstacked = data_stacked.unstack(level=-1) In [20]: data_stacked_unstacked Out[20]: prd_1 prd_2 prd_3 prd_4
# converting index to columns In [21]: data_stacked_unstacked_df = data_stacked_unstacked.reset_index()
# changing columns' name In [22]: data_stacked_unstacked_df.rename(columns={'level_0' : 'custID', ...: 'level_1' : 'year'}, inplace=True) ...: In [23]: data_stacked_unstacked_df Out[23]: custID year prd_1 prd_2 prd_3 prd_4
|
이상으로 stack(), unstack()을 이용한 데이터 재구조화에 대해서 알아보았습니다.
다음번 포스팅에서는 melt(), wide_to_long() 을 이용한 데이터 재구조화를 소개하겠습니다.
많은 도움 되었기를 바랍니다.