matplotlib (Python のライブラリ)を使って、グラフを作成する方法を解説します
完成形のグラフ
使用するデータ
題材は、気温、日照時間、寡照時間の推移を使用します(気象庁データベース引用)
名称の定義
グラフの各箇所の名称を定義しておきます
グラフ(デフォルト)を表示する
import matplotlib.pyplot as plt
fig=plt.figure()
ax1=fig.add_subplot()
plt.show()
print(plt.rcParams["font.family"])
print(plt.rcParams["figure.dpi"])
print(plt.rcParams["figure.figsize"])
print(plt.ylim())
print(plt.xlim())
コードの解説
行2
import matplotlib.pyplot as plt
matplotilib の pyplot をインポートする
行4
fig=plt.figure()
グラフの表示領域の下地を宣言
行5
ax1=fig.add_subplot()
グラフに軸を追加する
行7
plt.show()
グラフを表示する
行9
plt.rcParams["font.family"]
フォントファミリーを取得
行10
plt.rcParams["figure.dpi"]
解像度dpiを取得
dpi は、ピクセル数 / インチ
行11
plt.rcParams["figure.figsize"]
グラフのサイズ(横、縦) 単位は、インチ
行12
plt.ylim()
Y軸の幅(最小値、最大値)
行13
plt.xlim()
X軸の幅(最小値、最大値)
デフォルトでは、次のように表示されます
printで出力した結果です
主なデフォルトの値
グラフのサイズ(縦、横):640px、480px
フォントファミリ:sans-serif
x軸の幅(最小値、最大値):0.0、1.0
y軸の幅(最小値、最大値):0.0、1.0
エクセルのデータを追加
import matplotlib.pyplot as plt
import pandas as pd
df=pd.read_excel('data.xlsx')
day=df['日付'].to_list()
ondo=df['温度'].to_list()
fig=plt.figure()
ax1=fig.add_subplot()
ax1.plot(day,ondo)
plt.show()
コードの解説 (追加分)
行3
import pandas as pd
pandas をインポートする
行5
df = pd.read_excel(‘data.xlsx’)
エクセルファイルのデータをDataFrame型に変換
行6-7
day=df[‘日付’].to_list()
DataFrameの一部をリスト型に変換
行11
ax1.plot(day, ondo)
軸に折れ線グラフを追加する
エクセル内のデータ形式が日付の場合、そのデータをpandasで読み込むと、pandas.timestamp型となります
pandas.timestamp型の表示形式は、デフォルトで、”{年}-{月}” となります
日付の表示形式を変更
import matplotlib.pyplot as plt
import pandas as pd
df=pd.read_excel('data.xlsx')
day=df['日付'].to_list()
ondo=df['温度'].to_list()
for i in range(len(day)):
day[i]=str(day[i].year + '年' + str(day[i].month) + '月')
fig=plt.figure()
ax1=fig.add_subplot()
ax1.plot(day,ondo)
plt.show()
コードの解説 (追加分)
行9-10
for i in range(len(day)):
{処理内容}
配列内の要素に対して、同じ処理を繰り返す
day[i]=str(day[i].year) + '年' + str(day[i].month) + '月'
{pandas.timestamp型} → str型に変換
2023-04-01 00:00:00 → 2023年4月に表示を変換
{pandas.timestamp型} .year / month
「 年 」/ 「 月 」の値を取得します int型で出力されます
str()
{pandas.timestamp型} .year /monthは、int型で出力されます
後で他のstr型と連結できるように、str型に変換します
年、月 (日本語フォント)が、文字化けしています
これは、フォントファミリがまだ非日本語フォントのままだからです
目盛値の表示が重なってしまっています
フォントとグラフの幅を設定
import matplotlib.pyplot as plt
import pandas as pd
df=pd.read_excel('data.xlsx')
day=df['日付'].to_list()
ondo=df['温度'].to_list()
for i in range(len(day)):
day[i]=str(day[i].year + '年' + str(day[i].month) + '月')
plt.rcParams["font.family"]="MS Gothic"
fig=plt.figure()
fig.set_figwidth(12)
ax1=fig.add_subplot()
ax1.plot(day,ondo)
plt.show()
コードの解説 (追加分)
行12
plt.rcParams["font.family"]="MS Gothic"
フォントファミリーを、”MS Gothic” に変更
行15
fig.set_figwidth(12)
グラフの幅を12インチに変更します
解像度dpi=100のため、1200pxになります
デフォルトでは、
・軸のラベル、グラフのマーカーがない
・グラフの色は、青
です
また、x軸の目盛値の間隔が狭いです
グラフの各種設定
import matplotlib.pyplot as plt
import pandas as pd
df=pd.read_excel('data.xlsx')
day=df['日付'].to_list()
ondo=df['温度'].to_list()
for i in range(len(day)):
day[i]=str(day[i].year + '年' + str(day[i].month) + '月')
plt.rcParams["font.family"]="MS Gothic"
fig=plt.figure()
fig.set_figwidth(12)
ax1=fig.add_subplot()
ax1.set_ylabel("平均温度(度)",labelpad=5)
ax1.plot(day,ondo,color='darkorange',marker='o')
ax1.tick_params(axis="x",labelrotation=5)
plt.show()
コードの解説 (追加分)
行18
ax1.set_ylabel("平均温度(度)",labelpad=5)
軸のラベルを設定します
labelpad=5
軸とラベルとの間隔を設定します
行19
ax1.plot(day,ondo,color='darkorange',marker='o')
グラフの色とマーカーを設定します
color : グラフの色
marker : マーカーの形状
行20
ax1.tick_params(axis="x",labelrotation=5)
x軸の目盛値の傾きを設定
axis : 軸の設定
labelrotation : 角度の設定
もう一つ軸を追加
import matplotlib.pyplot as plt
import pandas as pd
df=pd.read_excel('data.xlsx')
day=df['日付'].to_list()
ondo=df['温度'].to_list()
nisho=df['日照時間'].to_list()
kasho=df['寡照時間'].to_list()
for i in range(len(day)):
day[i]=str(day[i].year + '年' + str(day[i].month) + '月')
plt.rcParams["font.family"]="MS Gothic"
fig=plt.figure()
fig.set_figwidth(12)
ax1=fig.add_subplot()
ax1.set_ylabel("平均温度(度)",labelpad=5)
ax1.plot(day,ondo,color='darkorange',marker='o')
ax1.tick_params(axis="x",labelrotation=5)
ax2=ax1.twinx()
p1=ax2.bar(day,kasho)
p1=ax2.bar(day.nisho)
plt.show()
コードの解説 (追加分)
行8-9
nisho=df['日照時間'].to_list()
DataFrameの一部をリスト型に変換します
行24
ax2=ax1.twinx()=df['日照時間'].to_list()
軸を追加する
行26-27
p1=ax2.bar(day,kasho)
軸に棒グラフを追加する
実行結果
エラー発生してしまいます
.bar の 引数は、float型に対応しています
kashoの要素のデータ型が、datetime.time型のままとなっています
import matplotlib.pyplot as plt
import pandas as pd
def float_time(pd_ts):
return pd_ts.hour + pd_ts.minute / 60
df=pd.read_excel('data.xlsx')
day=df['日付'].to_list()
ondo=df['温度'].to_list()
nisho=df['日照時間'].to_list()
kasho=df['寡照時間'].to_list()
for i in range(len(day)):
day[i]=str(day[i].year + '年' + str(day[i].month) + '月')
for i in range(len(nisho)):
nisho[i]=float_time(nisho[i])
for i in range(len(kasho)):
kasho[i]=float_time(kasho[i])
plt.rcParams["font.family"]="MS Gothic"
fig=plt.figure()
fig.set_figwidth(12)
ax1=fig.add_subplot()
ax1.set_ylabel("平均温度(度)",labelpad=5)
ax1.plot(day,ondo,color='darkorange',marker='o')
ax1.tick_params(axis="x",labelrotation=5)
ax2=ax1.twinx()
p1=ax2.bar(day,kasho)
p1=ax2.bar(day.nisho)
plt.show()
コードの解説 (追加分)
行5-6
def float_time(pd_ts):
return pd_ts.hour + pd_ts.minute / 60
float_timeという関数を宣言
{pandas.timestamp型} .hour : 「 時 」を取得
int型で出力される
{pandas.timestamp型} .hour : 「 分 」を取得
int型で出力される
数値の単位を、「 時 」にあわせるため、「 分 」の値を、60で除する
int型 ÷ int型 → float型となる
int型 + float型 → float型となる
日照時間、寡照時間の棒グラフが重なってしまっています
積み上げグラフにする
import matplotlib.pyplot as plt
import pandas as pd
def float_time(pd_ts):
return pd_ts.hour + pd_ts.minute / 60
df=pd.read_excel('data.xlsx')
day=df['日付'].to_list()
ondo=df['温度'].to_list()
nisho=df['日照時間'].to_list()
kasho=df['寡照時間'].to_list()
for i in range(len(day)):
day[i]=str(day[i].year + '年' + str(day[i].month) + '月')
for i in range(len(nisho)):
nisho[i]=float_time(nisho[i])
for i in range(len(kasho)):
kasho[i]=float_time(kasho[i])
plt.rcParams["font.family"]="MS Gothic"
fig=plt.figure()
fig.set_figwidth(12)
ax1=fig.add_subplot()
ax1.set_ylabel("平均温度(度)",labelpad=5)
ax1.plot(day,ondo,color='darkorange',marker='o')
ax1.tick_params(axis="x",labelrotation=5)
ax2=ax1.twinx()
p1=ax2.bar(day,kasho)
p1=ax2.bar(day.nisho,bottom=kasho)
plt.show()
コードの解説 (追加分)
行36
p2=ax.bar(day,nisho,bottom=kasho)
積み上げ棒グラフに設定します
bottomに、他方の棒グラフを設定します
折れ線グラフと棒グラフが重なってしまっています
目盛値の最小値 / 最大値の設定
import matplotlib.pyplot as plt
import pandas as pd
def float_time(pd_ts):
return pd_ts.hour + pd_ts.minute / 60
df=pd.read_excel('data.xlsx')
day=df['日付'].to_list()
ondo=df['温度'].to_list()
nisho=df['日照時間'].to_list()
kasho=df['寡照時間'].to_list()
for i in range(len(day)):
day[i]=str(day[i].year + '年' + str(day[i].month) + '月')
for i in range(len(nisho)):
nisho[i]=float_time(nisho[i])
for i in range(len(kasho)):
kasho[i]=float_time(kasho[i])
plt.rcParams["font.family"]="MS Gothic"
fig=plt.figure()
fig.set_figwidth(12)
ax1=fig.add_subplot()
ax1.set_ylabel("平均温度(度)",labelpad=5)
ax1.plot(day,ondo,color='darkorange',marker='o')
ax1.tick_params(axis="x",labelrotation=5)
ax1.set_ylim(-15,35)
ax2=ax1.twinx()
ax2.set_ylim(0,80)
p1=ax2.bar(day,kasho)
p1=ax2.bar(day.nisho,bottom=kasho)
plt.show()
コードの解説 (追加分)
行32,35
ax1.set_ylim(-15,35)
y軸の最小値と最大値を設定します
折れ線グラフと棒グラフが同じ色
y軸(右側)にラベルがない
という状況です
グラフの各種設定
import matplotlib.pyplot as plt
import pandas as pd
def float_time(pd_ts):
return pd_ts.hour + pd_ts.minute / 60
df=pd.read_excel('data.xlsx')
day=df['日付'].to_list()
ondo=df['温度'].to_list()
nisho=df['日照時間'].to_list()
kasho=df['寡照時間'].to_list()
for i in range(len(day)):
day[i]=str(day[i].year + '年' + str(day[i].month) + '月')
for i in range(len(nisho)):
nisho[i]=float_time(nisho[i])
for i in range(len(kasho)):
kasho[i]=float_time(kasho[i])
plt.rcParams["font.family"]="MS Gothic"
fig=plt.figure()
fig.set_figwidth(12)
ax1=fig.add_subplot()
ax1.set_ylabel("平均温度(度)",labelpad=5)
ax1.plot(day,ondo,color='darkorange',marker='o')
ax1.tick_params(axis="x",labelrotation=5)
ax1.set_ylim(-15,35)
ax2=ax1.twinx()
ax2.set_ylim(0,80)
ax2.set_ylabel("日照時間 / 寡照時間(時間)",labelpad=10)
p1=ax2.bar(day,kasho,color='lightgrey')
p1=ax2.bar(day.nisho,bottom=kasho,color='darkturquoise')
plt.show()
コードの解説 (追加分)
行36
ax2.set_ylabel("日照時間 / 寡照時間(時間)",labelpad=10)
軸のラベルを設定します
labelpad : 軸とラベルとの距離を設定
行38-39
p1=ax2.bar(day,kasho,color='lightgrey')
グラフの色を設定します
color : グラフの色
参考サイト : 設定可能な色
グラフにまだテキストが表示されていない状態です
グラフにテキストを追加
import matplotlib.pyplot as plt
import pandas as pd
def float_time(pd_ts):
return pd_ts.hour + pd_ts.minute / 60
df=pd.read_excel('data.xlsx')
day=df['日付'].to_list()
ondo=df['温度'].to_list()
nisho=df['日照時間'].to_list()
kasho=df['寡照時間'].to_list()
for i in range(len(day)):
day[i]=str(day[i].year + '年' + str(day[i].month) + '月')
for i in range(len(nisho)):
nisho[i]=float_time(nisho[i])
for i in range(len(kasho)):
kasho[i]=float_time(kasho[i])
plt.rcParams["font.family"]="MS Gothic"
fig=plt.figure()
fig.set_figwidth(12)
ax1=fig.add_subplot()
ax1.set_ylabel("平均温度(度)",labelpad=5)
ax1.plot(day,ondo,color='darkorange',marker='o')
ax1.tick_params(axis="x",labelrotation=5)
ax1.set_ylim(-15,35)
for i,value in enumerate(ondo):
ax1.text(day[i],ondo[i],value)
ax2=ax1.twinx()
ax2.set_ylim(0,80)
ax2.set_ylabel("日照時間 / 寡照時間(時間)",labelpad=10)
p1=ax2.bar(day,kasho,color='lightgrey')
p1=ax2.bar(day.nisho,bottom=kasho,color='darkturquoise')
ax2.bar_label(p1)
ax2.bar_label(p2)
plt.show()
コードの解説 (追加分)
行34-35
for i,value in enumerate(ondo):
ax1.text(day[i],ondo[i],value)
折れ線グラフにテキストを追加します
for i,value in enumerate(ondo):
配列から、添字と値を取得します
ax1.text(day[i], ondo[i], value)
折れ線グラフにテキストを追加します
第1引数 : x軸の値
第2引数 : y軸の値
第3引数 : 表示するテキスト
行44-45
ax2.bar_label(p1)
棒グラフにテキストを追加します
折れ線グラフとテキストが重なっています
棒グラフのテキストがfloat型となっています
import matplotlib.pyplot as plt
import pandas as pd
def float_time(pd_ts):
return pd_ts.hour + pd_ts.minute / 60
df=pd.read_excel('data.xlsx')
day=df['日付'].to_list()
ondo=df['温度'].to_list()
nisho=df['日照時間'].to_list()
kasho=df['寡照時間'].to_list()
for i in range(len(day)):
day[i]=str(day[i].year + '年' + str(day[i].month) + '月')
for i in range(len(nisho)):
nisho[i]=float_time(nisho[i])
for i in range(len(kasho)):
kasho[i]=float_time(kasho[i])
plt.rcParams["font.family"]="MS Gothic"
fig=plt.figure()
fig.set_figwidth(12)
ax1=fig.add_subplot()
ax1.set_ylabel("平均温度(度)",labelpad=5)
ax1.plot(day,ondo,color='darkorange',marker='o')
ax1.tick_params(axis="x",labelrotation=5)
ax1.set_ylim(-15,35)
for i,value in enumerate(ondo):
ax1.text(day[i],ondo[i]-3,value)
ax2=ax1.twinx()
ax2.set_ylim(0,80)
ax2.set_ylabel("日照時間 / 寡照時間(時間)",labelpad=10)
p1=ax2.bar(day,kasho,color='lightgrey')
p1=ax2.bar(day.nisho,bottom=kasho,color='darkturquoise')
labels1=[]
labels2=[]
for tmp in df['寡照時間']:
labels1.append(tmp.strftime('%H:%M'))
for tmp in df['日照時間']:
labels2.append(tmp.strftime('%H:%M'))
ax2.bar_label(p1,labels=labels1)
ax2.bar_label(p2,labels=labels2)
plt.show()
コードの解説 (追加分)
行35
ax1.text(day[i],ondo[i]-3,value)
テキストの位置を設定する
第2引数に、「 -3 」を追記することで、 テキストの位置を下側へ設定する
行44-45
labels1=[]
配列を宣言する
行47,50
for tmp in df['寡照時間']:
DataFrame内の一部の要素を取得する
行48,51
labels1.append(tmp.strftime('%H:%M'))
配列にデータを追加する
tmp.strftime('%H:%M')
{pandas.timestamp型}から、「 時 」と 「 分 」を取得する
str型で出力される
折れ線グラフとテキストが、一部重なっています
棒グラフのテキストの位置が棒グラフの位置から離れています
import matplotlib.pyplot as plt
import pandas as pd
def float_time(pd_ts):
return pd_ts.hour + pd_ts.minute / 60
df=pd.read_excel('data.xlsx')
day=df['日付'].to_list()
ondo=df['温度'].to_list()
nisho=df['日照時間'].to_list()
kasho=df['寡照時間'].to_list()
for i in range(len(day)):
day[i]=str(day[i].year + '年' + str(day[i].month) + '月')
for i in range(len(nisho)):
nisho[i]=float_time(nisho[i])
for i in range(len(kasho)):
kasho[i]=float_time(kasho[i])
plt.rcParams["font.family"]="MS Gothic"
fig=plt.figure()
fig.set_figwidth(12)
ax1=fig.add_subplot()
ax1.set_ylabel("平均温度(度)",labelpad=5)
ax1.plot(day,ondo,color='darkorange',marker='o')
ax1.tick_params(axis="x",labelrotation=5)
ax1.set_ylim(-15,35)
posi=0
for i,value in enumerate(ondo):
if i==5:
posi=2
elif i==6 or i==7:
posi=-4
else:
posi=-3
ax1.text(day[i],ondo[i]+posi,value)
ax2=ax1.twinx()
ax2.set_ylim(0,80)
ax2.set_ylabel("日照時間 / 寡照時間(時間)",labelpad=10)
p1=ax2.bar(day,kasho,color='lightgrey')
p1=ax2.bar(day.nisho,bottom=kasho,color='darkturquoise')
labels1=[]
labels2=[]
for tmp in df['寡照時間']:
labels1.append(tmp.strftime('%H:%M'))
for tmp in df['日照時間']:
labels2.append(tmp.strftime('%H:%M'))
ax2.bar_label(p1,labels=labels1,label_type='center')
ax2.bar_label(p2,labels=labels2,label_type='center')
plt.show()
コードの解説 (追加分)
行34
posi=0
変数の宣言と初期化
行36-41
if i==5:
posi=2
6番目の要素に対して、位置を再設定する
添字は、0始まり
行60-61
ax2.bar_label(p1,labels=labels1,label_type=‘center’)
ラベルの位置を、棒グラフの上下中央に設定する
凡例を設定する
import matplotlib.pyplot as plt
import pandas as pd
def float_time(pd_ts):
return pd_ts.hour + pd_ts.minute / 60
df=pd.read_excel('data.xlsx')
day=df['日付'].to_list()
ondo=df['温度'].to_list()
nisho=df['日照時間'].to_list()
kasho=df['寡照時間'].to_list()
for i in range(len(day)):
day[i]=str(day[i].year + '年' + str(day[i].month) + '月')
for i in range(len(nisho)):
nisho[i]=float_time(nisho[i])
for i in range(len(kasho)):
kasho[i]=float_time(kasho[i])
plt.rcParams["font.family"]="MS Gothic"
fig=plt.figure()
fig.set_figwidth(12)
ax1=fig.add_subplot()
ax1.set_ylabel("平均温度(度)",labelpad=5)
ax1.plot(day,ondo,color='darkorange',marker='o')
ax1.tick_params(axis="x",labelrotation=5)
ax1.set_ylim(-15,35)
posi=0
for i,value in enumerate(ondo):
if i==5:
posi=2
elif i==6 or i==7:
posi=-4
else:
posi=-3
ax1.text(day[i],ondo[i]+posi,value)
ax2=ax1.twinx()
ax2.set_ylim(0,80)
ax2.set_ylabel("日照時間 / 寡照時間(時間)",labelpad=10)
p1=ax2.bar(day,kasho,color='lightgrey')
p1=ax2.bar(day.nisho,bottom=kasho,color='darkturquoise')
labels1=[]
labels2=[]
for tmp in df['寡照時間']:
labels1.append(tmp.strftime('%H:%M'))
for tmp in df['日照時間']:
labels2.append(tmp.strftime('%H:%M'))
ax2.bar_label(p1,labels=labels1,label_type='center')
ax2.bar_label(p2,labels=labels2,label_type='center')
ax1.legend(labels=['平均温度'])
ax1.legend(labels=['寡照時間','日照時間'])
plt.show()
コードの解説 (追加分)
行63-64
ax1.legend(labels=['平均温度'])
軸の凡例を追加する
labels : 凡例に表示する文字列の設定
平均温度の凡例が隠れてしまっています
凡例の表示順序が逆になってしまっています(日照時間→寡照時間としたい)
凡例の枠が表示されています
import matplotlib.pyplot as plt
import pandas as pd
def float_time(pd_ts):
return pd_ts.hour + pd_ts.minute / 60
df=pd.read_excel('data.xlsx')
day=df['日付'].to_list()
ondo=df['温度'].to_list()
nisho=df['日照時間'].to_list()
kasho=df['寡照時間'].to_list()
for i in range(len(day)):
day[i]=str(day[i].year + '年' + str(day[i].month) + '月')
for i in range(len(nisho)):
nisho[i]=float_time(nisho[i])
for i in range(len(kasho)):
kasho[i]=float_time(kasho[i])
plt.rcParams["font.family"]="MS Gothic"
fig=plt.figure()
fig.set_figwidth(12)
ax1=fig.add_subplot()
ax1.set_ylabel("平均温度(度)",labelpad=5)
ax1.plot(day,ondo,color='darkorange',marker='o')
ax1.tick_params(axis="x",labelrotation=5)
ax1.set_ylim(-15,35)
posi=0
for i,value in enumerate(ondo):
if i==5:
posi=2
elif i==6 or i==7:
posi=-4
else:
posi=-3
ax1.text(day[i],ondo[i]+posi,value)
ax2=ax1.twinx()
ax2.set_ylim(0,80)
ax2.set_ylabel("日照時間 / 寡照時間(時間)",labelpad=10)
p1=ax2.bar(day,kasho,color='lightgrey')
p1=ax2.bar(day.nisho,bottom=kasho,color='darkturquoise')
labels1=[]
labels2=[]
for tmp in df['寡照時間']:
labels1.append(tmp.strftime('%H:%M'))
for tmp in df['日照時間']:
labels2.append(tmp.strftime('%H:%M'))
ax2.bar_label(p1,labels=labels1,label_type='center')
ax2.bar_label(p2,labels=labels2,label_type='center')
ax1.legend(labels=['平均温度'],frameon=False)
ax1.legend(handles=[p2,p1],labels=['寡照時間','日照時間'],bbox_to_anchor=(1,0.94),frameon=False)
plt.show()
コードの解説 (追加分)
行63-64
ax1.legend(labels=['平均温度'],frameon=False)
frameon : 凡例の枠の設定
行64
ax2.legend( handles = [p2,p1], labels = [ ‘日照時間’ , ‘寡照時間’ ],
bbox_to_anchor = (1, 0.94), frameon = False)
凡例の順序と位置を設定します
handles : 凡例の順書を設定
bbox_to_anchor : 凡例の位置を設定
基準の座標 (左下) から、どれだけの位置にあるかを設定
デフォルトは、(1, 1) で右上となる
これで冒頭の完成形となります
matplotlibでグラフを作成する方法の解説はこれで終了です
2軸、折れ線グラフ、棒グラフ、テキストの追加、色の変更、マーカーの追加、凡例の追加などができるようになったと思います
汎用性のある題材としていますので、他のデータでグラフを作成するときにご活用ください
コメント