범주형 데이터 (categorical data)를 수치화하는 방법은 대표적으로 1) 0부터 범주 개수까지 범위의 숫자를 할당하는 nominal 인코딩 (Label encoding), 2) 각 범주마다 1의 값을 가지는 dummy variable을 생성하는 onehot 인코딩 방법이 있습니다. (물론 다른 방법들도 있습니다.) 특히, one-hot 인코딩은 Pandas의 get_dummies 함수를 이용해서 쉽게 수행할 수 있었는데요, 이 함수를 사용할 경우 inverse_transform 함수가 정의되어 있는 scikit-learn 함수와는 달리 변환 이후에 원래 데이터 양식으로 역변환 함수를 따로 만들어줘야 합니다.
다음과 같은 데이터프레임이 있다고 가정했을 때 get_dummies 함수를 이용하면 prefix_sep에 따라 각 범주의 dummy variable이 생성됩니다. 이 상황에서 원래의 "name", "color" 값으로 되돌릴려면 어떻게 해야 할까요?
fruit = pd.DataFrame({'name':['apple', 'banana', 'cherry', 'durian', 'mango'],
'color':['red', 'yellow', 'red', 'green', 'yellow']})
dummy_fruit = pd.get_dummies(fruit, columns=['name', 'color'], prefix_sep='_')
dummy_fruit
일단 데이터프레임의 column을 순회하면서 칼럼명에 prefix_sep ('_')이 포함되면 dummy 변수인 것이므로 prefix_sep 기준으로 스플릿하여 dummy화가 된 칼럼/안된 칼럼으로 구분하는 딕셔너리를 생성할 수 있습니다. 이때, dummy 칼럼의 이름은 prefix_sep 앞부분이 원래 컬럼명이라는 것을 이용합니다.
cols2collapse = {
item.split(prefix_sep)[0]: (prefix_sep in item) for item in df.columns
}
각 컬럼 별로 처리된 pandas 시리즈를 담을 리스트를 하나 생성하고 딕셔너리를 기반으로 순회하면서 dummy화된 변수에 대해 원래 컬럼명으로 필터링하고 (pandas.DataFrame.filter) 0/1로 되어있는 값 중 1로 된 것이 원래의 값이므로 pandas.DataFrame.idxmax 함수를 이용합니다. 이후에는 결과 시리즈에 대해 이름을 원래 칼럼명으로 바꿔주고 (pandas.rename) 리스트에 추가합니다. Dummy화된 변수가 아니라면 그대로 리스트에 추가합니다.
series_list = []
for col, needs_to_collapse in cols2collapse.items():
if needs_to_collapse:
undummified = (
df.filter(like=col)
.idxmax(axis=1)
.apply(lambda x: x.split(prefix_sep, maxsplit=1)[1])
.rename(col)
)
series_list.append(undummified)
else:
series_list.append(df[col])
최종적으로 concat 함수를 이용하여 리스트에 담긴 pandas 시리즈를 이어붙이고 리턴합니다. 이를 함수화하면 다음과 같습니다.
def undummify(df, prefix_sep="_"):
cols2collapse = {
item.split(prefix_sep)[0]: (prefix_sep in item) for item in df.columns
}
series_list = []
for col, needs_to_collapse in cols2collapse.items():
if needs_to_collapse:
undummified = (
df.filter(like=col)
.idxmax(axis=1)
.apply(lambda x: x.split(prefix_sep, maxsplit=1)[1])
.rename(col)
)
series_list.append(undummified)
else:
series_list.append(df[col])
undummified_df = pd.concat(series_list, axis=1)
return undummified_df
- Pandas의 filter 함수의 like는 문자열을 입력으로 받아 해당 축 (디폴트는 axis=1)에 입력으로 전달한 문자열을 포함한 인덱스나 컬럼을 필터링합니다.
- Pandas의 idxmax 함수는 주어진 축에 대하여 큰 값을 가지는 인덱스나 칼럼명을 리턴합니다.
df = pd.DataFrame({'consumption': [10.51, 103.11, 55.48], 'co2_emissions': [37.2, 19.66, 1712]}, index=['Pork', 'Wheat Products', 'Beef']) >>> df.idxmax() consumption Wheat Products co2_emissions Beef dtype: object
원래 데이터로 잘 돌아왔네요.
'Computer > Pandas' 카테고리의 다른 글
Pandas groupby (1) (0) | 2021.08.07 |
---|---|
Pandas Categorical Data (0) | 2021.08.01 |
Pandas Multiple Columns Label Encoding (1) | 2021.07.14 |
Pandas DataFrame 합치기 - merge, concat (0) | 2021.03.31 |
Pandas 에서 데이터 이상치 찾기 - Z-score, Modified Z-score, IQR (0) | 2021.03.31 |