数量化理論をPythonで理解する

数量化理論とは、数値ではない「カテゴリカルデータ」と呼ばれるデータをいかに統計学の世界に招き入れるかという理論で、数量化I類、数量化II類などが有名です。

### 数量化I類・拡張型数量化I類

重回帰分析などの回帰分析は、数値データを説明変数とし、数値データを目的変数として予測します。一方で、数値ではないカテゴリカルデータを説明変数とし、数値データを目的変数として予測するのが数量化I類です。説明変数に数値データとカテゴリカルが混在している場合は拡張型数量化I類と呼ばれます。

### 数量化II類・拡張型数量化II類

ロジスティック回帰や判別分析などは、数値データを説明変数とし、カテゴリカルデータを目的変数として予測するのに使われます。一方で、数値ではないカテゴリカルデータを説明変数とし、カテゴリカルデータを目的変数として予測するのが数量化II類です。説明変数に数値データとカテゴリカルデータが混在している場合は拡張型数量化II類と呼ばれます。

# １９８５年自動車価格のデータを例に説明します。

UCI Machine Learning Repository の Automobile のデータ http://archive.ics.uci.edu/ml/datasets/Automobile を少し改変したものを利用します。


```python
# URL によるリソースへのアクセスを提供するライブラリをインポートする
import urllib.request 

# URLを指定してテキストデータをダウンロードする
url = "https://raw.githubusercontent.com/maskot1977/ipython_notebook/master/toydata/auto-imports-1985.txt"
urllib.request.urlretrieve(url, 'auto-imports-1985.txt') 
```




    ('auto-imports-1985.txt', <http.client.HTTPMessage at 0x10f056780>)




```python
# 表形式の計算をサポートするライブラリのインポート
import pandas as pd

# ダウンロードしたデータを読み込む
df = pd.read_csv("auto-imports-1985.txt", sep="\t", index_col=0)
df.head()

# 実は、次のように直接URLを指定しても読み込めるが、
# 当然、そのときインターネットに接続していなければいけません
# df = pd.read_csv("https://raw.githubusercontent.com/maskot1977/ipython_notebook/master/toydata/auto-imports-1985.txt", sep="\t", index_col=0)
```

<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>symboling</th>
      <th>normalized-losses</th>
      <th>make</th>
      <th>fuel-type</th>
      <th>aspiration</th>
      <th>num-of-doors</th>
      <th>body-style</th>
      <th>drive-wheels</th>
      <th>engine-location</th>
      <th>wheel-base</th>
      <th>...</th>
      <th>engine-size</th>
      <th>fuel-system</th>
      <th>bore</th>
      <th>stroke</th>
      <th>compression-ratio</th>
      <th>horsepower</th>
      <th>peak-rpm</th>
      <th>city-mpg</th>
      <th>highway-mpg</th>
      <th>price</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>3</td>
      <td>NaN</td>
      <td>alfa-romero</td>
      <td>gas</td>
      <td>std</td>
      <td>two</td>
      <td>convertible</td>
      <td>rwd</td>
      <td>front</td>
      <td>88.6</td>
      <td>...</td>
      <td>130</td>
      <td>mpfi</td>
      <td>3.47</td>
      <td>2.68</td>
      <td>9.0</td>
      <td>111.0</td>
      <td>5000.0</td>
      <td>21</td>
      <td>27</td>
      <td>13495.0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>3</td>
      <td>NaN</td>
      <td>alfa-romero</td>
      <td>gas</td>
      <td>std</td>
      <td>two</td>
      <td>convertible</td>
      <td>rwd</td>
      <td>front</td>
      <td>88.6</td>
      <td>...</td>
      <td>130</td>
      <td>mpfi</td>
      <td>3.47</td>
      <td>2.68</td>
      <td>9.0</td>
      <td>111.0</td>
      <td>5000.0</td>
      <td>21</td>
      <td>27</td>
      <td>16500.0</td>
    </tr>
    <tr>
      <th>2</th>
      <td>1</td>
      <td>NaN</td>
      <td>alfa-romero</td>
      <td>gas</td>
      <td>std</td>
      <td>two</td>
      <td>hatchback</td>
      <td>rwd</td>
      <td>front</td>
      <td>94.5</td>
      <td>...</td>
      <td>152</td>
      <td>mpfi</td>
      <td>2.68</td>
      <td>3.47</td>
      <td>9.0</td>
      <td>154.0</td>
      <td>5000.0</td>
      <td>19</td>
      <td>26</td>
      <td>16500.0</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2</td>
      <td>164.0</td>
      <td>audi</td>
      <td>gas</td>
      <td>std</td>
      <td>four</td>
      <td>sedan</td>
      <td>fwd</td>
      <td>front</td>
      <td>99.8</td>
      <td>...</td>
      <td>109</td>
      <td>mpfi</td>
      <td>3.19</td>
      <td>3.40</td>
      <td>10.0</td>
      <td>102.0</td>
      <td>5500.0</td>
      <td>24</td>
      <td>30</td>
      <td>13950.0</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2</td>
      <td>164.0</td>
      <td>audi</td>
      <td>gas</td>
      <td>std</td>
      <td>four</td>
      <td>sedan</td>
      <td>4wd</td>
      <td>front</td>
      <td>99.4</td>
      <td>...</td>
      <td>136</td>
      <td>mpfi</td>
      <td>3.19</td>
      <td>3.40</td>
      <td>8.0</td>
      <td>115.0</td>
      <td>5500.0</td>
      <td>18</td>
      <td>22</td>
      <td>17450.0</td>
    </tr>
  </tbody>
</table>
<p>5 rows × 26 columns</p>
</div>



数字のデータと、数字ではないデータ（カテゴリカルデータ）が混在してますね。

# データの前処理

## 説明変数Xと目的変数Yに分解

説明変数Xと目的変数Yに分解しましょう。この説明変数Xから目的変数Yを予測することを目指します。


```python
X = df.iloc[:, :-1]
Y = df.iloc[:, -1]
```


```python
# 説明変数
X.head()
```




