Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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

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

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

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

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

1985年自動車価格のデータを例に説明します。

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

# 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>)
# 表形式の計算をサポートするライブラリのインポート
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)
symboling normalized-losses make fuel-type aspiration num-of-doors body-style drive-wheels engine-location wheel-base ... engine-size fuel-system bore stroke compression-ratio horsepower peak-rpm city-mpg highway-mpg price
0 3 NaN alfa-romero gas std two convertible rwd front 88.6 ... 130 mpfi 3.47 2.68 9.0 111.0 5000.0 21 27 13495.0
1 3 NaN alfa-romero gas std two convertible rwd front 88.6 ... 130 mpfi 3.47 2.68 9.0 111.0 5000.0 21 27 16500.0
2 1 NaN alfa-romero gas std two hatchback rwd front 94.5 ... 152 mpfi 2.68 3.47 9.0 154.0 5000.0 19 26 16500.0
3 2 164.0 audi gas std four sedan fwd front 99.8 ... 109 mpfi 3.19 3.40 10.0 102.0 5500.0 24 30 13950.0
4 2 164.0 audi gas std four sedan 4wd front 99.4 ... 136 mpfi 3.19 3.40 8.0 115.0 5500.0 18 22 17450.0

5 rows × 26 columns

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

データの前処理

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

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

X = df.iloc[:, :-1]
Y = df.iloc[:, -1]
# 説明変数
X.head()
symboling normalized-losses make fuel-type aspiration num-of-doors body-style drive-wheels engine-location wheel-base ... num-of-cylinders engine-size fuel-system bore stroke compression-ratio horsepower peak-rpm city-mpg highway-mpg
0 3 NaN alfa-romero gas std two convertible rwd front 88.6 ... four 130 mpfi 3.47 2.68 9.0 111.0 5000.0 21 27
1 3 NaN alfa-romero gas std two convertible rwd front 88.6 ... four 130 mpfi 3.47 2.68 9.0 111.0 5000.0 21 27
2 1 NaN alfa-romero gas std two hatchback rwd front 94.5 ... six 152 mpfi 2.68 3.47 9.0 154.0 5000.0 19 26
3 2 164.0 audi gas std four sedan fwd front 99.8 ... four 109 mpfi 3.19 3.40 10.0 102.0 5500.0 24 30
4 2 164.0 audi gas std four sedan 4wd front 99.4 ... five 136 mpfi 3.19 3.40 8.0 115.0 5500.0 18 22

5 rows × 25 columns

# 目的変数
pd.DataFrame(Y).head()
price
0 13495.0
1 16500.0
2 16500.0
3 13950.0
4 17450.0

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

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

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

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

X = pd.get_dummies(X, dummy_na=True)
X.head()
symboling normalized-losses wheel-base length width height curb-weight engine-size bore stroke ... num-of-cylinders_nan fuel-system_1bbl fuel-system_2bbl fuel-system_4bbl fuel-system_idi fuel-system_mfi fuel-system_mpfi fuel-system_spdi fuel-system_spfi fuel-system_nan
0 3 NaN 88.6 168.8 64.1 48.8 2548 130 3.47 2.68 ... 0 0 0 0 0 0 1 0 0 0
1 3 NaN 88.6 168.8 64.1 48.8 2548 130 3.47 2.68 ... 0 0 0 0 0 0 1 0 0 0
2 1 NaN 94.5 171.2 65.5 52.4 2823 152 2.68 3.47 ... 0 0 0 0 0 0 1 0 0 0
3 2 164.0 99.8 176.6 66.2 54.3 2337 109 3.19 3.40 ... 0 0 0 0 0 0 1 0 0 0
4 2 164.0 99.4 176.6 66.4 54.3 2824 136 3.19 3.40 ... 0 0 0 0 0 0 1 0 0 0

5 rows × 85 columns

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

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

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

X = X.fillna(X.median())
X.head()
symboling normalized-losses wheel-base length width height curb-weight engine-size bore stroke ... num-of-cylinders_nan fuel-system_1bbl fuel-system_2bbl fuel-system_4bbl fuel-system_idi fuel-system_mfi fuel-system_mpfi fuel-system_spdi fuel-system_spfi fuel-system_nan
0 3 115.0 88.6 168.8 64.1 48.8 2548 130 3.47 2.68 ... 0 0 0 0 0 0 1 0 0 0
1 3 115.0 88.6 168.8 64.1 48.8 2548 130 3.47 2.68 ... 0 0 0 0 0 0 1 0 0 0
2 1 115.0 94.5 171.2 65.5 52.4 2823 152 2.68 3.47 ... 0 0 0 0 0 0 1 0 0 0
3 2 164.0 99.8 176.6 66.2 54.3 2337 109 3.19 3.40 ... 0 0 0 0 0 0 1 0 0 0
4 2 164.0 99.4 176.6 66.4 54.3 2824 136 3.19 3.40 ... 0 0 0 0 0 0 1 0 0 0

