Pythonで散布図を簡単に作成する方法【Matplotlib】

Pythonで散布図を簡単に作成する方法【Matplotlib】 プログラミング

下のグラフは、実際のデータをもとに作成された散布図です。
そして、企業のマーケティングの場で利用されているモノです。

この記事では、上の散布図を作成していきます。
この画像をゴール散布図と呼びます。

本記事の内容

  • Pythonで散布図を作成するための環境
  • Pandasによるエクセルデータの読み込み
  • Matplotlibによる散布図の作成
  • Matplotlibによる散布図の微調整
  • 完成した散布図のコード

上記の内容に沿って、Pythonで簡単に散布図を作成する方法を説明していきます。
まずは、今回用いた環境の説明からです。

Pythonで散布図を作成するための環境

  • Windows 10 Home (バージョン1909)※以下の説明は64bit前提
  • Python 3.7.3
  • NumPy 1.18.5
  • Matplotlib 3.2.1
  • Pandas 0.24.2
  • xlrd 1.2.0

もし、まだMatplotlibの日本語化対応をしていない場合は、次の記事をご覧ください。

Pandasによるエクセルデータの読み込み

ゴール散布図のデータは、次のURLでダウンロード可能です。
http://j-sda.or.jp/about-jsda/weather/kekka4.php

画面の中央に「元データのダウンロードはこちらから」リンクがあります。
これをクリックすれば、ダウンロードが開始します。

ダウンロードしたファイルは、「DL4.xls」です。
エクセルファイルです。
このエクセルファイルをプログラムから読み込む場所に移動しておきます。

xlrdライブラリのインストール

xlrdは、エクセルを扱うためのライブラリです。
これをインストールすれば、Pandasでエクセルを読むことが可能となります。

xlrdライブラリのインストールは、以下のコマンドで行います。

pip install xlrd

エクセルファイルをPandasで読み込む

エクセルの内容は以下。

では、このExcelファイルを読み込みます。
以下のコードだけで、エクセルファイルを読み込むことができます。

なお、エクセルは最初のシートが対象です。
そのため、 read_excelの引数にsheet_name=0と設定しています。

import pandas as pd

df = pd.read_excel('data/DL4.xls', index_col=0)
print(df.head())

結果に以下が表示されれば、OK。

         年月日  平均気温      販売指数      週別指数       週別気温
0 2014-04-01  13.9  2.263703       NaN        NaN
1 2014-04-02  15.2  1.697737       NaN        NaN
2 2014-04-03  13.8  1.407450       NaN        NaN
3 2014-04-04  15.3  1.209598       NaN        NaN
4 2014-04-05  11.4  1.206834  1.227821  13.157143

問題なく読み込めていますね。

Matplotlibによる散布図の作成

散布図の作成方法を具体的に説明していきます。
ただし、今回はゴール画像の一部には対応しません。
その一部とは以下。

  • 回帰分析に関する表示(直線とR[二乗]=0.7898)
  • 「東京都」の太文字

回帰分析まで対応すると、話が広がり過ぎます。
今回は、あくまで散布図の作成がメインです。

また、太文字に関してはフォントが未対応です。
そのため、太文字にする設定が無効となります。

では、早速、簡単な散布図の作成から行いましょう。
以下のコードで散布図を出力できます。

import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_excel('data/DL4.xls', sheet_name=0)

# 欠損値が一つでも含まれる行を削除
df = df.dropna(how='any')
x = df['週別気温']
y = df['週別指数']

# 散布図を描画
plt.scatter(x, y, c=(1.0,0,0))

出力結果は以下。

散布図が、簡単に出ましたね。
では、ここからゴール散布図に見た目を近づけていきます。

以下の記事の内容で対応可能な箇所に変更を加えていきます。

その結果は以下のコード。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_excel('data/DL4.xls', sheet_name=0)

# 欠損値が一つでも含まれる行を削除
df = df.dropna(how='any')
x = df['週別気温']
y = df['週別指数']

# 目盛の値
xscale = np.arange(0, 40, 5)
yscale = np.arange(0, 3, 2.5)