<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>symboling</th>
      <th>normalized-losses</th>
      <th>make</th>
      <th>fuel-type</th>
      <th>aspiration</th>
      <th>num-of-doors</th>
      <th>body-style</th>
      <th>drive-wheels</th>
      <th>engine-location</th>
      <th>wheel-base</th>
      <th>...</th>
      <th>num-of-cylinders</th>
      <th>engine-size</th>
      <th>fuel-system</th>
      <th>bore</th>
      <th>stroke</th>
      <th>compression-ratio</th>
      <th>horsepower</th>
      <th>peak-rpm</th>
      <th>city-mpg</th>
      <th>highway-mpg</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>3</td>
      <td>NaN</td>
      <td>alfa-romero</td>
      <td>gas</td>
      <td>std</td>
      <td>two</td>
      <td>convertible</td>
      <td>rwd</td>
      <td>front</td>
      <td>88.6</td>
      <td>...</td>
      <td>four</td>
      <td>130</td>
      <td>mpfi</td>
      <td>3.47</td>
      <td>2.68</td>
      <td>9.0</td>
      <td>111.0</td>
      <td>5000.0</td>
      <td>21</td>
      <td>27</td>
    </tr>
    <tr>
      <th>1</th>
      <td>3</td>
      <td>NaN</td>
      <td>alfa-romero</td>
      <td>gas</td>
      <td>std</td>
      <td>two</td>
      <td>convertible</td>
      <td>rwd</td>
      <td>front</td>
      <td>88.6</td>
      <td>...</td>
      <td>four</td>
      <td>130</td>
      <td>mpfi</td>
      <td>3.47</td>
      <td>2.68</td>
      <td>9.0</td>
      <td>111.0</td>
      <td>5000.0</td>
      <td>21</td>
      <td>27</td>
    </tr>
    <tr>
      <th>2</th>
      <td>1</td>
      <td>NaN</td>
      <td>alfa-romero</td>
      <td>gas</td>
      <td>std</td>
      <td>two</td>
      <td>hatchback</td>
      <td>rwd</td>
      <td>front</td>
      <td>94.5</td>
      <td>...</td>
      <td>six</td>
      <td>152</td>
      <td>mpfi</td>
      <td>2.68</td>
      <td>3.47</td>
      <td>9.0</td>
      <td>154.0</td>
      <td>5000.0</td>
      <td>19</td>
      <td>26</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2</td>
      <td>164.0</td>
      <td>audi</td>
      <td>gas</td>
      <td>std</td>
      <td>four</td>
      <td>sedan</td>
      <td>fwd</td>
      <td>front</td>
      <td>99.8</td>
      <td>...</td>
      <td>four</td>
      <td>109</td>
      <td>mpfi</td>
      <td>3.19</td>
      <td>3.40</td>
      <td>10.0</td>
      <td>102.0</td>
      <td>5500.0</td>
      <td>24</td>
      <td>30</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2</td>
      <td>164.0</td>
      <td>audi</td>
      <td>gas</td>
      <td>std</td>
      <td>four</td>
      <td>sedan</td>
      <td>4wd</td>
      <td>front</td>
      <td>99.4</td>
      <td>...</td>
      <td>five</td>
      <td>136</td>
      <td>mpfi</td>
      <td>3.19</td>
      <td>3.40</td>
      <td>8.0</td>
      <td>115.0</td>
      <td>5500.0</td>
      <td>18</td>
      <td>22</td>
    </tr>
  </tbody>
</table>
<p>5 rows × 25 columns</p>
</div>




```python
# 目的変数
pd.DataFrame(Y).head()
```



<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>price</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>13495.0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>16500.0</td>
    </tr>
    <tr>
      <th>2</th>
      <td>16500.0</td>
    </tr>
    <tr>
      <th>3</th>
      <td>13950.0</td>
    </tr>
    <tr>
      <th>4</th>
      <td>17450.0</td>
    </tr>
  </tbody>
</table>
</div>



## カテゴリカルデータをダミー変数に変換

pandas.get_dummies() を用いて、カテゴリカルデータをダミー変数に変換します。ダミー変数とは、そのカテゴリーに属すれば１、属さなければ０の変数です。dummy_na=True を指定すると、データが NaN（欠損値） の場合に１、欠損でなければ０とします。

重回帰分析などでは、カテゴリーの数がN個ある場合、N個のダミー変数を作ると予測できないため、どれか1個の変数を除外します。scikit-learnの重回帰分析 LinearRegression() では、この問題を回避する設計にしているようで、N個のダミー変数を作成しても動作します。

なお、pandas.get_dummies(drop_first=True) とすると、ダミー変数を作成するときに最初のカテゴリーを無視します。 


```python
X = pd.get_dummies(X, dummy_na=True)
X.head()
```


<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>symboling</th>
      <th>normalized-losses</th>
      <th>wheel-base</th>
      <th>length</th>
      <th>width</th>
      <th>height</th>
      <th>curb-weight</th>
      <th>engine-size</th>
      <th>bore</th>
      <th>stroke</th>
      <th>...</th>
      <th>num-of-cylinders_nan</th>
      <th>fuel-system_1bbl</th>
      <th>fuel-system_2bbl</th>
      <th>fuel-system_4bbl</th>
      <th>fuel-system_idi</th>
      <th>fuel-system_mfi</th>
      <th>fuel-system_mpfi</th>
      <th>fuel-system_spdi</th>
      <th>fuel-system_spfi</th>
      <th>fuel-system_nan</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>3</td>
      <td>NaN</td>
      <td>88.6</td>
      <td>168.8</td>
      <td>64.1</td>
      <td>48.8</td>
      <td>2548</td>
      <td>130</td>
      <td>3.47</td>
      <td>2.68</td>
      <td>...</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>3</td>
      <td>NaN</td>
      <td>88.6</td>
      <td>168.8</td>
      <td>64.1</td>
      <td>48.8</td>
      <td>2548</td>
      <td>130</td>
      <td>3.47</td>
      <td>2.68</td>
      <td>...</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>2</th>
      <td>1</td>
      <td>NaN</td>
      <td>94.5</td>
      <td>171.2</td>
      <td>65.5</td>
      <td>52.4</td>
      <td>2823</td>
      <td>152</td>
      <td>2.68</td>
      <td>3.47</td>
      <td>...</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2</td>
      <td>164.0</td>
      <td>99.8</td>
      <td>176.6</td>
      <td>66.2</td>
      <td>54.3</td>
      <td>2337</td>
      <td>109</td>
      <td>3.19</td>
      <td>3.40</td>
      <td>...</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2</td>
      <td>164.0</td>
      <td>99.4</td>
      <td>176.6</td>
      <td>66.4</td>
      <td>54.3</td>
      <td>2824</td>
      <td>136</td>
      <td>3.19</td>
      <td>3.40</td>
      <td>...</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
  </tbody>
