min/max/mean등은 groupby의 전체 Series 데이터로는 사용할 수 없다.
groupby 와 transform을 사용해서 전체 Series 에 대한 값을 설정할 수 있다.
import pandas as pd
import numpy as np
df = pd.read_csv("diabetes.csv")
# 혈압 인슐린 BMI, 피부 두께가 0인 데이터들이 있다.
# 값이 비정상적이라, 0인 값을 None으로 대체하고 전체 평균으로 fillna하는 것보다
# 나이대별 평균으로 fillna를 한다고 한다면.(우선 혈압데이터에 대해 진행한다)
df.describe()
# Pregnancies Glucose BloodPressure SkinThickness Insulin BMI DiabetesPedigreeFunction Age Outcome
# count 768.000000 768.000000 768.000000 768.000000 768.000000 768.000000 768.000000 768.000000 768.000000
# mean 3.845052 120.894531 69.105469 20.536458 79.799479 31.992578 0.471876 33.240885 0.348958
# std 3.369578 31.972618 19.355807 15.952218 115.244002 7.884160 0.331329 11.760232 0.476951
# min 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.078000 21.000000 0.000000
# 25% 1.000000 99.000000 62.000000 0.000000 0.000000 27.300000 0.243750 24.000000 0.000000
# 50% 3.000000 117.000000 72.000000 23.000000 30.500000 32.000000 0.372500 29.000000 0.000000
# 75% 6.000000 140.250000 80.000000 32.000000 127.250000 36.600000 0.626250 41.000000 1.000000
# max 17.000000 199.000000 122.000000 99.000000 846.000000 67.100000 2.420000 81.000000 1.000000
# 1. 10대 20대로 분류되는 컬럼을 생성한다.
df["Ages"] = df.Age//10*10
# 2. 혈압이 0인 데이터를 None으로 대체한다.
df.BloodPressure = np.where(df.BloodPressure == 0, None, df.BloodPressure)
# 3. null data는 35개가 있다.
df.BloodPressure.isna().sum()
# 35
# 4. 이후 확인을 위해 null index를 따로 저장한다.
naidx = df[df.BloodPressure.isna()].index
# 5. null data는 아래와 같이 확인 가능하다.
df.loc[naidx,"BloodPressure"].head(10)
# 7 None
# 15 None
# 49 None
# 60 None
# 78 None
# 81 None
# 172 None
# 193 None
# 222 None
# 261 None
# Name: BloodPressure, dtype: object
# 만약 나이대별 평균값을 가지는 column을 생성하려고 아래와 같이 실행하면
# index 개수가 맞지 않아 정상적으로 데이터가 생성되지 않는다. 특정 index만 비정상인 값이 생성된다.
# df["AgeMeanBP"] = df.groupby("Ages").BloodPressure.mean()
# 전체 데이터가 768개인데 7개의 index만 출력된다.
# 이런 경우 mean결과를 별도 저장하고, 전체 데이터와 merge기능을 이용해서 컬럼을 생성해야하는 복잡한 과정이 필요하다.
df.groupby("Ages").BloodPressure.mean()
#Ages
#20 68.824468
#30 73.685897
#40 77.212389
#50 79.807018
#60 78.275862
#70 82.000000
#80 74.000000
#Name: BloodPressure, dtype: float64
# 이런경우 transform으로 생성하면 각 index별 그룹별 평균값을 생성할 수 있다.
# 6. 그룹별 혈압 평균을 저장하는 768개의 index를 가지는 컬럼을 생성한다.
df["AgeMeanBP"] = df.groupby("Ages").BloodPressure.transform("mean")
# null값만 확인하면 위에서 확인한 연령대별 평균이 정상적으로 생성되어있음을 확인 할 수 있다.
df.loc[naidx,["Ages","BloodPressure","AgeMeanBP"]].head(10)
# Ages BloodPressure AgeMeanBP
#7 20 None 68.824468
#15 30 None 73.685897
#49 20 None 68.824468
#60 20 None 68.824468
#78 20 None 68.824468
#81 20 None 68.824468
#172 20 None 68.824468
#193 40 None 77.212389
#222 30 None 73.685897
#261 20 None 68.824468
# 7. fillna로 AgeMeanBP 를 지정하면 None value에 AgeMeanBP 값으로 추가한다.
df.BloodPressure.fillna(df.AgeMeanBP, inplace=True)
df.loc[naidx,["Ages","BloodPressure","AgeMeanBP"]].head(10)# fillna가 정상적으로 되었는지 확인
# Ages BloodPressure AgeMeanBP
#7 20 68.824468 68.824468
#15 30 73.685897 73.685897
#49 20 68.824468 68.824468
#60 20 68.824468 68.824468
#78 20 68.824468 68.824468
#81 20 68.824468 68.824468
#172 20 68.824468 68.824468
#193 40 77.212389 77.212389
#222 30 73.685897 73.685897
#261 20 68.824468 68.824468
# 그룹별 평균 혈압 컬럼을 생성하지 않고, lambda식으로 한번에 생성도 가능하다.
# 다시 null 값을 원복한다.
df.loc[naidx,"BloodPressure"] = None
df.loc[naidx,["Ages","BloodPressure","AgeMeanBP"]].head(10) # 다시 null
# Ages BloodPressure AgeMeanBP
#7 20 None 68.824468
#15 30 None 73.685897
#49 20 None 68.824468
#60 20 None 68.824468
#78 20 None 68.824468
#81 20 None 68.824468
#172 20 None 68.824468
#193 40 None 77.212389
#222 30 None 73.685897
#261 20 None 68.824468
# transform에 lambda식으로 평균을 입력하면 AgeMeanBP 칼럼 없이, 그룹별 혈압 평균입력이 가능하다.
df.BloodPressure = df.groupby("Ages").BloodPressure.transform(lambda x : x.fillna(x.mean()))
df.loc[naidx,["Ages","BloodPressure","AgeMeanBP"]].head(10) # 값이 정상적으로 입력
# Ages BloodPressure AgeMeanBP
#7 20 68.824468 68.824468
#15 30 73.685897 73.685897
#49 20 68.824468 68.824468
#60 20 68.824468 68.824468
#78 20 68.824468 68.824468
#81 20 68.824468 68.824468
#172 20 68.824468 68.824468
#193 40 77.212389 77.212389
#222 30 73.685897 73.685897
#261 20 68.824468 68.824468
'전처리' 카테고리의 다른 글
Pandas 구간화 bining(cut, qcut) (0) | 2023.06.21 |
---|---|
Pandas groupby section5 unstack (0) | 2023.06.21 |
Pandas groupby section3 (agg) (0) | 2023.06.20 |
Pandas groupby section2(Multi Key) (0) | 2023.06.20 |
Pandas groupby section1 (0) | 2023.06.20 |