PythonのライブラリであるMatplotlibを使用することで、2次元のグラフを作成することができます。
今回は、Excelファイルのデータを読み込み、matplotlibでグラフ化(エラーバー付きの複数棒グラフ)する方法をご紹介します。
実施環境
■ 使用したPC
- ASUS Zenbook 14(UM425QA-KIR915WS)
- OS:Windows 11 Home 64bit
スペックの詳細はこちらの記事に書いています。
■ 参考図書
Python初心者向けのテキストです。今回はこちらの2冊を参考にしました。
Pythonでグラフを作成する
Python(Matplotlib)でグラフを作成する流れは、以下の通りです。
- Step 0JupyterLabを起動する
- Step 1Excelファイルをアップロードする
- Step 2データを読み込む
- Step 3データを整形する
- Step 4データをグラフ化する
- Step 5グラフの外観を設定する
それぞれのやり方について、以下で詳しく見ていきます。
JupyterLabを起動する
前準備として、Webブラウザ上でPythonコードを実行するために「JupyterLab」を起動します。
JupyterLabの起動までの方法は、以下の記事で詳しく説明しています。
Excelファイルをアップロードする
グラフにするデータが含まれたExcelファイルを、JupyterLabを実行しているフォルダにアップロードします。
JupyterLabの左上にあるアイコンをクリックして、Excelファイルを選択します。
Excelファイルがアップロードされると、左メニューにファイル名が表示されます。
データを読み込む
pandasでアップロードしたExcelファイルのデータを読み込みます。
#グラフ描画に必要なライブラリをimportする
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
#Excelファイルを読み込む
df = pd.read_excel('speedtest_data_netcafe.xlsx')
df
上のコードを実行すると、Excelファイルのデータが読み込まれ、2次元データのDataFrame(データフレーム)として出力されました。
ちなみに、今回使用するExcelファイル「speedtest_data_netcafe.xlsx」のデータは、筆者がネットカフェで計測したVPN有無によるネットワーク通信速度の比較データです。
データを整形する
Excelファイルから読み込んだデータは、グラフ描画に必要のないデータも含まれているため、扱いやすいように不要な列(カラム)の削除やデータの抽出を行います。
不要な列(カラム)を削除する
まず、1行目の「ID」の列(カラム)を削除します。
#1列目の「ID」を削除
df = df.drop('ID', axis=1)
df
1行目の「ID」のカラムが削除されました。
条件を指定してデータを抽出する
今回のデータは、次の2種類に区別することができます。
- PCがWindows、VPNあり
- PCがWindows、VPNなし
これらのデータが1つのテーブルとして読み込まれているので、それらを抽出して2つのDataFrameに分割します。
まず「PCがWindows、VPNあり」のデータを抽出します。
#PCがWindows、VPNありのデータを抽出
df_win_vpn = df[
(df['pc'] == 'windows') &
(df['vpn'] == 1)
]
df_win_vpn
同様にして、「df_win_novpn」も作成します。
#PCがWindows、VPNなしのデータを抽出
df_win_novpn = df[
(df['pc'] == 'windows') &
(df['vpn'] == 0)
]
各データの抽出ができたら、「vpn」カラムを削除します。
#「vpn」カラムを削除
df_win_vpn = df_win_vpn.drop('vpn', axis=1)
df_win_novpn = df_win_novpn.drop('vpn', axis=1)
基本統計量を出力する
DataFrameごとの基本統計量(最大値、最小値、平均値など)を出力して、データの概要を確認しておきます。
#describeメソッドでDataFrameの基本統計量を出力
df_win_vpn.describe()
download_megabits | upload_megabits | latency_ms | |
---|---|---|---|
count | 5.000000 | 5.000000 | 5.00000 |
mean | 28.846000 | 29.528000 | 10.80000 |
std | 6.917054 | 9.337287 | 1.30384 |
min | 17.610000 | 17.610000 | 10.00000 |
25% | 28.310000 | 25.770000 | 10.00000 |
50% | 29.260000 | 26.550000 | 10.00000 |
75% | 34.230000 | 36.650000 | 11.00000 |
max | 34.820000 | 41.060000 | 13.00000 |
出力された各項目の意味は、以下の通りです。
- count:データの個数(欠損値は含まない)
- mean:平均値
- std:標本標準偏差
- min:最小値
- 25%:第1四分位数
- 50%:中央値
- 75%:第3四分位数
- max;最大値
データの整形については以上です。
データをグラフ化する
ここからは、Matplotlibでデータをグラフ化していきます。
生データをそのままグラフ化したいときは、次のコードを実行します。
#棒グラフを描画する
df_win_vpn.plot.bar()
棒グラフをカラムごとに分けて表示したい場合は、次の通りです。
#カラムごとの棒グラフを描画する
df_win_vpn.plot.bar(subplots=True)
データの平均値や標準偏差を計算してグラフ化する場合は、まず各データの統計量を計算します。
#「windows、VPNあり」の平均値と標準偏差を計算
win_vpn_mean_values = df_win_vpn[['download_megabits', 'upload_megabits', 'latency_ms']].mean()
win_vpn_std_values = df_win_vpn[['download_megabits', 'upload_megabits', 'latency_ms']].std()
print(win_vpn_mean_values)
print(win_vpn_std_values)
download_megabits 28.846
upload_megabits 29.528
latency_ms 10.800
dtype: float64
download_megabits 6.917054
upload_megabits 9.337287
latency_ms 1.303840
dtype: float64
上のように計算された数値は、2次元データのDataFrameではなく、1次元データのSeries(シリーズ)と呼ばれます。
計算した結果を用いて、以下のようにグラフ化します。
#平均値の棒グラフを描画する
x = np.arange(len(win_vpn_mean_values))
width = 0.5
fig, ax = plt.subplots()
ax.bar(x, win_vpn_mean_values, width=width, align='center')
plt.ylabel('Mean Value')
plt.xticks(x, ['download_megabits', 'upload_megabits', 'latency_ms'])
plt.show()
グラフの外観を設定する
単純なグラフが作成できたら、次はグラフの外観(見た目)を設定していきます。
今回は、次の3つのやり方についてご紹介します。
- 複数の棒グラフを並べる
- エラーバーを付ける
- 目盛りを内側にする
複数の棒グラフを並べる
以下のように書くと、複数の棒グラフを並べて描画できます。
#複数の棒グラフを描画する
x = np.arange(len(win_vpn_mean_values))
width = 0.3
fig, ax = plt.subplots()
ax.bar(x, win_vpn_mean_values, width=width, label='win_vpn', align='center')
ax.bar(x+width, win_novpn_mean_values, width=width, label='win_novpn', align='center')
ax.bar(x+width*2, mac_novpn_mean_values, width=width, label='mac_novpn', align='center')
ax.legend()
plt.ylabel('Mean Value')
plt.xticks(x+width*2/2, ['download_megabits', 'upload_megabits', 'latency_ms'])
plt.show()
エラーバーをつける
以下のように書くと、エラーバー付き棒グラフを描画できます。
#エラーバー付き棒グラフを描画する
x = np.arange(len(win_vpn_mean_values))
width = 0.6
fig, ax = plt.subplots()
ax.bar(x, win_vpn_mean_values, yerr=win_vpn_std_values, width=width, align='center', ecolor='black', capsize=5)
plt.ylabel('Mean Value')
plt.xticks(x, ['download_megabits', 'upload_megabits', 'latency_ms'])
plt.show()
パラメータ | 意味 |
---|---|
x | 棒グラフのX軸方向の位置(配列) |
win_vpn_mean_values | 棒グラフのY軸方向の値(配列) |
yerr | エラーバー(標準偏差)の値(配列) |
width | 棒グラフの幅 |
align | X軸の目盛の位置 |
ecolor | エラーバーの色 |
capsize | エラーバーの横線の長さ |
複数種類の棒グラフにエラーバーを付けるには、次のように書きます。
#エラーバー付きの複数の棒グラフを描画する
x = np.arange(len(win_vpn_mean_values))
width = 0.3
fig, ax = plt.subplots()
ax.bar(x, win_vpn_mean_values, yerr=win_vpn_std_values, width=width, label='win_vpn', align='center', ecolor='black', capsize=5)
ax.bar(x+width, win_novpn_mean_values, yerr=win_novpn_std_values, width=width, label='win_novpn', align='center', ecolor='black', capsize=5)
ax.legend()
plt.ylabel('Mean Value')
plt.xticks(x+width/2, ['download_megabits', 'upload_megabits', 'latency_ms'])
plt.show()
目盛りを内側にする
グラフの目盛りを内側にするには、以下のように設定します。
#目盛りを内側にしたエラーバー付きの複数の棒グラフを描画する
x = np.arange(len(win_vpn_mean_values))
width = 0.3
fig, ax = plt.subplots()
ax.bar(x, win_vpn_mean_values, yerr=win_vpn_std_values, width=width, label='win_vpn', align='center', ecolor='black', capsize=5)
ax.bar(x+width, win_novpn_mean_values, yerr=win_novpn_std_values, width=width, label='win_novpn', align='center', ecolor='black', capsize=5)
ax.legend()
plt.ylabel('Mean Value')
plt.xticks(x+width/2, ['download_megabits', 'upload_megabits', 'latency_ms'])
#X軸とY軸の目盛を内側にする
plt.rcParams['xtick.direction'] = 'in'
plt.rcParams['ytick.direction'] = 'in'
plt.show()
参考
・神戸学院大学 経営学部 林坂ゼミ | Matplotlib
・matplotlib エラーバー付きのグラフを描く #Python – Qiita
・python:matplotlib:目盛りの設定 [雑多な記録]
まとめ
以上、Excelファイルのデータを読み込み、matplotlibでグラフ化(エラーバー付きの複数棒グラフ)する方法をご紹介しました。
今回参考にした『Pythonによるあたらしいデータ分析の教科書 第2版』では、Python初心者に向けて環境設定のやり方やデータ分析の方法が分かりやすく書かれています。
よければ参考に覗いてみてください。
最後まで読んでくださり、ありがとうございました!
(ご質問・ご感想はこちらからどうぞ)