fig = plt.figure(dpi=100, figsize=(4.6,3.8))
fig.suptitle('品目:スポーツ飲料等', fontsize=10, x=0.27, y=0.87)
ax = fig.add_subplot(111)
ax.yaxis.set_label_coords(-0.07,0.4)

# 散布図を描画
plt.scatter(x, y)
plt.title("東京都", fontsize=17)
plt.xticks(xscale, fontsize=8)
plt.yticks(yscale, fontsize=8)
plt.xlabel("平均気温(℃)", fontsize=10)
plt.ylabel("販\n売\n指\n数", fontsize=10, rotation=0)

plt.gca().spines['right'].set_visible(False)

plt.subplots_adjust(left=0.1, right=0.98, bottom=0.13, top=0.89)
plt.savefig("result1.png", facecolor="white")

実行結果は、以下。

ここまでの対応は、既存の知識で対応できました。
ゴール散布図に到達するには、あと2か所の微調整が必要です。

  • 散布図のマーカーを同じ表示にする
  • グラフ表示領域の上の枠線を販売指数2.5に設定する

これらの微調整を以下で行っていきます。

Matplotlibによる散布図の微調整

散布図のマーカーを同じ表示にする

マーカーの色を指定

マーカーの色は、引数「c」で行います。
カラーコードを設定可能です。

plt.scatter(x, y, c='#8cd7f8')

この変更を加えた結果。

散布図のマーカーの色が、変わりました。
しかし、アウトラインがまだ不足しています。

アウトラインの設定

アウトラインの設定は、引数「edgecolors」で行います。
カラーコードを設定可能です。

plt.scatter(x, y, c='#00FFFF', edgecolors="#37BAF2")

この変更を加えた結果は以下。

見事にアウトラインが設定されました。
残るは、y軸の最大を2.5にすることですね。

グラフ表示領域の上の枠線を販売指数2.5に設定する

以下のコードを設定します。

plt.ylim(0.0, 2.5)

もし、x軸の表示領域を制限するなら、次も追加。

plt.xlim(0, 35)

現状、x軸・y軸の目盛は、最大値を工夫することで対応しています。
工夫といっても、値を固定しているだけです。

# 目盛の値
xscale = np.arange(0, 40, 5)
yscale = np.arange(0, 3, 2.5)

ただ、これだと平均気温40度以上や販売指数3以上にも対応できません。
ありえないのでしょうけども・・・

そのため、データの最大値によって、目盛が自動的に決まるようにした方がよいでしょう。
この修正も含めて、次で最終コードを載せます。

完成した散布図のコード

最終コードです。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

df = pd.read_excel('data/DL4.xls', sheet_name=0)

# 欠損値が一つでも含まれる行を削除
df = df.dropna(how='any')
x = df['週別気温']
y = df['週別指数']

# 目盛の値
x_scale = 5
y_scale = 2.5
xscale = np.arange(0, (max(x)+1)*x_scale, x_scale)
yscale = np.arange(0, (max(y)+1)*y_scale, y_scale)

fig = plt.figure(dpi=100, figsize=(4.6,3.8))
fig.suptitle('品目:スポーツ飲料等', fontsize=10, x=0.27, y=0.87)
ax = fig.add_subplot(111)
ax.yaxis.set_label_coords(-0.07,0.4)

# 散布図を描画
plt.scatter(x, y, c='#00FFFF', edgecolors="#37BAF2")
plt.title("東京都", fontsize=17)
plt.xticks(xscale, fontsize=8)
plt.yticks(yscale, fontsize=8)
plt.xlabel("平均気温(℃)", fontsize=10)
plt.ylabel("販\n売\n指\n数", fontsize=10, rotation=0)
plt.xlim(0, 35)
plt.ylim(0.0, 2.5)

plt.gca().spines['right'].set_visible(False)

plt.subplots_adjust(left=0.1, right=0.98, bottom=0.13, top=0.89)
plt.savefig("result1.png", facecolor="white")

このコードの結果。

ゴール散布図をほぼ実現できました。
対応しないと宣言した部分以外では、次の部分が一致していませんね。

散布図のマーカーが、y軸の最大値で一部非表示になるところです。
ただ、これは最大値で表示が切れる方が正しい姿だと思います。

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