5 rows × 85 columns

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

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

X = X.iloc[:, [i for i, x in enumerate(X.var()) if x != 0]]
X.head()
symboling normalized-losses wheel-base length width height curb-weight engine-size bore stroke ... num-of-cylinders_twelve num-of-cylinders_two fuel-system_1bbl fuel-system_2bbl fuel-system_4bbl fuel-system_idi fuel-system_mfi fuel-system_mpfi fuel-system_spdi fuel-system_spfi
0 3 115.0 88.6 168.8 64.1 48.8 2548 130 3.47 2.68 ... 0 0 0 0 0 0 0 1 0 0
1 3 115.0 88.6 168.8 64.1 48.8 2548 130 3.47 2.68 ... 0 0 0 0 0 0 0 1 0 0
2 1 115.0 94.5 171.2 65.5 52.4 2823 152 2.68 3.47 ... 0 0 0 0 0 0 0 1 0 0
3 2 164.0 99.8 176.6 66.2 54.3 2337 109 3.19 3.40 ... 0 0 0 0 0 0 0 1 0 0
4 2 164.0 99.4 176.6 66.4 54.3 2824 136 3.19 3.40 ... 0 0 0 0 0 0 0 1 0 0

5 rows × 76 columns

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

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

X = X.iloc[:, [i for i, x in enumerate(X.sum()) if x != 1]]
X.head()
symboling normalized-losses wheel-base length width height curb-weight engine-size bore stroke ... num-of-cylinders_five num-of-cylinders_four num-of-cylinders_six num-of-cylinders_two fuel-system_1bbl fuel-system_2bbl fuel-system_4bbl fuel-system_idi fuel-system_mpfi fuel-system_spdi
0 3 115.0 88.6 168.8 64.1 48.8 2548 130 3.47 2.68 ... 0 1 0 0 0 0 0 0 1 0
1 3 115.0 88.6 168.8 64.1 48.8 2548 130 3.47 2.68 ... 0 1 0 0 0 0 0 0 1 0
2 1 115.0 94.5 171.2 65.5 52.4 2823 152 2.68 3.47 ... 0 0 1 0 0 0 0 0 1 0
3 2 164.0 99.8 176.6 66.2 54.3 2337 109 3.19 3.40 ... 0 1 0 0 0 0 0 0 1 0
4 2 164.0 99.4 176.6 66.4 54.3 2824 136 3.19 3.40 ... 1 0 0 0 0 0 0 0 1 0

5 rows × 70 columns

エラーを起こす行を除外

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

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 の中身は次のようになります。

droplist
[9, 44, 45, 129]

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

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

機械学習と交差検定

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

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

結果の解釈

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

clf = linear_model.LinearRegression()
clf.fit(X, Y)
coefs = pd.DataFrame(clf.coef_, index=X.columns).sort_values(0, ascending=False)
coefs # 回帰係数を大きい順に並べたもの
0
make_bmw 10041.151756
make_porsche 7829.488014
make_audi 6605.635485
engine-type_l 6530.190701
make_saab 6380.589720
make_mercedes-benz 5948.369828
num-of-cylinders_eight 5893.599864
fuel-type_diesel 3607.600803
fuel-system_idi 3607.600803
make_alfa-romero 3410.184970
num-of-cylinders_two 3198.595695
engine-type_rotor 3198.595695
engine-location_rear 2856.516426
num-of-cylinders_four 2739.959484
make_volkswagen 2697.045849
make_jaguar 2558.651437
num-of-cylinders_six 2208.090711
body-style_convertible 2131.983958
make_mazda 1866.481690
make_nissan 1539.816016
fuel-system_2bbl 1450.615300
make_honda 1332.692521
make_volvo 1213.565871
aspiration_turbo 984.516339
engine-type_ohcf 806.421738
width 625.621317
drive-wheels_rwd 473.746006
make_renault 404.114694
make_toyota 377.790964
make_isuzu 358.242593
... ...
normalized-losses -12.312491
city-mpg -42.229906
body-style_hardtop -75.642611
length -136.954058
num-of-doors_nan -163.376963
num-of-cylinders_five -327.028649
height -405.768728
body-style_sedan -440.124658
symboling -444.678768
drive-wheels_fwd -671.983102
body-style_wagon -712.745083
compression-ratio -799.095043
fuel-system_spdi -860.917681
body-style_hatchback -903.471605
aspiration_std -984.516339
fuel-system_1bbl -1094.045556
stroke -1290.742175
make_chevrolet -1321.257101
make_plymouth -1387.929217
make_mitsubishi -1415.174131
fuel-system_4bbl -1502.840531
make_dodge -1504.123832
make_subaru -2050.094688
engine-type_ohc -2186.287894
engine-location_front -2856.516426
engine-type_dohc -2893.648401
bore -3524.081308
fuel-type_gas -3607.600803
engine-type_ohcv -5455.271839
make_peugot -10065.030379