</table>
<p>5 rows × 85 columns</p>



## 数値データの欠損値を補間

pandas.get_dummies() では、カテゴリカルデータの欠損値は「欠損値」という値に変換しますが、数値データの欠損値は補間されません。補間する方法として pandas.DataFrame.fillna() があります。詳しくは pd.DataFrame.fillna? と入力して調べてみてください。

なお、欠損値を補間するのではなく、欠損値のあるデータを取り除きたい場合は pd.DataFrame.dropna() とします。


```python
X = X.fillna(X.median())
X.head()
```


<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>symboling</th>
      <th>normalized-losses</th>
      <th>wheel-base</th>
      <th>length</th>
      <th>width</th>
      <th>height</th>
      <th>curb-weight</th>
      <th>engine-size</th>
      <th>bore</th>
      <th>stroke</th>
      <th>...</th>
      <th>num-of-cylinders_nan</th>
      <th>fuel-system_1bbl</th>
      <th>fuel-system_2bbl</th>
      <th>fuel-system_4bbl</th>
      <th>fuel-system_idi</th>
      <th>fuel-system_mfi</th>
      <th>fuel-system_mpfi</th>
      <th>fuel-system_spdi</th>
      <th>fuel-system_spfi</th>
      <th>fuel-system_nan</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>3</td>
      <td>115.0</td>
      <td>88.6</td>
      <td>168.8</td>
      <td>64.1</td>
      <td>48.8</td>
      <td>2548</td>
      <td>130</td>
      <td>3.47</td>
      <td>2.68</td>
      <td>...</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>3</td>
      <td>115.0</td>
      <td>88.6</td>
      <td>168.8</td>
      <td>64.1</td>
      <td>48.8</td>
      <td>2548</td>
      <td>130</td>
      <td>3.47</td>
      <td>2.68</td>
      <td>...</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>2</th>
      <td>1</td>
      <td>115.0</td>
      <td>94.5</td>
      <td>171.2</td>
      <td>65.5</td>
      <td>52.4</td>
      <td>2823</td>
      <td>152</td>
      <td>2.68</td>
      <td>3.47</td>
      <td>...</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2</td>
      <td>164.0</td>
      <td>99.8</td>
      <td>176.6</td>
      <td>66.2</td>
      <td>54.3</td>
      <td>2337</td>
      <td>109</td>
      <td>3.19</td>
      <td>3.40</td>
      <td>...</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2</td>
      <td>164.0</td>
      <td>99.4</td>
      <td>176.6</td>
      <td>66.4</td>
      <td>54.3</td>
      <td>2824</td>
      <td>136</td>
      <td>3.19</td>
      <td>3.40</td>
      <td>...</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
    </tr>
  </tbody>
</table>
<p>5 rows × 85 columns</p>




## 分散値がゼロの列を取り除く

分散値がゼロの列は予測に使えません。以下のようにして取り除きます。列の数の変化を確認してください。


```python
X = X.iloc[:, [i for i, x in enumerate(X.var()) if x != 0]]
X.head()
```




<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>symboling</th>
      <th>normalized-losses</th>
      <th>wheel-base</th>
      <th>length</th>
      <th>width</th>
      <th>height</th>
      <th>curb-weight</th>
      <th>engine-size</th>
      <th>bore</th>
      <th>stroke</th>
      <th>...</th>
      <th>num-of-cylinders_twelve</th>
      <th>num-of-cylinders_two</th>
      <th>fuel-system_1bbl</th>
      <th>fuel-system_2bbl</th>
      <th>fuel-system_4bbl</th>
      <th>fuel-system_idi</th>
      <th>fuel-system_mfi</th>
      <th>fuel-system_mpfi</th>
      <th>fuel-system_spdi</th>
      <th>fuel-system_spfi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>3</td>
      <td>115.0</td>
      <td>88.6</td>
      <td>168.8</td>
      <td>64.1</td>
      <td>48.8</td>
      <td>2548</td>
      <td>130</td>
      <td>3.47</td>
      <td>2.68</td>
      <td>...</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>3</td>
      <td>115.0</td>
      <td>88.6</td>
      <td>168.8</td>
      <td>64.1</td>
      <td>48.8</td>
      <td>2548</td>
      <td>130</td>
      <td>3.47</td>
      <td>2.68</td>
      <td>...</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>2</th>
      <td>1</td>
      <td>115.0</td>
      <td>94.5</td>
      <td>171.2</td>
      <td>65.5</td>
      <td>52.4</td>
      <td>2823</td>
      <td>152</td>
      <td>2.68</td>
      <td>3.47</td>
      <td>...</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2</td>
      <td>164.0</td>
      <td>99.8</td>
      <td>176.6</td>
      <td>66.2</td>
      <td>54.3</td>
      <td>2337</td>
      <td>109</td>
      <td>3.19</td>
      <td>3.40</td>
      <td>...</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2</td>
      <td>164.0</td>
      <td>99.4</td>
      <td>176.6</td>
      <td>66.4</td>
      <td>54.3</td>
      <td>2824</td>
      <td>136</td>
      <td>3.19</td>
      <td>3.40</td>
      <td>...</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
    </tr>
  </tbody>
</table>
<p>5 rows × 76 columns</p>



## サンプル数が１のカテゴリカルデータを取り除く

サンプル数がゼロのカテゴリカルデータは予測に使えません。以下のようにして取り除きます。列の数の変化を確認してください。


```python
X = X.iloc[:, [i for i, x in enumerate(X.sum()) if x != 1]]
X.head()
```



