pythonにおけるsklearnでのOneHotencoding(train_test_splitによるX_train,X_valid分割データ)
pythonにおけるsklearnでのOneHotencodingで立ち止まっております。
問題は、X_train,X_validに分割(train_test_split)した後でのデータ変換です。indexがリセットされているようなのです。
それ故、元のデータとの結合(concat)をしても、まともに結合できません。
いろいろなサイトを調べたのですが、分割前のデータ(indexは0から始まっている)を使ってのものばかりでした。
確かに、0から始まるデータに対しては、sklearnのOneHotencodingは、問題なく変換をしてくれ、結合(concat)もできます。
今回、質問させていただくにあたり、
(1)変換後のデータのindexがリセットされているコード・・・小生の現在の問題点です。
(2)indexが0から始まるデータの場合(うまく行く)
(3)category_encordersでのOneHotencodingを使ってうまく行ったコード
を示します。
(1)のsklearnのOneHotencodingでのコードのどこが、間違っているのか、
どこをどう直せば、(3)のように良い結果が得られるのか、よろしくお願いします。
(Windows10 32bit,python 3.8.5 scikit-learn=1.02 (3)category_encorders=2.3.0 )
(1)変換後のデータのindexがリセットされているコード・・・小生の現在の問題点です------
'''
import pandas as pd
import numpy as np
from sklearn import preprocessing
from sklearn.preprocessing import OneHotEncoder
from sklearn.model_selection import train_test_split
import seaborn as sns
データセットを読み込む
df = sns.load_dataset('titanic')
df=df[['survived','pclass','sex','embarked','sibsp','parch']] # データを限定する
X=df.drop('survived',axis=1)
y=df['survived']
データをtrain,validに分割する
X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, random_state=0)
print(f"X({len(X)}) = X_train({len(X_train)}) + X_valid({len(X_valid)})")
print(f'\n-----------X_train{X_train.shape}-------------')
display(X_train.head(3))
print(f'\n-----------X_valid{X_valid.shape}-------------')
display(X_valid.head(3))
変換する特徴量の定義
category_selected=['embarked', 'sex']
ohe = OneHotEncoder(sparse=False)
encoded_T = ohe.fit_transform(X_train[category_selected].values)
encoded_V = ohe.transform(X_valid[category_selected].values)
列名を取得
label = ohe.get_feature_names(category_selected)
データフレーム化
encoded_T_df = pd.DataFrame(encoded_T, columns=label, dtype=np.int8)
encoded_V_df = pd.DataFrame(encoded_V, columns=label, dtype=np.int8)
データフレームを結合
print(f'\n-----------after encoding for X_train and convined with original X_train{encoded_T_df.shape}-------------')
display(pd.concat([X_train, encoded_T_df], axis=1).head(3))
print(f'\n-----------after encoding for X_valid and convined with original X_valid{encoded_V_df.shape}-------------')
display(pd.concat([X_valid, encoded_V_df], axis=1).head(3))
out***********************************************************
X(891) = X_train(712) + X_valid(179)
-----------X_train(712, 5)-------------
pclass sex embarked sibsp parch
140 3 female C 0 2
439 2 male S 0 0
817 2 male C 1 1
indexは140から始まっています
-----------X_valid(179, 5)-------------
pclass sex embarked sibsp parch
495 3 male C 0 0
648 3 male S 0 0
278 3 male Q 4 1
indexは495から始まっています
-----------after encoding for X_train and convined with original X_train(712, 6)-------------
pclass sex embarked sibsp parch embarked_C embarked_Q embarked_S embarked_nan sex_female sex_male
0 3.0 male S 1.0 0.0 1.0 0.0 0.0 0.0 1.0 0.0
1 NaN NaN NaN NaN NaN 0.0 0.0 1.0 0.0 0.0 1.0
2 3.0 female S 0.0 0.0 1.0 0.0 0.0 0.0 0.0 1.0
indexが0から始まっていることが問題だと思います。
-----------after encoding for X_valid and convined with original X_valid(179, 6)-------------
pclass sex embarked sibsp parch embarked_C embarked_Q embarked_S embarked_nan sex_female sex_male
0 NaN NaN NaN NaN NaN 1.0 0.0 0.0 0.0 0.0 1.0
1 1.0 female C 1.0 0.0 0.0 0.0 1.0 0.0 0.0 1.0
2 NaN NaN NaN NaN NaN 0.0 1.0 0.0 0.0 0.0 1.0
indexが0から始まっていることが問題だと思います。
out***********************************************************
'''
(2)indexが0から始まるデータの場合(うまく行く)
'''
分割されたX_trainではなく、元々の X を使う(変数名はX_trainを使う)
X_train=X
print(f'\n-----------X_train{X_train.shape}-------------')
display(X_train.head(3))
変換する特徴量の定義
category_selected=['embarked', 'sex']
ohe = OneHotEncoder(sparse=False)
encoded_T = ohe.fit_transform(X_train[category_selected].values)
列名を取得
label = ohe.get_feature_names(category_selected)
データフレーム化
encoded_T_df = pd.DataFrame(encoded_T, columns=label, dtype=np.int8)
データフレームを結合
print(f'\n-----------after encoding for X_train and convined with original X_train{encoded_T_df.shape}-------------')
display(pd.concat([X_train, encoded_T_df], axis=1).head(3))
'''
out***********************************************************
-----------X_train(891, 5)-------------
pclass sex embarked sibsp parch
0 3 male S 1 0
1 1 female C 1 0
2 3 female S 0 0
-----------after encoding for X_train and convined with original X_train(891, 6)-------------
pclass sex embarked sibsp parch embarked_C embarked_Q embarked_S embarked_nan sex_female sex_male
0 3 male S 1 0 0 0 1 0 0 1
1 1 female C 1 0 1 0 0 0 1 0
2 3 female S 0 0 0 0 1 0 1 0
out***********************************************************
(3)category_encordersでのOneHotencodingを使ってうまく行ったコード
'''
import category_encoders as ce
X=df.drop('survived',axis=1)
y=df['survived']
X_train, X_valid, y_train, y_valid = train_test_split(X, y, test_size=0.2, random_state=0)
print(f'\n-----------X_train{X_train.shape}-------------')
display(X_train.head(3))
print(f'\n-----------X_valid{X_valid.shape}-------------')
display(X_valid.head(3))
category_selected=['sex','embarked']
ce_ohe = ce.OneHotEncoder(cols=category_selected, handle_unknown='ignore')
ce_encoded_T = ce_ohe.fit_transform(X_train)
ce_encoded_V = ce_ohe.transform(X_valid)
print(f'\n-----------after ce_OneHotencoding for X_train{ce_encoded_T.shape}-------------')
display(ce_encoded_T.head(3))
print(f'\n-----------after ce_OneHotencoding for X_valid{ce_encoded_V.shape}-------------')
display(ce_encoded_V.head(3))
nan_list=list(X_train[X_train['embarked'].isna()].index)
trainに含まれていた 'embarked'=nan がどのように変換されたのかチェックする
print("\n original data X_train esp. 'embarked'=nan -----------------------")
print(nan_list)
display(X_train.loc[nan_list])
print("\n 'nan' is classified as embarked_4 in encoded data -----------------------")
display(ce_encoded_T.loc[nan_list])
'''
out***********************************************************
-----------X_train(712, 5)-------------
pclass sex embarked sibsp parch
140 3 female C 0 2
439 2 male S 0 0
817 2 male C 1 1
-----------X_valid(179, 5)-------------
pclass sex embarked sibsp parch
495 3 male C 0 0
648 3 male S 0 0
278 3 male Q 4 1
-----------after ce_OneHotencoding for X_train(712, 9)-------------
pclass sex_1 sex_2 embarked_1 embarked_2 embarked_3 embarked_4 sibsp parch
140 3 1 0 1 0 0 0 0 2
439 2 0 1 0 1 0 0 0 0
817 2 0 1 1 0 0 0 1 1
-----------after ce_OneHotencoding for X_valid(179, 9)-------------
pclass sex_1 sex_2 embarked_1 embarked_2 embarked_3 embarked_4 sibsp parch
495 3 0 1 1 0 0 0 0 0
648 3 0 1 0 1 0 0 0 0
278 3 0 1 0 0 1 0 4 1
original data X_train esp. 'embarked'=nan -----------------------
[61, 829]
pclass sex embarked sibsp parch
61 1 female NaN 0 0
829 1 female NaN 0 0
'nan' is classified as embarked_4 in encoded data -----------------------
pclass sex_1 sex_2 embarked_1 embarked_2 embarked_3 embarked_4 sibsp parch
61 1 1 0 0 0 0 1 0 0
829 1 1 0 0 0 0 1 0 0