인프런 커뮤니티 질문&답변

녕나님의 프로필 이미지

작성한 질문수

[개정판] 파이썬 머신러닝 완벽 가이드

안녕하세요

20.09.21 17:56 작성

·

462

0

안녕하세요 선생님 강의 잘 보고 있습니다.

다름이 아니고 "평가 3.6장, 피마 인디언 당뇨병 예측"을 공부 하고 있습니다. 여기서 Glucose, BloodPressure, SkinThickness...등 0으로 기록된 값이 있어서 책에서는 이것들을 평균으로 바꿔서 모델의 예측 성능을 높히셨는데

저는 좀 더 나아가보고자 저 값들을 그냥 평균으로 바꾸지 않고 해당 나이대에 비슷한 평균값으로 바꾸고 싶어서 나름 이리저리 코드를 굴려봤는데 잘 안되서 도움 요청을 드리고 싶습니다.

1. 나이는 실수값이라서 lamba 식을 이용해서 "Age_cat"를 따로 만들었습니다.

2. 만약 index=4의 사람의 insulin이 0이면 "그 해당 사람의 나이대에 맞는 값의 평균"으로 바꾸고자 하는 코딩이

for feature in zero_feature....부분 부터입니다. 한번에 적용하는 방법을 모르겠어서 이중 for문으로 구현해봤는데

어디가 오류인지 잘 모르겠네요.

3. 혹시 제가 구현하려는 방식보다 더 쉽고 간편한 방식이 있으시면 알려주시면 감사하겠습니다 ㅠㅠ 질문이 길어서 죄송합니다

답변 5

0

권 철민님의 프로필 이미지
권 철민
지식공유자

2020. 09. 21. 22:47

판다스가 API 기반이라 데이터 처리에 익숙해지는데 시간이 필요합니다.

원래 시도하신 방식이 논리적으론 맞는데, 문제는 Boolean indexing으로 filtering한 값을 update할 때 값 복사가 안되서 그런것 같습니다. 즉 df[df['Age_cat']==age][feature].replace()에서
df[df['Age_cat']==age] 결과에 replace() 적용시 이게 copy가 안됩니다. (아마 원래 코드로 하시면 값 복사가 안된다는 warning이 나올 겁니다).  

boolean indexing으로 추출한 결과가 원본 DataFrame에서 이미 filtering되어 있는 건데, 여기에 값을 update하는 것을 pandas에서 허용하지 않는것 같습니다.

그래서 아예 boolean indexing에서 update를 하지 않는 방식으로 변경했습니다. 필터링 하지 않고 컬럼레벨로 update하기 위해 groupby transform()을 적용한 것입니다.

0

녕나님의 프로필 이미지
녕나
질문자

2020. 09. 21. 21:49

df[feature].replace(0, df.groupby('Age_cat')[feature].transform('mean'), inplace=True)

이런식으로 .replace() 함수의 2번째 인자로 "series"가 오게 되면 df[feature]의 특정 index가 0이면 그 특정 index에 해당하는 값을 df.groupby('Age_cat')[feature].transform('mean') "series"에서 뽑아와서 적용시키는 건가요?

허 ㅠㅠ 판다스 익숙해지려고 해도 너무 헷갈리는게 많네요! 혹시 제 방식대로 평균을 적용할 경우 groupby transform이 최선인가요!? 더 쉬운 함수가 있는지 궁금하네요

0

권 철민님의 프로필 이미지
권 철민
지식공유자

2020. 09. 21. 20:40

아래 코드로 바꿔 보시지요.  groupby transform을 적용해서 변환했습니다.

df = pd.read_csv('./diabetes.csv')

y = df['Outcome']

X = df.drop(['Outcome'], axis=1)

def get_Age_cat(age):

    cat = ''

    if (age >= 50):

        cat = "Elderly"

    elif (age >= 35):

        cat = "Middle-Adult"

    elif (age >= 20):

        cat = "Young-Adult"

    else:

        cat = "Teen"

    return cat

df['Age_cat'] = df['Age'].apply(lambda x: get_Age_cat(x))

age_cat = ['Elderly', 'Middle-Adult', 'Young-Adult', 'Teen']

zero_features = ['Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', "BMI"]

for feature in zero_features:
    df[feature].replace(0, df.groupby('Age_cat')[feature].transform('mean'), inplace=True)
 

0

녕나님의 프로필 이미지
녕나
질문자

2020. 09. 21. 19:46

해당 코드입니다.

#pd.options.mode.chained_assignment = None

df = pd.read_csv('./diabetes.csv')

y = df['Outcome']

X = df.drop(['Outcome'], axis=1)

def get_Age_cat(age):

    cat = ''

    if (age >= 50):

        cat = "Elderly"

    elif (age >= 35):

        cat = "Middle-Adult"

    elif (age >= 20):

        cat = "Young-Adult"

    else:

        cat = "Teen"

    return cat

df['Age_cat'] = df['Age'].apply(lambda x: get_Age_cat(x))

age_cat = ['Elderly', 'Middle-Adult', 'Young-Adult', 'Teen']

zero_features = ['Glucose', 'BloodPressure', 'SkinThickness', 'Insulin', "BMI"]

for feature in zero_features:

    for age in age_cat:

        df[df['Age_cat']==age][feature].replace(0, df[df['Age_cat']==age][feature].mean(), inplace=True)

0

권 철민님의 프로필 이미지
권 철민
지식공유자

2020. 09. 21. 18:00

안녕하십니까,

좋은 아이디어군요. 해당 코드를 이미지 캡처하시지 마시고, 여기에 텍스트로 올려주시겠습니까? 제가 테스트 해보고 말씀드리겠습니다.

녕나님의 프로필 이미지

작성한 질문수

질문하기