【3/20更新】基本的な可視化手法を整理してみた

* 製造業出身のデータサイエンティストがお送りする記事
* 今回は業務で良く使う可視化手法を整理してみました。
* 適宜更新できるようにしたいと思います。

##はじめに
今回は[Auto MPG](https://archive.ics.uci.edu/ml/datasets/auto+mpg)のデータセットを使用して整理したいと思います。このデータセットは、1970年代後半から1980年台初めの自動車の燃費を現したデータです。

##データの確認
```php
# 必要なライブラリーのインストール
import numpy as np 
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
import os

file_path = 'https://archive.ics.uci.edu/ml/machine-learning-databases/auto-mpg/auto-mpg.data'
file_name = os.path.splitext(os.path.basename(file_path))[0]
column_names = ['MPG','Cylinders', 'Displacement', 'Horsepower', 'Weight',
                  'Acceleration', 'Model Year', 'Origin'] 

df = pd.read_csv(
    file_path, # ファイルパス
    names = column_names, # 列名を指定
    na_values ='?', # ?は欠損値として読み込む
    comment = '\t', # TAB以降右はスキップ 
    sep = ' ', # 空白行を区切りとする
    skipinitialspace = True, # カンマの後の空白をスキップ
    encoding = 'utf-8'
) 
df.head()
```

![スクリーンショット 2021-01-07 9.52.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/3349adff-750d-0fb4-b888-b248769b395d.png)

##レコード数、カラム数の確認

```php
# レコード数、カラム数の確認
df.shape
```

##欠損値の確認

```php
# 欠損値数の確認
df.isnull().sum()
```

##DataFrameの各列の属性の確認

```php
# DataFrameの各列の属性を確認
df.dtypes
```

##欠損値の可視化
欠損値に規則性があるかどうかの時に使用します。
現場に説明する際とかに分かりやすくて重宝します。

```php
plt.figure(figsize=(14,7))
sns.heatmap(df.isnull())
```

![欠損値.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/cfc943e9-e92f-ce7a-a82b-6c2922aee7ff.png)

##要約統計量の確認

```php
# 要約統計量
df.describe()
```

![スクリーンショット 2021-01-07 9.57.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/0f768e01-dbbd-551d-5e30-abe9630780ed.png)

##ヒストグラムの作成

```php
# ヒストグラム
df['MPG'].plot(kind='hist', bins=12)
```

![ヒストグラム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/061a054f-1b8a-781c-5bb7-074d130b5174.png)


###自分で設定した階級でヒストグラムを作成

```php
# 自分で設定した階級でヒストグラム
plt.hist(df['MPG'], list(range(0, 51, 5)), rwidth=.8)
plt.xticks(list(range(0, 51, 10)))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/dc28896e-59d7-f002-9603-3e5b959a417a.png)

###区間を軸に明示したヒストグラムを作成

```php
#区間を軸に明示したヒストグラム
pd.cut(df['MPG'], list(range(0, 51, 5)), right=False).value_counts().sort_index().plot.bar()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/a7daadba-7ccd-ac4e-b155-ac700d5d6e20.png)

##カーネル密度推定の作成
ヒストグラムはビンの大きさを変更すると形が変わって見えるので、カーネル密度推定で作成したグラフの方が良く使います。

```php
# カーネル密度推定
sns.kdeplot(data=df['MPG'], shade=True)
```

![カーネル密度推定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/7d07d5c5-04d5-824d-e563-cdcbc3926754.png)

##散布図の作成
####散布図＋ヒストグラム

```php
# 散布図+ヒストグラム
sns.jointplot(x='Model Year', y='MPG', data=df, alpha=0.3)
```

![散布図＋ヒストグラム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/8e3d4a7a-ff77-3c4c-87e6-04a5bf490a03.png)

####六角形の散布図
少しモダンでおしゃれな散布図。

```php
# hexagonal bins
sns.jointplot(x='Model Year', y='MPG', data=df, kind='hex')
```

![六角形.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/97e754be-fcf9-c7c7-2337-05d884814991.png)

####カーネル密度推定の散布図
等高線風のグラフを生成。

```php
# density estimates
sns.jointplot(x='Model Year', y='MPG', data=df, kind='kde', shade=True)
```

![kde.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/43ba9f78-7157-f1cb-42ee-081cbf37d052.png)

####散布図行列

```php
# 散布図行列
sns.pairplot(df[["MPG", "Cylinders", "Displacement", "Weight"]], diag_kind="kde")
```

![散布図行列.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/da1e1bf0-b18c-0ad4-c0d1-9eb28b48d694.png)

##箱ひげ図の作成
データのばらつきを可視化。

####countplot

```php
# 年代別のcountplot
ax = sns.countplot(x='Model Year', data=df, color='cornflowerblue')
```

![countplot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/1b40bbf2-87f6-d744-5713-418f3e3ed451.png)

####箱ひげ図(boxplot)

```php
# 箱ひげ図(boxplot)
sns.boxplot(x='Model Year', y='MPG', data=df.sort_values('Model Year'), color='cornflowerblue')
```

![boxplot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/21dfa4ea-a775-8db5-4857-d7f61fe7e747.png)

####violin plot
データの分布の密度を確認できるグラフ。

```php
# violin plot 
sns.violinplot(x='Model Year', y='MPG', data=df.sort_values('Model Year'), color='cornflowerblue')
```

![violin plot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/b4578ee7-be8b-13b6-7117-17df6b2405dd.png)

