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

빅분기수강생님의 프로필 이미지
빅분기수강생

작성한 질문수

[퇴근후딴짓] 빅데이터 분석기사 실기 (작업형1,2,3)

3-4 와 10-2 피쳐엔지니어링(인코딩) 부분 .columns 사용 등

해결된 질문

작성

·

161

·

수정됨

0

질문 1.

 

3-4 피쳐엔지니어링 강의 부분과

10-2 공식예제 체험형 2 연계 질문이 있습니다.

아래건 10-2에서 풀어본 거입니다.

import pandas as pd

train = pd.read_csv("data/customer_train.csv")
test = pd.read_csv("data/customer_test.csv")

# 사용자 코딩

# EDA
print(train.shape, test.shape)

# print(train.info())     # 범주형  주구매상품  , 주구매지점
# print(test.info())      # 범주형  주구매상품  , 주구매지점
# print(train.isnull().sum())      #    결측치   환불금액
# print(test.isnull().sum())       #    결측치   환불금액

## 전처리 (결측치, 이상치)
# print(train["환불금액"])
train["환불금액"] = train["환불금액"].fillna(0)
test["환불금액"] = test["환불금액"].fillna(0)
# print(train["환불금액"])

## 피쳐엔지니어링(스케일링, 인코딩)

from sklearn.preprocessing import LabelEncoder

cols = train.select_dtypes(include="O")

for col in cols:
	le = LabelEncoder()
	train[col] = le.fit_transform(train[col])
	test[col] = le.transform(test[col])


## 검증데이터셋 분리

from sklearn.model_selection import train_test_split

x_tr,x_val,y_tr,y_val = train_test_split(train.drop(["성별"], axis=1), train["성별"],test_size=0.2, random_state = 100)

## 평가지표 및 모델 불러오기


from sklearn.metrics import roc_auc_score, f1_score, accuracy_score
from sklearn.ensemble import RandomForestClassifier

rf = RandomForestClassifier(random_state = 100)
rf.fit(x_tr, y_tr)
pred_rf = rf.predict_proba(x_val)

print("roc_auc:",roc_auc_score(y_val,pred_rf[:,1]))    #  기본 0.6258311184510446     # 인코딩 후,  0.6356067057174067


# 예측 (테스트셋에 적용)
pred = rf.predict_proba(test)
# print(pred)
# print(pred[:,1])

# df 생성 및 제출

df = pd.DataFrame({"pred": pred[:,1]})
# print(df)

df.to_csv("result.csv", index=False)

print(pd.read_csv("result.csv"))

라벨? 레이블? 인코딩 하면서

cols 변수를 만들 때, .columns 를 추가하지 않아도 결과까지 문제 없이 되더라고요. .columns를 추가하면 시리즈 타입의 변수가 생성되고, 위에처럼 빼면 데이터프레임 차원 타입으로 변수가 생성되는건 확인했습니다.

그래서 간편성을 위해 .columns 를 빼고 원핫 인코딩도 가능한가

3-4 강의 때 자료를 적용해서 돌려봤습니다

n_train = X_train.select_dtypes(exclude = 'object').copy()       
n_test = X_test.select_dtypes(exclude = 'object').copy()
#사본 작성시 copy() 넣어서 실행
c_train = X_train.select_dtypes(include='object').copy()
c_test = X_test.select_dtypes(include = 'object').copy()


cols = X_train.select_dtypes(include="O")

c_train = pd.get_dummies(c_train[cols])                         
c_test = pd.get_dummies(c_test[cols])

그랬더니 에러가 발생 하더라고요.

#   ValueError: Boolean array expected for the condition, not object
cols = X_train.select_dtypes(include="O").columns 
# 이렇게 .columns 를 추가하고 돌리니 사용 가능

cols 변수 생성할때 다시 .columns 를 추가하고 돌리니까 에러 없이 끝까지 잘 되더라고요.

라벨 인코딩에선 문제 없던게 원핫 인코딩에서 ValueError: Boolean array expected for the condition, not object가 발생하는 이유가 뭔지 궁금합니다.

