이번에는 조금 다른 pivot 사례를 가져왔습니다.
이전 다룬 Pivot 사례는 group 기준이되는 index가 1개 이상이거나, value가 1개일 경우에 pivot하는 방법이였다면,
[IT/Python] - Python에서 행을 열로 변환하기 - pandas Pivot 메소드
Python에서 행을 열로 변환하기 - pandas Pivot 메소드
다음과 같이 데이터가 존재할 때 한 열을 컬럼명으로하고 한 열은 값으로 보여주고 싶을때 하는 기능이 Pivot 기능이죠. Sample group key val 0 01 A 10 1 01 B ..
h-a-i.tistory.com
이번에는 group 기준이 되는 index도 1개 이상이고, value값도 1개 이상일 경우에 pivot 하는 방법에 대해 알아보도록하겠습니다.
다음과 같은 샘플데이터가 있을때
meta1 meta2 para val1 val2
0 A B 1 AA AB
1 A B 2 BA BB
2 A B 3 AA BB
3 C D 1 CC CD
4 C D 2 DC DD
5 C D 3 CC DD
아래와 같은 결과를 얻고 싶을때가 있습니다.
meta1 meta2 1_val1 1_val2 2_val1 2_val2 3_val1 3_val2
0 A B AA AB BA BB AA BB
1 C D CC CD DC DD CC DD
이런 경우는 데이터가 많을때 주로 DB에 이렇게 적재가 되는데요.
데이터 분석을 할때는 옆으로 이렇게 쭉 있어야지
X 값으로 두고 분석을 할 수 있잖아요?
이럴때 Pivot을 하면됩니다.
방법은 2가지가 있어요.
1. Pandas Pivot 메소드를 사용한다.
2. Dict와 List를 이용해서 Pivot 할 수 있도록 만든다.
1. Pandas Pivot 메소드를 사용한다.
pivot 메소드를 사용하는 방법은 매우 간단합니다.
import pandas as pd
sample_df = pd.DataFrame(
[
{'meta1' : 'A', 'meta2': 'B', 'para' : '1', 'val1' : 'AA', 'val2' : 'AB' } ,
{'meta1':'A', 'meta2':'B', 'para': '2', 'val1':'BA', 'val2':'BB'},
{'meta1':'A', 'meta2':'B', 'para': '3', 'val1':'AA', 'val2':'BB'},
{'meta1': 'C', 'meta2': 'D', 'para': '1', 'val1': 'CC', 'val2': 'CD'},
{'meta1': 'C', 'meta2': 'D', 'para': '2', 'val1': 'DC', 'val2': 'DD'},
{'meta1': 'C', 'meta2': 'D', 'para': '3', 'val1': 'CC', 'val2': 'DD'}
])
print(sample_df)
# meta1 meta2 para val1 val2
# 0 A B 1 AA AB
# 1 A B 2 BA BB
# 2 A B 3 AA BB
# 3 C D 1 CC CD
# 4 C D 2 DC DD
# 5 C D 3 CC DD
pivot_df = sample_df.pivot(index=['meta1', 'meta2'],
columns= 'para',
values=['val1', 'val2']
)
print(pivot_df)
# val1 val2
# para 1 2 3 1 2 3
# meta1 meta2
# A B AA BA AA AB BB BB
# C D CC DC CC CD DD DD
이렇게 하면 데이터가 pivoting이 되지만
만약에 데이터가 중복된다면 에러가 생깁니다.
ValueError: Index contains duplicate entries, cannot reshape
그럼 중복제거를 하고 pivoting을 하면됩니다.
import pandas as pd
sample_df = pd.DataFrame(
[
{'meta1' : 'A', 'meta2': 'B', 'para' : '1', 'val1' : 'AA', 'val2' : 'AB' } ,
{'meta1':'A', 'meta2':'B', 'para': '2', 'val1':'BA', 'val2':'BB'},
{'meta1':'A', 'meta2':'B', 'para': '3', 'val1':'AA', 'val2':'BB'},
{'meta1': 'C', 'meta2': 'D', 'para': '1', 'val1': 'CC', 'val2': 'CD'},
{'meta1': 'C', 'meta2': 'D', 'para': '2', 'val1': 'DC', 'val2': 'DD'},
{'meta1': 'C', 'meta2': 'D', 'para': '3', 'val1': 'CC', 'val2': 'DD'},
{'meta1': 'C', 'meta2': 'D', 'para': '3', 'val1': 'CC', 'val2': 'DD'}
])
print(sample_df)
# meta1 meta2 para val1 val2
# 0 A B 1 AA AB
# 1 A B 2 BA BB
# 2 A B 3 AA BB
# 3 C D 1 CC CD
# 4 C D 2 DC DD
# 5 C D 3 CC DD
# 6 C D 3 CC DD
sample_df = sample_df.drop_duplicates()
pivot_df = sample_df.pivot(index=['meta1', 'meta2'],
columns= 'para',
values=['val1', 'val2']
)
print(pivot_df)
# val1 val2
# para 1 2 3 1 2 3
# meta1 meta2
# A B AA BA AA AB BB BB
# C D CC DC CC CD DD DD
자.. 여기에서 이렇게 데이터가 pivoting 되면 컬럼명이
참.. 마음에 안듭니다.
원하는 컬럼명은 이렇게 되야하는데..
meta1 meta2 1_val1 1_val2 2_val1 2_val2 3_val1 3_val2
저렇게하면 어쩌지?
생각이 들어서 그냥 짜보자. 해서 그냥 짜봤습니다.
2. Dict와 List를 이용해서 Pivot 할 수 있도록 만든다.
프로세스
1. 데이터프레임 row 한줄씩 처리한다.
2. pivot에서 index 역할을 하는 meta dict를 key로 생성한다. 이때 key는 hash 값으로 생성
3. pivot 대상 데이터의 컬럼명과 값을 dictionary에 담는다. : para_dict - key는 meta key, value는 col_name: col_value 형식의 dict
4. para_dict에 meta key 정보가 있으면 업데이트한다. 없으면 새로 생성한다.
5. meta_dict와 p_dict를 연결해서 data_list 에 담는다.
6. data_list를 데이터프레임으로 변경한다.
sample_df = pd.DataFrame(
[
{'meta1' : 'A', 'meta2': 'B', 'para' : '1', 'val1' : 'AA', 'val2' : 'AB' } ,
{'meta1':'A', 'meta2':'B', 'para': '2', 'val1':'BA', 'val2':'BB'},
{'meta1':'A', 'meta2':'B', 'para': '3', 'val1':'AA', 'val2':'BB'},
{'meta1': 'C', 'meta2': 'D', 'para': '1', 'val1': 'CC', 'val2': 'CD'},
{'meta1': 'C', 'meta2': 'D', 'para': '2', 'val1': 'DC', 'val2': 'DD'},
{'meta1': 'C', 'meta2': 'D', 'para': '3', 'val1': 'CC', 'val2': 'DD'},
{'meta1': 'C', 'meta2': 'D', 'para': '3', 'val1': 'CC', 'val2': 'DD'}
])
print(sample_df)
p_dict = dict()
meta_dict = dict()
for i, row in sample_df.iterrows():
# hash key 생성
key = hash(str(list(row[['meta1', 'meta2']])))
# meta dict 생성
meta_col_list = ['meta1', 'meta2']
meta_val_list = list(row[['meta1', 'meta2']])
meta_dict[key] = dict(zip(meta_col_list, meta_val_list))
# para dict 생성
para_col_list = [row['para']+'_'+val for val in ['val1', 'val2']]
para_val_list = list(row[['val1', 'val2']])
try:
p_dict[key].update(dict(zip(para_col_list, para_val_list)))
except KeyError as e:
p_dict[key] = dict(zip(para_col_list, para_val_list))
data_list = []
for key, val in meta_dict.items():
# meta, para 합치기
data_list.append({**val, **p_dict[key]})
print(pd.DataFrame(data_list))
# meta1 meta2 1_val1 1_val2 2_val1 2_val2 3_val1 3_val2
#0 A B AA AB BA BB AA BB
#1 C D CC CD DC DD CC DD
이렇게 진행했을 때의 장점은
대용량데이터 처리가 가능합니다.
그 이유는 모든데이터를 올려서 처리하는게 아니라 한줄한줄 처리가 가능하기때문에
메모리를 적게 사용하고 안정적으로 처리할 수 가 있습니다.
'IT > Python' 카테고리의 다른 글
Change Dtypes Series of Pandas DataFrame to Dictionary (0) | 2020.10.07 |
---|---|
Python에서 Progress bar로 진행상황 표현하기 (0) | 2020.09.25 |
Python에서 행을 열로 변환하기 - pandas Pivot 메소드 (0) | 2020.09.23 |
Python 추상자료형 - 큐 ( Queue ) (0) | 2020.09.22 |
Pandas DataFrame 연결하기 ( Union ) (0) | 2020.09.21 |