見出し画像

前処理大全:第6,7,8章

今回も前処理大全のコードを記載します。6~8章までの内容をまとめてますので参考にして頂けたらと思います。
*Pythonのみでの記載になります。

第6章:生成

6-1:アンダーサンプリングによる不均衡データの調整

本書では上記についてコードが紹介されてません。データの削減(重複データの削減等)ということで、生成とは少し違うのに加え、アンダーサンプリングを行うことは稀だそうです。

6-2:オーバーサンプリングにおける不均衡データの調整

オーバーサンプリング(オリジナルデータから新たなデータを生成)する手法の1つとしてSMOTEが紹介されてます。アルゴリズム概要は下記の通り。

①:生成元のデータからランダムに1つのデータを選択
②:設定したkの値を元に、1~kの整数値(一様分布)からランダムに選択肢nを設定
③:1で選択したデータにn番目に近いデータを新たに選択
④:1と3で選択したデータを元に新たなデータを生成
⑤:指定したデータ数に達するまで、1~4を繰り返す

Q:オーバーサンプリング

障害が起きてない(fault_flgがFalse)レコードが927件、障害が起きている(fault_flgがTrue)レコードが73件あります。障害が起きているレコードをSMOTEを用いてオーバーサンプリングを行い、障害が起きてないレコードの件数に近づける。なお、SMOTEのパラメータは5とする。

# SMOTE関数をライブラリから読み込み

from imblearn.over_sampling import SMOTE

# SMOTE関数の設定
# ratioは不均衡データに居置ける薄く名入れのデータを多い方のデータの何割まで増やすか設定
# (autoの場合は同じ数まで増やす、0.5と設定すると5割までデータを増やす)
# k_neighoborsはsmoteのkパラメータ
# randommM_stateは乱数のseed(乱数の生産パターンの元)
sm = SMOTE(sampling_strategy='auto', k_neighbors=5, random_state=71)

# オーバーサンプリングの実行
blance_date, balance_target = sm.fit_resample(production_tb[['length', 'thickness']], production_tb['fault_flg'])

第7章:展開

7-1:横持ちへの変換

Q:横持ち変換

予約テーブルから「顧客・宿泊人数」ごとに予約数をカウントし、行を顧客ID、列を宿泊人数、値を予約数の行列に変換。

# pivot_table関数で横持ち変換と集約処理を同時実行
# aggfuncに予約数をカウントする関数を指定
pd.pivot_table(reserve_tb, index='customer_id', columns='people_num', values='reserve_id', aggfunc=lambda x : len(x), fill_value=0)

7-2:スパースマトリックスへの変換

縦持ちから横持ちに変換するとデータサイズが膨れ上がってしまう場合があります。それは変換するとスパースマトリックスになってしまう場合です。 スパーづマトリックスとは、ほとんどの要素の値が0でごくわずかしか値が存在しない巨大な行列(表)のことです。 簡単にいうと「横持ちかつ見やすくしよう」という感じですね。

Q:スパースマトリックス

前節の例題(横持ち変換で作成した行列)をスパースマトリックスとして生成。

# スパースマトリックスのライブラリを読み込み
from scipy.sparse import csc_matrix

# 顧客ID/宿泊人数別の予約数の表を生成
cnt_tb = reserve_tb.groupby(['customer_id', 'people_num'])['reserve_id'].size().reset_index()
cnt_tb.columns = ['customer_id', 'people_num', 'rsv_cnt']

# sparseMatrixの行/列に該当する列の値をカテゴリ型に変換
customer_id = pd.Categorical(cnt_tb['customer_id'])
people_num = pd.Categorical(cnt_tb['people_num'])

# スパースマトリックスに生成
# 1の引数は、指定した行列に対応した値、行番号、列番号の配列をまとめたタプルを指定
# shapeには、スパースマトリックスのサイズを指定(行数/列数のタプルを指定)
# (customer_id.codesはインデックス番号の取得)
# (len(customer_id.categories)は、customer_idのユニークな数を取得)
csc_matrix((cnt_tb['rsv_cnt'], (customer_id.codes, people_num.codes)),
          shape=(len(customer_id.categories), len(people_num.categories)))

第8章:数値型

8-1:数値型への変換

Q:数値型への変換

40000/3をさまざまな数値のデータ型に変換

# データ型の確認
type(40000 / 3)

# 整数型へ変換
int(40000 / 3)

# 浮動小数点型へ変換
# float(40000 / 3)

df = pd.DataFrame({'value' : [40000 / 3]})

# データ型の確認

# 整数型へ変換
df['value'].astype('int8')
df['value'].astype('int16')
df['value'].astype('int32')
df['value'].astype('int64')

# 浮動小数点型へ変換
df['value'].astype('float16')
df['value'].astype('float32')
df['value'].astype('float64')
df['value'].astype('float128')

# 下記のようにPythonのデータ型を指定できる
df['value'].astype(int)
df['value'].astype(float)

8-2:対数化による非線形な変化

Q:対数化

予約テーブルのtotal_priceを1,000で割ってから、底10で割って対数化しましょう。

reserve_tb['total_price_log'] = reserve_tb['total_price'].apply(lambda x : np.log10(x / 1000 + 1))
reserve_tb.head()

8-3:カテゴリ化による非線形な変化

Q:数値型のカテゴリ化

顧客テーブルの年齢を10きざみのカテゴリ型として追加しましょう。

customer_tb['age_rang'] = (np.floor(customer_tb['age'] / 10) * 10).astype('category')
customer_tb.head()

8-4:正規化

Q:正規化