<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>symboling</th>
      <th>normalized-losses</th>
      <th>wheel-base</th>
      <th>length</th>
      <th>width</th>
      <th>height</th>
      <th>curb-weight</th>
      <th>engine-size</th>
      <th>bore</th>
      <th>stroke</th>
      <th>...</th>
      <th>num-of-cylinders_five</th>
      <th>num-of-cylinders_four</th>
      <th>num-of-cylinders_six</th>
      <th>num-of-cylinders_two</th>
      <th>fuel-system_1bbl</th>
      <th>fuel-system_2bbl</th>
      <th>fuel-system_4bbl</th>
      <th>fuel-system_idi</th>
      <th>fuel-system_mpfi</th>
      <th>fuel-system_spdi</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>3</td>
      <td>115.0</td>
      <td>88.6</td>
      <td>168.8</td>
      <td>64.1</td>
      <td>48.8</td>
      <td>2548</td>
      <td>130</td>
      <td>3.47</td>
      <td>2.68</td>
      <td>...</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
    </tr>
    <tr>
      <th>1</th>
      <td>3</td>
      <td>115.0</td>
      <td>88.6</td>
      <td>168.8</td>
      <td>64.1</td>
      <td>48.8</td>
      <td>2548</td>
      <td>130</td>
      <td>3.47</td>
      <td>2.68</td>
      <td>...</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
    </tr>
    <tr>
      <th>2</th>
      <td>1</td>
      <td>115.0</td>
      <td>94.5</td>
      <td>171.2</td>
      <td>65.5</td>
      <td>52.4</td>
      <td>2823</td>
      <td>152</td>
      <td>2.68</td>
      <td>3.47</td>
      <td>...</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
    </tr>
    <tr>
      <th>3</th>
      <td>2</td>
      <td>164.0</td>
      <td>99.8</td>
      <td>176.6</td>
      <td>66.2</td>
      <td>54.3</td>
      <td>2337</td>
      <td>109</td>
      <td>3.19</td>
      <td>3.40</td>
      <td>...</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
    </tr>
    <tr>
      <th>4</th>
      <td>2</td>
      <td>164.0</td>
      <td>99.4</td>
      <td>176.6</td>
      <td>66.4</td>
      <td>54.3</td>
      <td>2824</td>
      <td>136</td>
      <td>3.19</td>
      <td>3.40</td>
      <td>...</td>
      <td>1</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>0</td>
      <td>1</td>
      <td>0</td>
    </tr>
  </tbody>
</table>
<p>5 rows × 70 columns</p>



## エラーを起こす行を除外

以上で、エラーを起こしそうな原因はできるだけ取り除いたつもりですが、実際にはそれでもなぜかエラーを起こす行が残っていたりします。そのような場合、１行ずつ加えながら解析を実行し、エラーを起こす行を特定しながら取り除いていきます。


```python
from sklearn import linear_model
safe = []
droplist = []
for i in range(len(X)):
    try:
        clf = linear_model.LinearRegression() # 重回帰分析
        clf.fit(X.iloc[safe + [i], :], Y.iloc[safe + [i]])
        safe.append(i)
    except:
        droplist.append(i)
```


上記のコードにより、エラーを起こさない列の番号を safe というリストに、エラーを起こす列の番号を droplist というリストに格納しました。droplist の中身は次のようになります。


```python
droplist
```




    [9, 44, 45, 129]



エラーを起こさない行を集めて、それをもとに説明変数Xと目的変数Yを作り直します。


```python
X = X.iloc[safe, :]
Y = Y.iloc[safe]
```

# 機械学習と交差検定

ここまでくれば、あとは重回帰分析でも何でも来いです。以下のコードでは、１００回交差検定を行って、テストセットの予測精度を見積もっています。


```python
import numpy as np
from sklearn.model_selection import train_test_split
result_scores = []
for _ in range(100):
    X_train, X_test, Y_train, Y_test = train_test_split(X, Y)
    clf = linear_model.LinearRegression()
    clf.fit(X_train, Y_train)
    result_scores.append(clf.score(X_test, Y_test))
print('{0:.4f} ± {1:.4f}'.format(np.mean(result_scores), np.std(result_scores)))
```

    0.8402 ± 0.1195


# 結果の解釈

普通の重回帰分析においては、回帰係数は、目的変数を予測するときの傾きという解釈ができます。カテゴリカルデータを用いた場合はどうでしょうか。


```python
clf = linear_model.LinearRegression()
clf.fit(X, Y)
coefs = pd.DataFrame(clf.coef_, index=X.columns).sort_values(0, ascending=False)
coefs # 回帰係数を大きい順に並べたもの
```


