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()
price | yearOfRegistration | powerPS | kilometer | monthOfRegistration | |
---|---|---|---|---|---|
count | 3.715280e+05 | 371528.000000 | 371528.000000 | 371528.000000 | 371528.000000 |
mean | 1.729514e+04 | 2004.577997 | 115.549477 | 125618.688228 | 5.734445 |
std | 3.587954e+06 | 92.866598 | 192.139578 | 40112.337051 | 3.712412 |
min | 0.000000e+00 | 1000.000000 | 0.000000 | 5000.000000 | 0.000000 |
25% | 1.150000e+03 | 1999.000000 | 70.000000 | 125000.000000 | 3.000000 |
50% | 2.950000e+03 | 2003.000000 | 105.000000 | 150000.000000 | 6.000000 |
75% | 7.200000e+03 | 2008.000000 | 150.000000 | 150000.000000 | 9.000000 |
max | 2.147484e+09 | 9999.000000 | 20000.000000 | 150000.000000 | 12.000000 |
ここで注目するのは以下の2点です。
- max(最大値) と min(最小値)
- mean(平均値)との関係
「中古車の情報」という観点から、最大値と最小値が妥当な値を取っているかどうか考えてみましょう。
少し考えてみると、powerPS
とkilometer
は問題なさそうに見えます。
しかし、他の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
について調べます。monthOfRegistration
やyearOfRegistration
は、月や年を表すため、値がある程度決まっていました。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"]
サンプルごとに固有の値を持つ質的変数
削除する
コメント