####swarm plot
データの分布のドットで確認できるグラフ。

```php
# swarm plot
fig, ax = plt.subplots(figsize=(20, 5))
ax.tick_params(labelsize=20)
sns.swarmplot(x='Model Year', y='MPG', data=df.sort_values('Model Year'))
```

![swarm plot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/0bab65ef-83f4-ac06-9cf1-8db9c1e3ed36.png)

##ヒートマップ
####相関係数行列

```php
# 相関係数行列（値が0を含むrowを除く）
df = df[(df!=0).all(axis=1)]
corr = df.corr()
corr
```

![swarm plot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/fcb1e792-314b-d2db-e554-62d81fd4c794.png)

####相関係数行列のヒートマップ
cmapの「coolwarm」の色合いが個人的には好きです。何も指定しないと微妙な色合いになって資料とかで見えにくいので。

```php
# 相関係数のヒートマップ
sns.heatmap(df.corr(), annot=True, cmap='coolwarm')
```

![ヒートマップ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/5e6bdb03-dac2-2d37-ef50-5edf2b56af31.png)

##matplotlibを活用した可視化方法

####棒グラフの作成
Model Year毎にDisplacementを集計して棒グラフを作成します。

```php
df_year = df.groupby(['Model Year'])['Displacement'].sum().reset_index()
df_year['Displacement'] = df_year['Displacement']
df_year.head()
```

![スクリーンショット 2021-03-20 17.04.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/faeca7b7-5157-4212-b5fb-f2a9665683e3.png)

棒グラフを作成します。

```php
fig = plt.figure(figsize=(20, 8))
ax = fig.add_subplot(111, xticks=df_year['Model Year'])
ax.bar(df_year['Model Year'], df_year['Displacement'])
plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/d0f578ab-ad59-621f-6621-92613a84ef91.png)

次は軸に名前を付けます。

```php
fig = plt.figure(figsize=(20, 8))
ax = fig.add_subplot(111, xlabel='Model Year', ylabel='Displacement',
                     xticks=df_year['Model Year'])
ax.bar(df_year['Model Year'], df_year['Displacement'])

# set_xlabel, set_ylabelで設定してもOK
# ax.set_xlabel('Model Year', fontproperties=font, fontsize=20)
# ax.set_ylabel('Displacement', fontproperties=font, fontsize=20)
plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/dba564b8-ccce-8afc-8466-2f5172c7976c.png)

次は軸の文字を大きくします。

```php
fig = plt.figure(figsize=(20, 8))
ax = fig.add_subplot(111, xticks=df_year['Model Year'])
ax.bar(df_year['Model Year'], df_year['Displacement'])

# tick_paramsで設定
ax.tick_params(axis='x', labelsize=30)
ax.tick_params(axis='y', labelsize=30)
ax.ticklabel_format(axis='y', style='plain')
plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/ff524c2f-a73c-deb0-df1c-12215a2382cc.png)

次は軸の色を変えてみます。

```php
fig = plt.figure(figsize=(20, 8))
ax = fig.add_subplot(111, xticks=df_year['Model Year'])
ax.bar(df_year['Model Year'], df_year['Displacement'])

# tick_paramsで設定
ax.tick_params(axis='x', labelsize=30, colors = 'red')
ax.tick_params(axis='y', labelsize=30)
ax.ticklabel_format(axis='y', style='plain')
plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/29d7358e-7587-4a90-38d4-cda00627bc16.png)

次は棒グラフの上に数字を追加します。

```php
fig = plt.figure(figsize=(20, 8))
ax = fig.add_subplot(111, xticks=df_year['Model Year'])
ax.bar(df_year['Model Year'], df_year['Displacement'])

# 棒グラフの上に数字を追加
for i in range(len(df_year)):
    ax.text(
        x=df_year['Model Year'][i],
        y=df_year['Displacement'][i] + (df_year['Displacement'][i]) / 100,
        s=df_year['Displacement'][i],
        horizontalalignment='center',
        size=20)
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/e0211ad6-621f-5f1b-1df5-f59c554f16e4.png)

##seabornを活用した可視化方法

####折れ線グラフの作成

```php
# "flights" というデータセットの読み込み
df = sns.load_dataset('flights')
df.head()
```

![スクリーンショット 2021-03-20 17.15.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/e94c0dd7-a9d3-7e17-31de-e230b6456a42.png)

1月の乗客の推移を年ごとに可視化

```php
sns.lineplot(data=df[df.month == 'January'], x='year', y='passengers')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/429e89a5-e60c-9dc9-b5e4-b265941d6554.png)

特定の月に限定しない場合の可視化

```php
sns.lineplot(data=df, x='year', y='passengers')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/e05ecfb5-590d-5dd1-4c6c-0f1e4337554b.png)

標準偏差を用いた信頼区間を活用して可視化

```php
sns.lineplot(data=df, x='year', y='passengers', ci='sd')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/cd084de9-aacf-e35c-1a07-281ef8f3fa4c.png)


月別に可視化

```php
sns.relplot(data=df, kind='line', x='year', y='passengers', col='month', col_wrap=3)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/743453/04bcf13a-30b0-13cd-caf8-b61ed5ff6fbd.png)


##さいごに
最後まで読んで頂き、ありがとうございました。
今回は、基本的な可視化手法を整理してみました。
適宜自分のメモとして更新していこうと思います。

訂正要望がありましたら、ご連絡頂けますと幸いです。