AI, DataScience

[Pandas] 데이터를 그룹으로 나누어 각 그룹 별 평균으로 결측값 대치하기 (성별과 나이 별로 키, 몸무게 평균값 대치)

이무기뱀술 2022. 1. 24. 10:00
728x90

개요

오늘은 Python, Pandas를 이용한 데이터 전처리를 해보겠습니다.

데이터 전처리는 딥러닝 모델의 정확도를 높이기 위해 꼭 거쳐야하는 과정입니다.

결측값이 많은 데이터

키와 몸무게 데이터입니다. 한눈에 봐도 결측값이 매우 많지요?

DataFrame.info를 이용하여 칼럼의 정보를 봤더니 9704개 중 3597개, 5810개만 유효하군요. 이러한 데이터로 모델을 학습하면 매우 형편없는 결과가 나올 것입니다.

 

그러면 어떻게 해야할까요?

Scikit-learn의 SimpleImputer를 불러와서 사용해도 됩니다

https://scikit-learn.org/stable/modules/generated/sklearn.impute.SimpleImputer.html

from sklearn.impute import SimpleImputer

imp_mean = SimpleImputer(strategy='mean')

ctn = pd.DataFrame(imp_mean.fit_transform(raw_ctn), index=idx_dataset, columns=col_c)
# 아래는 개인적으로 만든 변수입니다.
# ctn: 전처리한 데이터
# raw_ctn: 원래 데이터
# idx_dataset: dataset의 index 리스트
# col_c: 칼럼 리스트
 

그러나 위 코드는 심각한 오류가 있습니다.

9704명 전체의 평균으로 결측값을 대치하는 것이 과연 맞을까요?

40대 남자의 키와, 60대 여자의 키를 똑같은 값으로 대치하는 것이 맞을까요??

 

그룹으로 만들기

이 문제를 해결하기 위해 데이터를 그룹으로 나눕니다.

성별, 나이

데이터는 40대~60대 남녀가 있습니다. 각 나잇대와 성별에 따라 6개의 그룹으로 나눕니다.

import numpy as np

condition = [(dataset['AS1_SEX'] == 0 ) & (dataset['AS1_AGE'] >= 60),  # 60대 남자
             (dataset['AS1_SEX'] == 0 ) & (dataset['AS1_AGE'] >= 50),  # 50대 남자
             (dataset['AS1_SEX'] == 0 ) & (dataset['AS1_AGE'] >= 40),  # 40대 남자
             (dataset['AS1_SEX'] == 1 ) & (dataset['AS1_AGE'] >= 60),  # 60대 여자
             (dataset['AS1_SEX'] == 1 ) & (dataset['AS1_AGE'] >= 50),  # 50대 여자
             (dataset['AS1_SEX'] == 1 ) & (dataset['AS1_AGE'] >= 40)   # 40대 여자
            ]
choice = ['M60', 'M50', 'M40', 'F60', 'F50', 'F40']

dataset['group'] = np.select(condition, choice, default=np.nan)
dataset['group']

NumPy의 select를 이용하였습니다. select 메소드는 주어진 condition에 따라 choice로 구성된 리스트를 반환합니다.

 

위 코드를 보면 'AS1_SEX'가 0이고, 'AS1_AGE'가 60이상이면 M60(60대 남자)을 부여합니다.

 

이렇게 선택된 choice를 새로운 칼럼 'group'에 넣었습니다

 

np.select()를 이용한 그룹 열 생성

 

그룹 별 결측값 대치

그리고 DataFrame.groupby와 DataFrame.apply를 이용하여 결측값을 대치합니다.

 

fill_mean_func = lambda g: g.fillna(g.mean()) # 각 그룹별 평균으로 결측값 대치

dataset['AS1_HEIGHT'] = dataset.groupby('group')['AS1_HEIGHT'].apply(fill_mean_func)
dataset['AS1_WEIGHT'] = dataset.groupby('group')['AS1_WEIGHT'].apply(fill_mean_func)

각 그룹의 dataset['AS1_HEIGHT']와 dataset['AS1_WEGHT']를 불러와서,

람다함수 fill_mean_func을 apply() 합니다.

 

완료

결측값을 대치한 데이터

 

 

 

참고자료:

https://www.delftstack.com/ko/howto/python-pandas/how-to-create-dataframe-column-based-on-given-condition-in-pandas/

 

Pandas에서 주어진 조건에 따라 DataFrame 열을 만드는 방법

DataFrame 객체에 대한 목록 이해 기술, 숫자 메서드, apply() 메서드 및 map() 메서드를 사용하여 Pandas의 주어진 조건을 기반으로 DataFrame 열을 만들 수 있습니다.

www.delftstack.com

https://rfriend.tistory.com/402

 

[Python Pandas] 결측값을 그룹 평균값으로 채우기 (Fill missing values by Group means)

이전 포스팅에서 Pandas 의 함수를 활용해서 결측값을 채우거나 행을 제거하기, GroupBy operator를 사용해서 그룹별 (가중)평균을 구하는 방법을 소개했었습니다. 결측값 채우기 (http://rfriend.tistory.com

rfriend.tistory.com

 

728x90