機械学習回帰編 データクレンジング

import numpy as np
import pandas as pd
import pandas_profiling as pdp
import matplotlib.pyplot as plt
%matplotlib inline
from mpl_toolkits.mplot3d import Axes3D
import seaborn as sns
import pickle
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import r2_score
from sklearn.metrics import mean_squared_error
import xgboost as xgb
import lightbm as lgb
import warnings
warnings.simplefilter('ignore')
csvDataPath = 'autos.csv'
data = pd.read_csv(csvDataPath, encoding="cp1252")

num_data=data.select_dtypes(include='int164')
obj_data=data.select_dtypes(include'object')
lostlist=obj_data.columns[obj_data.isnull().sum()!=0]
complist=obj_data.columns[obj_data.isnull().sum()!=0]
lost_obj_data=obj_data[lostlist]
comp_obj_data=obj_data[complist]

量的変数の見直し

まずは、回帰に使った全ての変数dataについて、1つ1つ考えていきます。

まず、dataの量的変数は、本当に全てpriceに関係する変数なのでしょうか?

  • price:売却価格
  • yearOfRegistration:出品された年
  • powerPS:車の馬力
  • kilometer:出品時点の走行距離
  • monthOfRegistration:出品された月
  • nrOfPictures:出品広告の写真数
  • postalCode:サイトでランダムに割り振られた広告番号

値が1つしかない量的変数

1点目は、データフレームを見ればすぐに分かるはずです。

nrOfPicturesの列に、値が0しか並んでいないのです!

念のため.value_counts()で確かめてみましょう。

data["nrOfPictures"].value_counts()
0    371528
Name: nrOfPictures, dtype: int64

この出力より、nrOfPicturesの値は0のみであることが示されました。

つまり、この変数はpriceの値とは全く関係ありません!

変数の削除にはdelを使いましょう。引数delのあとに削除したい変数名を入力します。

del data["nrOfPictures"]

サンプルごとに固有の値を持つ量的変数

2点目は、変数の説明を見れば気付く方もいるでしょう。

postalCodeは、サイト側でランダムに割り振られた広告番号です。

postalCodeの値は商品ごとに異なるため、予測には全く役に立ちません。削除してしまいましょう。

del data["postalCode"]

外れ値の発見

これで量的変数は絞り込めました。

しかし、データクレンジングでは「各変数の値の種類」だけでなく「各変数の値の範囲」にも注目する必要があります。

外れ値があると、回帰モデルがその外れ値によって大きく歪んでしまい、全体の予測精度が悪化するからです。

deta.describe()
priceyearOfRegistrationpowerPSkilometermonthOfRegistration
count3.715280e+05371528.000000371528.000000371528.000000371528.000000
mean1.729514e+042004.577997115.549477125618.6882285.734445
std3.587954e+0692.866598192.13957840112.3370513.712412
min0.000000e+001000.0000000.0000005000.0000000.000000
25%1.150000e+031999.00000070.000000125000.0000003.000000
50%2.950000e+032003.000000105.000000150000.0000006.000000
75%7.200000e+032008.000000150.000000150000.0000009.000000
max2.147484e+099999.00000020000.000000150000.00000012.000000

ここで注目するのは以下の2点です。

  • max(最大値) と min(最小値)
  • mean(平均値)との関係

「中古車の情報」という観点から、最大値と最小値が妥当な値を取っているかどうか考えてみましょう。

少し考えてみると、powerPSkilometerは問題なさそうに見えます。

しかし、他の3変数はどうでしょう。

  • priceは中古車の販売価格なのに、最小値が0円になっている
  • priceの平均値(1.73×1041.73×104)に対して最大値(2.15×1092.15×109)が大きすぎる
  • yearOfRegistrationの最小値が1000,最大値が9999と、西暦を表す値としては異常
  • monthOfRegistrationの最小値が0と、月を表す値としてはおかしい

この4点がおかしいと感じられたら、データを細かく見ることができている証拠です。

それでは、それぞれの変数について外れ値を削除してみましょう。

外れ値の削除 年月データの場合

外れ値のある変数はprice/yearOfRegistration/monthOfRegistrationです。これらの変数について更に細かく調べ、外れ値を削除しましょう。まず、monthOfRegistrationの値の種類を調べます。値の種類を取得したい場合は.unique()を使います。見やすくするために、sorted()も使って形を整えましょう。

X = data["monthOfRegistration"].unique()
sorted(X)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

このように、1~12の月を表す値が入っており、0は異質です。しかし、この0は「不明(NaN)」を表すカテゴリーとも考えられます。よってmonthOfRegistrationには、実は外れ値は無いのです。次に、yearOfRegistrationも同様に見てみましょう。

X= data["yearOfRegistration"].unique()
sorted(X)

1900より小さな値(1800以下)、および2020より大きな値(2066以降)があります。これは西暦としては古すぎたり、存在しないものなので、削除しましょう。条件を指定してデータを抽出し、上書きします。

data = data[(data.yearOfRegistration < 2020 ) & (data.yearOfRegistration > 1900)]

外れ値の削除 数値データの場合

最後にpriceについて調べます。monthOfRegistrationyearOfRegistrationは、月や年を表すため、値がある程度決まっていました。priceは、連続値を取るため、その値の範囲は幅広いです。いったん.unique()で調べてみましょう。

X = data["price"].unique()
sorted(X)

値の種類が膨大なため、目視では外れ値の範囲は決定できません。そんなときは、分位点を活用する方法が有効です。分位点を計算するには.quantile()を使います。

.quantile()の引数には0.25などの割合を入力し、その値は以下のように解釈できます。

  • .quantile(0.01):この値より小さいデータの個数は、データ全体の1%である
  • .quantile(0.99):この値より小さいデータの個数は、データ全体の99%である
q1= data["price"].quantile(0.01)
q2= data["price"].quantile(0.99)
print(q1,q2)
data = data[(data["price"]> q1) & (data["price"] < q2)]
data.describe()

値がほぼ一つしかない質的変数

削除する

data["seller"].value_counts()

→
del data["seller"]

サンプルごとに固有の値を持つ質的変数

削除する

コメント

タイトルとURLをコピーしました