<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>0</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>make_bmw</th>
      <td>10041.151756</td>
    </tr>
    <tr>
      <th>make_porsche</th>
      <td>7829.488014</td>
    </tr>
    <tr>
      <th>make_audi</th>
      <td>6605.635485</td>
    </tr>
    <tr>
      <th>engine-type_l</th>
      <td>6530.190701</td>
    </tr>
    <tr>
      <th>make_saab</th>
      <td>6380.589720</td>
    </tr>
    <tr>
      <th>make_mercedes-benz</th>
      <td>5948.369828</td>
    </tr>
    <tr>
      <th>num-of-cylinders_eight</th>
      <td>5893.599864</td>
    </tr>
    <tr>
      <th>fuel-type_diesel</th>
      <td>3607.600803</td>
    </tr>
    <tr>
      <th>fuel-system_idi</th>
      <td>3607.600803</td>
    </tr>
    <tr>
      <th>make_alfa-romero</th>
      <td>3410.184970</td>
    </tr>
    <tr>
      <th>num-of-cylinders_two</th>
      <td>3198.595695</td>
    </tr>
    <tr>
      <th>engine-type_rotor</th>
      <td>3198.595695</td>
    </tr>
    <tr>
      <th>engine-location_rear</th>
      <td>2856.516426</td>
    </tr>
    <tr>
      <th>num-of-cylinders_four</th>
      <td>2739.959484</td>
    </tr>
    <tr>
      <th>make_volkswagen</th>
      <td>2697.045849</td>
    </tr>
    <tr>
      <th>make_jaguar</th>
      <td>2558.651437</td>
    </tr>
    <tr>
      <th>num-of-cylinders_six</th>
      <td>2208.090711</td>
    </tr>
    <tr>
      <th>body-style_convertible</th>
      <td>2131.983958</td>
    </tr>
    <tr>
      <th>make_mazda</th>
      <td>1866.481690</td>
    </tr>
    <tr>
      <th>make_nissan</th>
      <td>1539.816016</td>
    </tr>
    <tr>
      <th>fuel-system_2bbl</th>
      <td>1450.615300</td>
    </tr>
    <tr>
      <th>make_honda</th>
      <td>1332.692521</td>
    </tr>
    <tr>
      <th>make_volvo</th>
      <td>1213.565871</td>
    </tr>
    <tr>
      <th>aspiration_turbo</th>
      <td>984.516339</td>
    </tr>
    <tr>
      <th>engine-type_ohcf</th>
      <td>806.421738</td>
    </tr>
    <tr>
      <th>width</th>
      <td>625.621317</td>
    </tr>
    <tr>
      <th>drive-wheels_rwd</th>
      <td>473.746006</td>
    </tr>
    <tr>
      <th>make_renault</th>
      <td>404.114694</td>
    </tr>
    <tr>
      <th>make_toyota</th>
      <td>377.790964</td>
    </tr>
    <tr>
      <th>make_isuzu</th>
      <td>358.242593</td>
    </tr>
    <tr>
      <th>...</th>
      <td>...</td>
    </tr>
    <tr>
      <th>normalized-losses</th>
      <td>-12.312491</td>
    </tr>
    <tr>
      <th>city-mpg</th>
      <td>-42.229906</td>
    </tr>
    <tr>
      <th>body-style_hardtop</th>
      <td>-75.642611</td>
    </tr>
    <tr>
      <th>length</th>
      <td>-136.954058</td>
    </tr>
    <tr>
      <th>num-of-doors_nan</th>
      <td>-163.376963</td>
    </tr>
    <tr>
      <th>num-of-cylinders_five</th>
      <td>-327.028649</td>
    </tr>
    <tr>
      <th>height</th>
      <td>-405.768728</td>
    </tr>
    <tr>
      <th>body-style_sedan</th>
      <td>-440.124658</td>
    </tr>
    <tr>
      <th>symboling</th>
      <td>-444.678768</td>
    </tr>
    <tr>
      <th>drive-wheels_fwd</th>
      <td>-671.983102</td>
    </tr>
    <tr>
      <th>body-style_wagon</th>
      <td>-712.745083</td>
    </tr>
    <tr>
      <th>compression-ratio</th>
      <td>-799.095043</td>
    </tr>
    <tr>
      <th>fuel-system_spdi</th>
      <td>-860.917681</td>
    </tr>
    <tr>
      <th>body-style_hatchback</th>
      <td>-903.471605</td>
    </tr>
    <tr>
      <th>aspiration_std</th>
      <td>-984.516339</td>
    </tr>
    <tr>
      <th>fuel-system_1bbl</th>
      <td>-1094.045556</td>
    </tr>
    <tr>
      <th>stroke</th>
      <td>-1290.742175</td>
    </tr>
    <tr>
      <th>make_chevrolet</th>
      <td>-1321.257101</td>
    </tr>
    <tr>
      <th>make_plymouth</th>
      <td>-1387.929217</td>
    </tr>
    <tr>
      <th>make_mitsubishi</th>
      <td>-1415.174131</td>
    </tr>
    <tr>
      <th>fuel-system_4bbl</th>
      <td>-1502.840531</td>
    </tr>
    <tr>
      <th>make_dodge</th>
      <td>-1504.123832</td>
    </tr>
    <tr>
      <th>make_subaru</th>
      <td>-2050.094688</td>
    </tr>
    <tr>
      <th>engine-type_ohc</th>
      <td>-2186.287894</td>
    </tr>
    <tr>
      <th>engine-location_front</th>
      <td>-2856.516426</td>
    </tr>
    <tr>
      <th>engine-type_dohc</th>
      <td>-2893.648401</td>
    </tr>
    <tr>
      <th>bore</th>
      <td>-3524.081308</td>
    </tr>
    <tr>
      <th>fuel-type_gas</th>
      <td>-3607.600803</td>
    </tr>
    <tr>
      <th>engine-type_ohcv</th>
      <td>-5455.271839</td>
    </tr>
    <tr>
      <th>make_peugot</th>
      <td>-10065.030379</td>
    </tr>
  </tbody>
</table>
<p>70 rows × 1 columns</p>



ひとつのカテゴリカルデータが複数の列に分れたままなので解釈が難しいですね。

## 同じカテゴリカルデータ由来の列をまとめる

ダミー変数の作成により、ひとつのカテゴリカルデータが複数の列に分かれます。この作業は重回帰分析などの手法を適用するために必要なのですが、列が分かれたままでは解釈が困難になるため、どのカテゴリカルデータがどの列に分れたのかが追跡できるようにします。


```python
col_group = {}
for col in X.columns:
    a = col.split("_")
    if len(a) == 2:
        if a[0] not in col_group.keys():
            col_group[a[0]] = []
        col_group[a[0]].append(a[1])
    else:
        col_group[col] = [col]
```

このように分かれたことがわかります。


```python
for k, v in col_group.items():
    print(k,":", v)
```

    symboling : ['symboling']
    normalized-losses : ['normalized-losses']
    wheel-base : ['wheel-base']
    length : ['length']
    width : ['width']
    height : ['height']
    curb-weight : ['curb-weight']
    engine-size : ['engine-size']
    bore : ['bore']
    stroke : ['stroke']
    compression-ratio : ['compression-ratio']
    horsepower : ['horsepower']
    peak-rpm : ['peak-rpm']
    city-mpg : ['city-mpg']
    highway-mpg : ['highway-mpg']
    make : ['alfa-romero', 'audi', 'bmw', 'chevrolet', 'dodge', 'honda', 'isuzu', 'jaguar', 'mazda', 'mercedes-benz', 'mitsubishi', 'nissan', 'peugot', 'plymouth', 'porsche', 'renault', 'saab', 'subaru', 'toyota', 'volkswagen', 'volvo']
    fuel-type : ['diesel', 'gas']
    aspiration : ['std', 'turbo']
    num-of-doors : ['four', 'two', 'nan']
    body-style : ['convertible', 'hardtop', 'hatchback', 'sedan', 'wagon']
    drive-wheels : ['4wd', 'fwd', 'rwd']
    engine-location : ['front', 'rear']
    engine-type : ['dohc', 'l', 'ohc', 'ohcf', 'ohcv', 'rotor']
    num-of-cylinders : ['eight', 'five', 'four', 'six', 'two']
    fuel-system : ['1bbl', '2bbl', '4bbl', 'idi', 'mpfi', 'spdi']


## 回帰係数の幅

もともと同じ列に存在していたデータの回帰係数をひとまとめにします。


```python
names = []
values = []
for k,v in col_group.items():
    if len(v) == 1:
        coef = coefs.loc[k][0]
        names.append(k)
        values.append([coef])
    else:
        names.append(k)
        ary = []
        for val in v:
            coef = coefs.loc["{}_{}".format(k,val)][0]
            ary.append(coef)
        values.append(ary)
```

その回帰係数がどのくらいの幅を持っているのか図示してみましょう。