予約テーブルの予約人数(people_num)と合計金額(total_price)を平均0、分散1の分布に変換して正規化をしましょう。

from sklearn.preprocessing import StandardScaler

# 小数点以下を扱えるようにするためfloat型に変換
reserve_tb['people_num']  = reserve_tb['people_num'].astype(float)

# 正規化を行うオブジェクトを生成
ss = StandardScaler()

# fit_transform関数は、fit関数(正規化するための前準備の計算)と
# transform関数(準備された情報から正規化の変換処理を行う)の両方を行う
result = ss.fit_transform(reserve_tb[['people_num', 'total_price']])

reserve_tb['people_num_normalized'] = [x[0] for x in result]
reserve_tb['total_price_normalized'] = [x[1] for x in result]

reserve_tb.head()

8-5:外れ値の除去

Q:標準偏差基準の外れ値の除去

予約テーブルの予約合計金額(total_price)において、平均値から標準偏差値の3倍以内の値に収まる予約テーブルのみに絞りましょう

reserve_tb = reserve_tb[(abs(reserve_tb['total_price'] - np.mean(reserve_tb['total_price'])) / np.std(reserve_tb['total_price'], ddof=0) <= 3)
].reset_index(drop=True)

reserve_tb

8-6:主成分分析による次元圧縮

Q:主成分分析による次元圧縮

製造レコードのlengthとthicknessを1次元に圧縮しましょう

# PCA読み込み
from sklearn.decomposition import PCA

# n_componentsに、主成分分析で変換後の次元数を設定
pca = PCA(n_components=2)

# 主成分分析を実行
# pcaに主成分分析の変換パラメータが保存され、返り値に主成分分析後の値が返される
pca_values = pca.fit_transform(production_tb[['length', 'thickness']])

# 累積寄与率と寄与率の確認
print('累積寄与率 : {0}'.format(sum(pca.explained_variance_ratio_)))
print('各次元の寄与率 : {0}'.format(pca.explained_variance_ratio_))

# predict関数を利用し、同じ次元圧縮処理を実行
pca_newvalues = pca.transform(production_tb[['length', 'thickness']])

8-7:数値型の補完

Q:欠損レコードの削除

thicknessが欠損しているレコードを削除しましょう

production_missing_num_tb = pd.read_csv('production_missing_num.csv', encoding='UTF-8')

# replace関数によってNoneをnanに変換
# (Noneを指定する際には文字列として指定する必要がある)
production_missing_num_tb.replace('None', np.nan, inplace=True)

# dropna関数によって、thickenessにnanを含むレコードを削除
production_missing_num_tb.dropna(subset=['thickness'], inplace=True)

Q:定数補完

欠損しているthicknessを1の値で補完しましょう

production_missing_num_tb = pd.read_csv('production_missing_num.csv', encoding='UTF-8')

# replace関数によってNoneをnanに変換
# (Noneを指定する際には文字列として指定する必要がある)
production_missing_num_tb.replace('None', np.nan, inplace=True)

# fillna関数によって、thicknessの欠損値を1で補完
production_missing_num_tb['thickness'].fillna(1, inplace=True)

Q:平均値補完

欠損しているthicknessを欠損していないthicknessの平均値で補完しましょう

production_missing_num_tb = pd.read_csv('production_missing_num.csv', encoding='UTF-8')

# replace関数によってNoneをnanに変換
# (Noneを指定する際には文字列として指定する必要がある)
production_missing_num_tb.replace('None', np.nan, inplace=True)

# thicknessを数値型に変換(Noneが混ざっているため数値型になっていない)
production_missing_num_tb['thickness'] = production_missing_num_tb['thickness'].astype('float64')

# thicknessの平均値を計算
thickness_mean = production_missing_num_tb['thickness'].mean()

# thicknessの欠損値をthicknessの平均値で補完
production_missing_num_tb['thickness'].fillna(thickness_mean, inplace=True)

Q:PMMによる多重代入

欠損しているthicknessの値を多重代入法で補完PMMを簡単に説明すると以下のような手順になります

1.欠損データを除いたデータから欠損データを予測する回帰モデルを構築
2.構築した回帰モデルの計数と誤差分散の分布を計算
3.係数と誤差分散の分布から新たな係数と誤差分散の値を生成
4.で生成した係数と誤差分散の値に従った回帰モデルから予測値を計算
5.欠損していない観測データの中から予測値に最も近いデータを補完値として採用
6.データを補完して新たな回帰モデルの係数と誤差分散の分布を計算、3に戻る

3-6を補完する値の分布が安定するまで繰り返し、安定してから指定したデータセットの数分の補完値が得られたら終了とする。

from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer

# replase関数によって、Noneをnanに変換
production_missing_num_tb.replace('None', np.nan, inplace=True)

# データ型を変換
production_missing_num_tb['thickness'] = production_missing_num_tb['thickness'].astype('float64')
production_missing_num_tb['type'] = production_missing_num_tb['type'].astype('category')
production_missing_num_tb['fault_flg'] = production_missing_num_tb['fault_flg'].astype('category')

# ダミー変数化
production_dummy_flg = pd.get_dummies(
    production_missing_num_tb[['type', 'fault_flg']], drop_first=True
)

# IterativeImputerのインスタンスを作成
imputer = IterativeImputer()

imputed_data = imputer.fit_transform(
    pd.concat([production_missing_num_tb[['length', 'thickness']], production_dummy_flg], axis=1)
)


サポートして頂いたお金は開業資金に充てさせて頂きます。 目標は自転車好きが集まる場所を作る事です。 お気持ち程度でいいのでサポートお願い致します!