인코딩은 라벨이든 원핫이든 cols 변수 때 select_dtypes(include="O).columns 으로 .columns 까지 다 입력하는걸로 연습하는게 맞는거 같은데 오류 발생은 이해가 안되네요.

 

 

질문 2.

※ 피쳐엔지니어링에서 train, test 셋을 분리( .copy() )해서 수치형은 스케일링하고 범주형은 인코딩 한 다음, 합치기 ( .concat() ) 하는 방식이 아니라

수치형 부분 칼럼을 변수(cols_n)로 받고, 범주형 부분을 변수(cols_c) 으로 받아서, 데이터셋을 수치와 범주형으로 분리하지 않은 상태에서 각각 스케일링, 인코딩을 적용하고 검증데이터셋 분리-> 모델 & 평가지표 불러오기 -> 예측(테스트셋 적용) -> df 생성 -> 제출 하는 방법은 어렵나요?

아래 처럼요.

 

[train, test 2개 데이터셋 제공시]

# train셋엔 있고 test셋엔 없는 target에 해당하는 칼럼 분리

target = train["target"]

cols_n = train.drop("target", axis=1).select_dtypes(exclude="O).columns

cols_c = train.drop("target",axis=1).select_dtypes(include="O").columns

# "target" 데이터는 범주형이든 수치형이든 스케일링이나 인코딩을 하면 안되므로 제외시킴(이거 맞나요?)

또는

target = train.pop(["target"])

cols_n = train.select_dtypes(exclude="O).columns

cols_c = train.select_dtypes(include="O").columns

## 수치형 민맥스 스케일링 작업
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
           
train[cols_n] = scaler.fit_transform(train[cols_n])
test[cols_n] = scaler.transform(test[cols_n])

 

## 범주형 라벨 인코딩 작업
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()

for col in cols_c:
    le = LabelEncoder()
    train[col] = le.fit_transform(train[col])
    test[col] = le.transform(test[col])

그 다음 검증데이터셋 분리 ~~~~~~~~~~~ 제출

 

[X_train, y_train, X_test 3개 데이터셋 제공시]

cols_n = X_train.select_dtypes(exclude="O).columns

cols_c = X_train.select_dtypes(include="O").columns

## 수치형 민맥스 스케일링 작업
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
          
X_train[cols_n] = scaler.fit_transform(train[cols_n])
X_test[cols_n] = scaler.transform(test[cols_n])
## 범주형 라벨 인코딩 작업
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()

for col in cols_c:
    le = LabelEncoder()
    X_train[col] = le.fit_transform(X_train[col])     # 처음에 
    X_test[col] = le.transform(X_test[col])

이후 검증데이터셋 분리 ~~~~~~~~~~~ 제출

 

이런 식으로요.

작업형2에서 피쳐엔지니어링 부분이 특히 어려워서 조금이라도 간편하고, 범용성 높은 방법을 찾는게 머리 속 정리하기도 쉽고, 외우기도 좋을 거 같아서 고민중입니다.

답변 2

0

퇴근후딴짓님의 프로필 이미지
퇴근후딴짓
지식공유자

  1. columns를 추가 하던지 원핫인코딩시 아래와 같이 사용해주세요!

    c_train = pd.get_dummies(c_train)                         
    c_test = pd.get_dummies(c_test)

    cols은 이상황에서 필요없는 내용입니다.

columns이 없으면 데이터프레임 cols 형태로는 원핫인코딩이 불가능하네요!

 

  1. 네 정확히 이해하고 풀이하셨어요! 분리없이 하는 것이 더 간편합니다.

     

    다만 레이블 인코딩에서 for문에서 받아오는건 col인데 사용한는건 col_n으로 했네요 이부분만 통일시키면 될 것 같아요

for col in cols:
    le = LabelEncoder()
    X_train[col_n] = le.fit_transform(X_train[col_n])
    X_test[col_n] = le.transform(X_test[col_n])

질문 1.

그럼 질문 2 코딩 내용을 참고한다고 전제하고

범수형과 수치형을 분리(.copy()) 후 합(.concat())하지 않고 원핫인코딩을 한다면

 

target = train.pop(["target"])

cols_n = train.select_dtypes(exclude="O).columns

cols_c = train.select_dtypes(include="O").columns

 

train[col_c] = pd.get_dummies(col_c)

test[col_c] = pd.get_dummies(col_c)

이렇게 하면 되는거 맞나요? 선생님

 

 

질문 2.

for 문에 제가 잘못 썼네요... 이제 발견했습니다

 

## 범주형 라벨 인코딩 작업

from sklearn.preprocessing import LabelEncoder

 

for col in col_c: <<<< 범주형 칼럼의 집합(시리즈 타입)인 변수 col_c에서 반복 작업

le = LabelEncoder()

train[col] = le.fit_transform(train[col])

test[col] = le.transform(test[col])

 

이렇게 바꾸는게 맞나요?

col_c 이 범주형 칼럼을 모은 변수니까 col_c 에서 범주형 칼럼을 각각 col 에 넣어서 반복문으로 출력하는 방식이요.

 

퇴근후딴짓님의 프로필 이미지
퇴근후딴짓
지식공유자

1

train = pd.get_dummies(train)
test = pd.get_dummies(test)

로 하며 자동으로 범주형만 인코딩 됩니다.

 

2 네 맞습니다.

0

안녕하세요, 인프런 AI 인턴입니다.

빅분기수강생님의 질문에 답변드리겠습니다. 먼저 질문하신 내용에 대해 구체적으로 설명을 드리자면, 라벨 인코딩과 원핫 인코딩에서 .columns 사용 여부에 따른 차이와 인코딩 작업 시 선택한 변수(cols) 대상에 따른 에러 발생과 그 해결 방안에 대한 것 같습니다.

  1. .columns 사용 여부 차이: .columns를 사용하면 컬럼명만을 리스트 형태로 추출합니다. 이는 특히 라벨 인코딩, 원핫 인코딩 등을 할 때 해당 컬럼들에만 연산을 적용하기 위해 필요합니다. 데이터프레임에서 특정 컬럼만 선택할 경우, .columns를 사용하지 않고 직접 데이터프레임 형태로 선택하면 에러가 발생할 수 있습니다. 왜냐하면, LabelEncoder는 1차원 데이터(즉, 시리즈)에만 적용 가능하기 때문입니다.

    라벨 인코딩에서는 문제가 없었던 이유는 의도치 않게 작동됐을 가능성이 있습니다. 원핫 인코딩에서 에러가 발생한 것은 pd.get_dummies는 데이터프레임에 대해서도 작동하지만, 전달된 데이터의 타입이나 구조에 따라 예상치 못한 에러가 발생할 수 있습니다.

  2. 수치형 및 범주형 데이터에 대한 처리 방식: 질문하신 방식대로 데이터를 분석하고 처리하는 것은 전혀 어렵지 않으며, 사실 매우 일반적인 접근 방법입니다. select_dtypes를 사용하여 데이터를 수치형과 범주형으로 나누고, 각각 적합한 전처리(스케일링 또는 인코딩)를 적용하는 것이 좋은 전략입니다. 특히 스케일링 작업은 주로 수치형 데이터에 적용되며, 인코딩(라벨 인코딩 또는 원핫 인코딩)은 범주형 데이터에 적용됩니다.

    train["target"] 데이터를 제외시키는 것도 올바른 접근 방법입니다. 왜냐하면 대부분의 경우, 타겟 변수는 모델 학습 시 사용되는 피처와는 별개로 취급되어야 하기 때문입니다. 일반적인 머신러닝 작업 흐름에서 타겟 변수에 대해 스케일링하거나 인코딩을 적용하는 것은 일반적이지 않습니다(타겟 인코딩 같은 특별한 경우를 제외하고).

여러분이 언급하신 피쳐 엔지니어링 과정은 실제로 많이 사용되는 표준 절차 중 하나입니다. 데이터의 특성에 따라 적절한 전처리 작업을 선택하고 적용하는 것이 중요합니다.

해당 주제에 대한 구체적인 예시 및 실습은 아래 링크에서 확인할 수 있습니다:

위 링크는 비슷한 맥락의 문의에 대해 지식공유자께서 제공한 답변을 포함하고 있으며, 여러분의 질문에 대한 해결점을 찾는 데 도움이 될 수 있습니다.

모델링 과정에서 데이터를 적절히 전처리하고 인코딩하는 것은 매우 중요하며, 여러분의 접근 방식은 그 방향성에 잘 부합하는 것으로 보입니다. 다만, 구체적인 데이터와 상황에 따라 최적의 방법이 달라질 수 있음을 기억하세요.

저는 질문자님의 이해를 돕고자 지식공유자님의 기존 답변을 참고하여 유사한 답변 링크를 추천해드리고 있습니다.
현재 베타 기능으로 답변이 만족스럽지 않을 수 있는 점 양해 부탁드립니다. 🙏
추가적으로 궁금한 점이 있으시면, 이어서 질문해 주세요. 곧 지식공유자께서 답변해 주실 것입니다.

빅분기수강생님의 프로필 이미지
빅분기수강생

작성한 질문수

질문하기