```python
%matplotlib inline
import matplotlib.pyplot as plt

for i, y in enumerate(values):
    plt.scatter([i for _ in y], y)
plt.xticks([i for i in range(len(names))], names, rotation=90)
plt.grid()
plt.show()
```

![output_34_1.png](https://qiita-image-store.s3.amazonaws.com/0/211162/9d2ef8e3-92e4-ec4b-8dd2-a35123024dff.png)


カテゴリカル変数の回帰係数が正負に大きい傾向がありますが、対応するダミー変数が０か１かしかない影響です。

## 相関係数との関係

次に、相関係数との関係を見てみましょう。ここで意識すべきことは、説明変数と目的変数が直線的な関係（線形）であるという前提条件において、

* 相関係数が 1 に近い説明変数は、価格を高くする要因である。
* 相関係数が -1 に近い説明変数は、価格を低くする要因である。
* 相関係数が 0 に近い説明変数は、価格にはあまり影響しない要因である。
* 相関係数の正負と、回帰係数の正負が一致しているものが、価格への影響が説明できる要因である。もし正負が逆転している場合は、価格への影響が（少なくとも線形関係としては）説明できない。

下記のコードでは、数値データの場合は横軸＝元データ、縦軸＝価格として散布図・相関係数・回帰係数を出力し、カテゴリカルデータの場合は横軸＝回帰係数、縦軸＝価格の平均値として散布図・相関係数を出力します。ひとつひとつの説明変数に対して、相関係数と回帰係数の関係を観察してください。


```python
import numpy as np
meaningful_cols = []
for k,v in col_group.items():
    if len(v) != 1:
        x_axis = []
        y_axis = []
        xy_names = []
        for val in v:
            try:
                x_axis.append(coefs.loc["{}_{}".format(k,val)][0])
                y_axis.append(Y[X["{}_{}".format(k,val)] == 1].median())                   
                xy_names.append(val)
            except:
                continue
                
        corrcoef = np.corrcoef(x_axis, y_axis)[0][1]
        plt.title("{}, corrcoef={}".format(k, corrcoef))
        for x, y, name in zip(x_axis, y_axis, xy_names):
            plt.scatter(x, y)
            plt.text(x, y, name)
        plt.xlabel("regression coefficient")
        plt.ylabel("median of Y")
        plt.grid()
        plt.show()
        
        if np.corrcoef(x_axis, y_axis)[0][1] >= 0.5:
            meaningful_cols.append(k)
    else:
        corrcoef = np.corrcoef(X[k].values, Y.values)[0][1]
        regrcoef = coefs.loc[k][0]
        plt.title("{0}, corrcoef={1:.4f}, regrcoef={2:.4f}".format(k, corrcoef, regrcoef))
        plt.scatter(X[k].values, Y.values)
        plt.xlabel("X")
        plt.ylabel("Y")
        plt.grid()
        plt.show()
        if corrcoef * regrcoef > 0:
            if abs(np.corrcoef(X[k].values, Y.values)[0][1]) >= 0.5:
                meaningful_cols.append(k)
```

![output_36_0.png](https://qiita-image-store.s3.amazonaws.com/0/211162/5023bac3-cd56-cd60-98e6-99a28ba188e7.png)

![output_36_1.png](https://qiita-image-store.s3.amazonaws.com/0/211162/11244124-f810-e410-3240-1c04270f696f.png)

![output_36_2.png](https://qiita-image-store.s3.amazonaws.com/0/211162/fc06bc5f-f8c3-aca6-7965-09b0fd9a38f8.png)

![output_36_3.png](https://qiita-image-store.s3.amazonaws.com/0/211162/8031cd71-e7d1-42af-e9a5-a8bb2b28529c.png)

![output_36_4.png](https://qiita-image-store.s3.amazonaws.com/0/211162/a5282a05-379d-8518-c916-47109bb83644.png)

![output_36_5.png](https://qiita-image-store.s3.amazonaws.com/0/211162/8a4fffc0-d8da-d729-92ae-a260a02de0e5.png)

![output_36_6.png](https://qiita-image-store.s3.amazonaws.com/0/211162/e6ea75ca-e860-d69b-3def-0bb29187723d.png)

![output_36_7.png](https://qiita-image-store.s3.amazonaws.com/0/211162/cef301d0-924b-b079-f30a-29fcc6a1cf02.png)

![output_36_8.png](https://qiita-image-store.s3.amazonaws.com/0/211162/d9ef5320-bd4f-f928-c4ab-d08ed4959da2.png)

![output_36_9.png](https://qiita-image-store.s3.amazonaws.com/0/211162/86866bd5-a947-7d64-ce5f-c2bab0be06ee.png)

![output_36_10.png](https://qiita-image-store.s3.amazonaws.com/0/211162/f36649e4-8611-2b8b-6068-0da257621c80.png)

![output_36_11.png](https://qiita-image-store.s3.amazonaws.com/0/211162/9734c0ae-ef5e-f206-ef5a-f140c08d2103.png)

![output_36_12.png](https://qiita-image-store.s3.amazonaws.com/0/211162/514a7127-cfd5-b25a-531e-a5f1dd3e8f1a.png)

![output_36_13.png](https://qiita-image-store.s3.amazonaws.com/0/211162/ba4d2928-bfd7-5441-1c56-666bbeffa4ff.png)

![output_36_14.png](https://qiita-image-store.s3.amazonaws.com/0/211162/d03619b9-e41b-40f3-91a8-2a3628bd640a.png)

![output_36_15.png](https://qiita-image-store.s3.amazonaws.com/0/211162/69979bf8-6d8d-3cc2-8262-e192f8511efe.png)

![output_36_16.png](https://qiita-image-store.s3.amazonaws.com/0/211162/2974f4f4-433a-2499-b59a-5d9c743d3084.png)

![output_36_17.png](https://qiita-image-store.s3.amazonaws.com/0/211162/82e82880-ed0b-bbba-40e0-3415402dfa75.png)

![output_36_18.png](https://qiita-image-store.s3.amazonaws.com/0/211162/79e877ff-e0ef-bfd0-162c-995b68a6b880.png)

![output_36_19.png](https://qiita-image-store.s3.amazonaws.com/0/211162/e7b002bc-3501-7b47-abd5-bfedce135614.png)

![output_36_20.png](https://qiita-image-store.s3.amazonaws.com/0/211162/ea790a55-db3d-6837-f048-91acd6e58c7d.png)

![output_36_21.png](https://qiita-image-store.s3.amazonaws.com/0/211162/e7364716-31f4-7777-92e5-88b41e798f24.png)

![output_36_22.png](https://qiita-image-store.s3.amazonaws.com/0/211162/3f2b041b-573c-7684-0486-38919a267841.png)

![output_36_23.png](https://qiita-image-store.s3.amazonaws.com/0/211162/5e3b9fc2-5a13-b8e4-b68b-1ad5693e24d3.png)

![output_36_24.png](https://qiita-image-store.s3.amazonaws.com/0/211162/10e8d3c5-f5e5-357a-61dd-b1fb919a8e6f.png)

以上のコードでは、相関係数と回帰係数を比較して、「予測する上で意味がありそうな」列を取り出し、meaningful_cols というリストの中に入れるようにしました。結果として次の列が「意味がありそうな」列として選ばれました。どういう条件で取り出したかは上のコードを確認してください。


```python
meaningful_cols
```




    ['wheel-base',
     'width',
     'curb-weight',
     'engine-size',
     'horsepower',
     'city-mpg',
     'make',
     'fuel-type',
     'aspiration',
     'body-style',
     'drive-wheels',
     'engine-location']



## 「意味がありそうな」列だけを用いて予測

意味がありそうな列だけを用いて、データの前処理からやり直します。


```python
X = df[meaningful_cols]
X = pd.get_dummies(X, dummy_na=True)
X = X.fillna(X.median())
X = X.iloc[:, [i for i, x in enumerate(X.var()) if x != 0]]
X = X.iloc[:, [i for i, x in enumerate(X.sum()) if x != 1]]
Y = df.iloc[:, -1]
```


```python
from sklearn import linear_model
safe = []
droplist = []
for i in range(len(X)):
    try:
        clf = linear_model.LinearRegression()
        clf.fit(X.iloc[safe + [i], :], Y.iloc[safe + [i]])
        safe.append(i)
    except:
        droplist.append(i)
```


```python
X = X.iloc[safe, :]
Y = Y.iloc[safe]
```


```python
from sklearn.model_selection import train_test_split
result_scores = []
for _ in range(100):
    X_train, X_test, Y_train, Y_test = train_test_split(X, Y)
    clf = linear_model.LinearRegression()
    clf.fit(X_train, Y_train)
    result_scores.append(clf.score(X_test, Y_test))
print('{0:.4f} ± {1:.4f}'.format(np.mean(result_scores), np.std(result_scores)))
```

    0.8988 ± 0.0506


全ての列を用いた時よりも精度が上がりました。

## 説明変数の影響度

通常の重回帰分析でもそうですが、説明変数の標準化をしてから回帰すると、説明変数の尺度に依存しない標準回帰係数が得られ、説明変数の影響度を比較することができます。


```python
X_std = X.apply(lambda x: (x-x.mean())/x.std(), axis=0) # 説明変数の標準化
X_std.head()
```



<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>wheel-base</th>
      <th>width</th>
      <th>curb-weight</th>
      <th>engine-size</th>
      <th>horsepower</th>
      <th>city-mpg</th>
      <th>make_alfa-romero</th>
      <th>make_audi</th>
      <th>make_bmw</th>
      <th>make_chevrolet</th>
      <th>...</th>
      <th>body-style_convertible</th>
      <th>body-style_hardtop</th>
      <th>body-style_hatchback</th>
      <th>body-style_sedan</th>
      <th>body-style_wagon</th>
      <th>drive-wheels_4wd</th>
      <th>drive-wheels_fwd</th>
      <th>drive-wheels_rwd</th>
      <th>engine-location_front</th>
      <th>engine-location_rear</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>0</th>
      <td>-1.680910</td>
      <td>-0.851335</td>
      <td>-0.014821</td>
      <td>0.075201</td>
      <td>0.205661</td>
      <td>-0.650624</td>
      <td>8.103804</td>
      <td>-0.174975</td>
      <td>-0.203088</td>
      <td>-0.122785</td>
      <td>...</td>
      <td>5.686678</td>
      <td>-0.203088</td>
      <td>-0.713256</td>
      <td>-0.934951</td>
      <td>-0.37595</td>
      <td>-0.203088</td>
      <td>-1.189375</td>
      <td>1.292920</td>
      <td>0.122785</td>
      <td>-0.122785</td>
    </tr>
    <tr>
      <th>1</th>
      <td>-1.680910</td>
      <td>-0.851335</td>
      <td>-0.014821</td>
      <td>0.075201</td>
      <td>0.205661</td>
      <td>-0.650624</td>
      <td>8.103804</td>
      <td>-0.174975</td>
      <td>-0.203088</td>
      <td>-0.122785</td>
      <td>...</td>
      <td>5.686678</td>
      <td>-0.203088</td>
      <td>-0.713256</td>
      <td>-0.934951</td>
      <td>-0.37595</td>
      <td>-0.203088</td>
      <td>-1.189375</td>
      <td>1.292920</td>
      <td>0.122785</td>
      <td>-0.122785</td>
    </tr>
    <tr>
      <th>2</th>
      <td>-0.708334</td>
      <td>-0.185134</td>
      <td>0.516789</td>
      <td>0.604724</td>
      <td>1.356164</td>
      <td>-0.961995</td>
      <td>8.103804</td>
      <td>-0.174975</td>
      <td>-0.203088</td>
      <td>-0.122785</td>
      <td>...</td>
      <td>-0.174975</td>
      <td>-0.203088</td>
      <td>1.395045</td>
      <td>-0.934951</td>
      <td>-0.37595</td>
      <td>-0.203088</td>
      <td>-1.189375</td>
      <td>1.292920</td>
      <td>0.122785</td>
      <td>-0.122785</td>
    </tr>
    <tr>
      <th>3</th>
      <td>0.165335</td>
      <td>0.147966</td>
      <td>-0.422710</td>
      <td>-0.430252</td>
      <td>-0.035142</td>
      <td>-0.183569</td>
      <td>-0.122785</td>
      <td>5.686678</td>
      <td>-0.203088</td>
      <td>-0.122785</td>
      <td>...</td>
      <td>-0.174975</td>
      <td>-0.203088</td>
      <td>-0.713256</td>
      <td>1.064253</td>
      <td>-0.37595</td>
      <td>-0.203088</td>
      <td>0.836595</td>
      <td>-0.769595</td>
      <td>0.122785</td>
      <td>-0.122785</td>
    </tr>
    <tr>
      <th>4</th>
      <td>0.099398</td>
      <td>0.243137</td>
      <td>0.518722</td>
      <td>0.219617</td>
      <td>0.312685</td>
      <td>-1.117680</td>
      <td>-0.122785</td>
      <td>5.686678</td>
      <td>-0.203088</td>
      <td>-0.122785</td>
      <td>...</td>
      <td>-0.174975</td>
      <td>-0.203088</td>
      <td>-0.713256</td>
      <td>1.064253</td>
      <td>-0.37595</td>
      <td>4.899487</td>
      <td>-1.189375</td>
      <td>-0.769595</td>
      <td>0.122785</td>
      <td>-0.122785</td>
    </tr>
  </tbody>
</table>
<p>5 rows × 41 columns</p>
</div>




```python
Y_std = [(y - Y.mean())/Y.std() for y in Y] # 目的変数の標準化
```


```python
clf = linear_model.LinearRegression()
clf.fit(X_std, Y_std)
coefs = pd.DataFrame(clf.coef_, index=X_std.columns).sort_values(0, ascending=False)
coefs # 回帰係数を大きい順に並べたもの
```


<table border="1" class="dataframe">
  <thead>
    <tr style="text-align: right;">
      <th></th>
      <th>0</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th>make_bmw</th>
      <td>0.284965</td>
    </tr>
    <tr>
      <th>make_mercedes-benz</th>
      <td>0.282663</td>
    </tr>
    <tr>
      <th>horsepower</th>
      <td>0.214117</td>
    </tr>
    <tr>
      <th>curb-weight</th>
      <td>0.164879</td>
    </tr>
    <tr>
      <th>make_porsche</th>
      <td>0.145504</td>
    </tr>
    <tr>
      <th>engine-size</th>
      <td>0.142839</td>
    </tr>
    <tr>
      <th>width</th>
      <td>0.136375</td>
    </tr>
    <tr>
      <th>make_jaguar</th>
      <td>0.136342</td>
    </tr>
    <tr>
      <th>make_audi</th>
      <td>0.113193</td>
    </tr>
    <tr>
      <th>make_mazda</th>
      <td>0.113180</td>
    </tr>
    <tr>
      <th>wheel-base</th>
      <td>0.094628</td>
    </tr>
    <tr>
      <th>make_volvo</th>
      <td>0.090131</td>
    </tr>
    <tr>
      <th>make_saab</th>
      <td>0.086344</td>
    </tr>
    <tr>
      <th>make_honda</th>
      <td>0.080182</td>
    </tr>
    <tr>
      <th>engine-location_rear</th>
      <td>0.074579</td>
    </tr>
    <tr>
      <th>body-style_convertible</th>
      <td>0.074073</td>
    </tr>
    <tr>
      <th>make_volkswagen</th>
      <td>0.070591</td>
    </tr>
    <tr>
      <th>make_nissan</th>
      <td>0.066461</td>
    </tr>
    <tr>
      <th>make_toyota</th>
      <td>0.053857</td>
    </tr>
    <tr>
      <th>make_alfa-romero</th>
      <td>0.050050</td>
    </tr>
    <tr>
      <th>city-mpg</th>
      <td>0.049853</td>
    </tr>
    <tr>
      <th>make_dodge</th>
      <td>0.047942</td>
    </tr>
    <tr>
      <th>make_chevrolet</th>
      <td>0.047092</td>
    </tr>
    <tr>
      <th>make_subaru</th>
      <td>0.035763</td>
    </tr>
    <tr>
      <th>make_plymouth</th>
      <td>0.033667</td>
    </tr>
    <tr>
      <th>make_mitsubishi</th>
      <td>0.026031</td>
    </tr>
    <tr>
      <th>make_peugot</th>
      <td>0.025644</td>
    </tr>
    <tr>
      <th>drive-wheels_4wd</th>
      <td>0.021523</td>
    </tr>
    <tr>
      <th>drive-wheels_rwd</th>
      <td>0.019836</td>
    </tr>
    <tr>
      <th>make_isuzu</th>
      <td>0.019012</td>
    </tr>
    <tr>
      <th>make_renault</th>
      <td>0.009916</td>
    </tr>
    <tr>
      <th>aspiration_turbo</th>
      <td>0.009471</td>
    </tr>
    <tr>
      <th>fuel-type_gas</th>
      <td>0.003038</td>
    </tr>
    <tr>
      <th>body-style_sedan</th>
      <td>-0.001227</td>
    </tr>
    <tr>
      <th>body-style_hardtop</th>
      <td>-0.002052</td>
    </tr>
    <tr>
      <th>body-style_hatchback</th>
      <td>-0.002310</td>
    </tr>
    <tr>
      <th>fuel-type_diesel</th>
      <td>-0.003038</td>
    </tr>
    <tr>
      <th>aspiration_std</th>
      <td>-0.009471</td>
    </tr>
    <tr>
      <th>drive-wheels_fwd</th>
      <td>-0.028030</td>
    </tr>
    <tr>
      <th>body-style_wagon</th>
      <td>-0.031814</td>
    </tr>
    <tr>
      <th>engine-location_front</th>
      <td>-0.074579</td>
    </tr>
  </tbody>
</table>
</div>




```python
col_group = {}
for col in X_std.columns:
    a = col.split("_")
    if len(a) == 2:
        if a[0] not in col_group.keys():
            col_group[a[0]] = []
        col_group[a[0]].append(a[1])
    else:
        col_group[col] = [col]
```


```python
names = []
values = []
for k,v in col_group.items():
    if len(v) == 1:
        coef = coefs.loc[k][0]
        names.append(k)
        values.append([coef])
    else:
        names.append(k)
        ary = []
        for val in v:
            coef = coefs.loc["{}_{}".format(k,val)][0]
            ary.append(coef)
        values.append(ary)
```


```python
%matplotlib inline
import matplotlib.pyplot as plt

for i, y in enumerate(values):
    plt.scatter([i for _ in y], y)
plt.xticks([i for i in range(len(names))], names, rotation=90)
plt.grid()
plt.show()
```

![output_51_0.png](https://qiita-image-store.s3.amazonaws.com/0/211162/6755aca6-d2e6-125f-61a2-7503d478face.png)