70 rows × 1 columns

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

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

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

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]

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

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']

回帰係数の幅

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

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)

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

%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

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

相関係数との関係

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

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

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

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

output_36_1.png

output_36_2.png

output_36_3.png

output_36_4.png

output_36_5.png

output_36_6.png

output_36_7.png

output_36_8.png

output_36_9.png

output_36_10.png

output_36_11.png

output_36_12.png

output_36_13.png

output_36_14.png

output_36_15.png

output_36_16.png

output_36_17.png

output_36_18.png

output_36_19.png

output_36_20.png

output_36_21.png

output_36_22.png

output_36_23.png

output_36_24.png

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

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

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

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

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]
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)
X = X.iloc[safe, :]
Y = Y.iloc[safe]
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

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

説明変数の影響度

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

X_std = X.apply(lambda x: (x-x.mean())/x.std(), axis=0) # 説明変数の標準化
X_std.head()
wheel-base width curb-weight engine-size horsepower city-mpg make_alfa-romero make_audi make_bmw make_chevrolet ... body-style_convertible body-style_hardtop body-style_hatchback body-style_sedan body-style_wagon drive-wheels_4wd drive-wheels_fwd drive-wheels_rwd engine-location_front engine-location_rear
0 -1.680910 -0.851335 -0.014821 0.075201 0.205661 -0.650624 8.103804 -0.174975 -0.203088 -0.122785 ... 5.686678 -0.203088 -0.713256 -0.934951 -0.37595 -0.203088 -1.189375 1.292920 0.122785 -0.122785
1 -1.680910 -0.851335 -0.014821 0.075201 0.205661 -0.650624 8.103804 -0.174975 -0.203088 -0.122785 ... 5.686678 -0.203088 -0.713256 -0.934951 -0.37595 -0.203088 -1.189375 1.292920 0.122785 -0.122785
2 -0.708334 -0.185134 0.516789 0.604724 1.356164 -0.961995 8.103804 -0.174975 -0.203088 -0.122785 ... -0.174975 -0.203088 1.395045 -0.934951 -0.37595 -0.203088 -1.189375 1.292920 0.122785 -0.122785
3 0.165335 0.147966 -0.422710 -0.430252 -0.035142 -0.183569 -0.122785 5.686678 -0.203088 -0.122785 ... -0.174975 -0.203088 -0.713256 1.064253 -0.37595 -0.203088 0.836595 -0.769595 0.122785 -0.122785
4 0.099398 0.243137 0.518722 0.219617 0.312685 -1.117680 -0.122785 5.686678 -0.203088 -0.122785 ... -0.174975 -0.203088 -0.713256 1.064253 -0.37595 4.899487 -1.189375 -0.769595 0.122785 -0.122785

5 rows × 41 columns

Y_std = [(y - Y.mean())/Y.std() for y in Y] # 目的変数の標準化
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 # 回帰係数を大きい順に並べたもの
0
make_bmw 0.284965
make_mercedes-benz 0.282663
horsepower 0.214117
curb-weight 0.164879
make_porsche 0.145504
engine-size 0.142839
width 0.136375
make_jaguar 0.136342
make_audi 0.113193
make_mazda 0.113180
wheel-base 0.094628
make_volvo 0.090131
make_saab 0.086344
make_honda 0.080182
engine-location_rear 0.074579
body-style_convertible 0.074073
make_volkswagen 0.070591
make_nissan 0.066461
make_toyota 0.053857
make_alfa-romero 0.050050
city-mpg 0.049853
make_dodge 0.047942
make_chevrolet 0.047092
make_subaru 0.035763
make_plymouth 0.033667
make_mitsubishi 0.026031
make_peugot 0.025644
drive-wheels_4wd 0.021523
drive-wheels_rwd 0.019836
make_isuzu 0.019012
make_renault 0.009916
aspiration_turbo 0.009471
fuel-type_gas 0.003038
body-style_sedan -0.001227
body-style_hardtop -0.002052
body-style_hatchback -0.002310
fuel-type_diesel -0.003038
aspiration_std -0.009471
drive-wheels_fwd -0.028030
body-style_wagon -0.031814
engine-location_front -0.074579

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]
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)
%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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away