はじめに
今回私は最近はやりのchatGPTに興味を持ち、深層学習について学んでみたいと思い立ちました!
深層学習といえばPythonということなので、最終的にはPythonを使って深層学習ができるとこまでコツコツと学習していくことにしました。
ただ、勉強するだけではなく少しでもアウトプットをしようということで、備忘録として学習した内容をまとめていこうと思います。
この記事が少しでも誰かの糧になることを願っております!
※投稿主の環境はWindowsなのでMacの方は多少違う部分が出てくると思いますが、ご了承ください。
最初の記事:Python初心者の備忘録 #01
前の記事:Python初心者の備忘録 #07 ~DSに使われるライブラリ編02~
次の記事:Python初心者の備忘録 #09 ~DSに使われるライブラリ編04~
今回はMatPlotlibについてまとめております。
■学習に使用している資料
Udemy:米国データサイエンティストがやさしく教えるデータサイエンスのためのPython講座
■MatPlotlib
▶MatPlotlibとは
Pythonで数値を可視化(グラフ化)する際に使用されるライブラリの一つ。
使用する際はimport matplotlib.pyplot as plt
とインポートする。
※JupyterLabでは、グラフを描画する際におまじないとして%matplotlib inline
とコードする必要がある。
import matplotlib.pyplot as plt
%matplotlib inline
▶plt.plot(x, y)
それぞれx軸とy軸に数字、または数式を指定することで平面グラフの描画が可能。
plt.plot('column1', 'column2', data=DataFrame)
とすることで、DataFrameの描画も可能。
それぞれ1つの値だけ渡した場合は、indexをx軸、値をy軸に置いたグラフを出力する。
# 平面グラフの描画
# シグモイド関数
x = np.linspace(-10, 10)
y = 1 / (1 + np.exp(-x))
plt.plot(x, y)
# DataFrameの描画
df = pd.DataFrame({'a': [1, 2, 3, 4, 5, 6],
'b': [10, 15, 40, 100, 200, 400]})
plt.plot('a', 'b', data=df)
▶Styleの変更
plt.plot()
のStyle用に様々な引数が設定されている。
線の色を変更するcolor='red'
だったり、線形ls='--'
、線の太さlw='2'
、プロットの形marker='o'
など色々ある。
# よく使われるstyle
# color : グラフの線の色 ⇨ ’red’や’green’のように色の名前を指定します.’r’や’g’のように頭文字でもOKです.
# lw (line width) : 線の太さ ⇨ 数字です.好みの大きさにしてください
# ls (line style) : 線の種類 ⇨ ’-‘や’--‘のように指定します.よく使うのはこの二つのどちらかです.
# marker : マーカーの種類 ⇨ ’o’や’x’ように指定します.マーカーの形が変わります.
# markersize : マーカーの大きさ ⇨ 数字です.好みの大きさにしてください
# markerfacecolor : マーカーの色 ⇨ ’red’や’green’のように色の名前を指定します.’r’や’g’のように頭文字でもOKです.
# markeredgecolor : マーカーの枠に色 ⇨ ’red’や’green’のように色の名前を指定します.’r’や’g’のように頭文字でもOKです.
# markeredgewidth : マーカーの枠の太さ ⇨ 数字です.好みの大きさにしてください
# alpha : plotの透明度 ⇨ 0から1の間をfloatで指定します.0に近い程透明度が上がります.
plt.plot(x, z,
color='red',
lw=5, ls='-',
marker='o',
markersize=2,
markerfacecolor='yellow',
markeredgecolor='blue',
markeredgewidth=4,
alpha=0.5)
※より詳しく知りたい方はCheatsSheetsがあるので、そちらを参照してください。
MatPlotlibチートシート
▶付属情報
グラフの題名やラベルといったよりわかりやすくするための情報の付与が可能。
# plt.xlabel()でx軸にラベルをつける
# plt.ylabel()でy軸にラベルをつける
# plt.title()で図にタイトルをつける
# plt.plot(label=’ラベル’)でplotにラベルをつけ, plt.legend()で凡例をつける
# plt.xticks()でx軸に任意のticksをつける
# plt.yticks()でy軸に任意のticksをつける
# plt.axis(‘off’)で軸を消す
plt.plot(x, z, label='sigmoid')
# 2つのグラフを表示する場合はもう1つplt.plotを作ればOK
plt.plot(x, 2*z, label='sigmoid * 2')
plt.xlabel('x')
plt.ylabel('sigmoid(x)')
plt.title('Sigmoid function')
plt.legend(loc=4)
plt.xticks([1, 2, 3], rotation=20)
plt.yticks([0, 0.5, 1])
Challenge
※挑戦する際は「tmdb_5000_movies.csv」を使用してください。
- 年代別の映画のリリース数をプロット
- 年代別に興行収益(revenue)の中央値、平均値、最大値をプロット
1の解答例
# 年代別のrevenueの平均推移のグラフを描画
df = pd.read_csv('tmdb_5000_movies.csv')
# yeah項目をrelease_dateから作成
df = df.dropna(subset=['release_date'])
df['year'] = df['release_date'].apply(lambda x: int(x[:4]))
# レコード数の年代推移
df = df.sort_values('year')
plt.plot(df.groupby('year').count()['id'])
plt.xlabel('year')
plt.ylabel('count')
2の解答例
# 年代別のrevenueの平均推移のグラフを描画
df = pd.read_csv('tmdb_5000_movies.csv')
# yeah項目をrelease_dateから作成
df = df.dropna(subset=['release_date'])
df['year'] = df['release_date'].apply(lambda x: int(x[:4]))
# revenueの年代の推移を見てみる
df = df[df['revenue']!=0]
plt.plot(df.groupby('year').median()['revenue'], label='median')
plt.plot(df.groupby('year').mean()['revenue'], label='mean')
plt.plot(df.groupby('year')['revenue'].max(), label='max')
plt.legend()
plt.xlabel('year')
plt.ylabel('revenue')
▶複数グラフのプロット
・plt.subplot(nrows=1, ncols=1, index)
nrows
は縦に何個、ncols
は横に何個グラフを作成するか指定することができ、'index'は何個目のグラフについてプロットをするかを指定することができる。
※この時のindex
は0~ではなく、1~なので注意。
x = np.linspace(-10, 10, 100)
# 1(行) x 2(列)のplot.indexは1から始まる.
plt.subplot(1, 2, 1)
#plt.subplot(121) #この書き方も可能
plt.plot(x, x**2)
# 2個目グラフをプロット
plt.subplot(1, 2, 2)
plt.plot(x, x**3)
・plt.figure()
※オブジェクト指向の考え方が出てくるが、深く考えるよりそういうものだと理解するので十分
plt.figure()
でインスタンスを生成し、そのインスタンスに対して.add_subplot(nrows, ncols, index)
でaxesオブジェクトを追加していくイメージ。
x = np.linspace(-10, 10, 100)
# インスタンスの生成
fig = plt.figure()
# subplotを足していくイメージ.axesオブジェクトを作っていく
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(1, 2, 2)
# それぞれのaxesオブジェクトに対して、プロットしていく
ax1.plot(x, x**2)
ax2.plot(x, x**3)
・plt.subplots(nrows=1, ncols=1)
※こちらも.figure()
同様にオブジェクト指向によるものだが、こちらのほうが簡単なのでこちらを使用するのがおすすめ
plt.subplots(nrows, ncols)
でfigure
インスタンスとaxes
オブジェクトを同時に作成することができる。
axes[index].plot()
でグラフのプロットが可能。
作成されたaxes
オブジェクトにはndarrayでax
が保存されているので、plt.subplots(2, 2)
のように複数行、複数列のグラフについては、ndarray
と同じ方法でグラフの指定が可能。
グラフのticksが詰め詰めで見にくい場合は、fig.tight_layout()
で自動調節してくれる。
x = np.linspace(-10, 10, 100)
# インスタンスとオブジェクトの同時作成
fig, axes = plt.subplots(nrows=1, ncols=2)
axes[0].plot(x, x**2)
axes[1].plot(x, x**3)
# 複数行列を作る場合
fig, axes = plt.subplots(nrows=2, ncols=2)
# [行, 列]でindexingする
axes[0, 0].plot(x, x**2)
axes[0, 1].plot(x, x**3)
axes[1, 0].plot(x, x**4)
axes[1, 1].plot(x, x**5)
# 軸のラベル等が被ってみにくい時は
# fig.tight_layout()
#1つの場合でも使える
fig, axes = plt.subplots() #デフォルトはnros=1, ncols=1
axes.plot(x, x**2)
・付属情報の追加(axes.set_xx())
fig, axes = plt.subplots(nrows=1, ncols=2)
# プロットのラベル付与
axes[0].plot(x, x**2, label='something')
axes[1].plot(x, x**3)
# 軸ラベルの追加
axes[0].set_xlabel('xlabel1')
axes[0].set_ylabel('xlabel2')
# タイトルの追加
axes[0].set_title('plot title')
# ticksの調整
axes[0].set_xticks([-3, -2, -1, 3])
axes[0].set_yticks([0, 10, 20])
# legendの追加
axes[0].legend()
# グラフの枠を削除
axes[1].axis('off')
▶散布図(scatterplot)
plt.scatter(x, y)
で簡単に散布図を作成することができる。
引数を渡すことで、様々なグラフの装飾を行うことができる。
alpha=1.0:プロットの透明度、数値が低いほど透明度が上がる。
s=n:プロットのサイズを変更
c='color':プロットの色を指定、数値のリストを渡すことで色の自動割り振りもしてくれる。
plt.annotate('name', (x, y))
で指定した座標(x, y)にname
textを追加することができる。
df = pd.read_csv('tmdb_5000_movies.csv')
# revenueとbudgetの散布図
plt.scatter(df['revenue'], df['budget'], alpha=0.2)
# data引数を使ってもOK
# plt.scatter('revenue', 'budget', data=df, alpha=0.2)
plt.xlabel('revenue')
plt.ylabel('budget')
# 各言語ごとのrevenueとbudgetの平均値の散布図、マーカーの大きさはvote_countの平均
df = df[(df['revenue'] != 0) & (df['budget'] != 0)]
lang_group_df = df.groupby('original_language').mean()[['revenue', 'budget', 'vote_count']]
# 色の指定を数値の連番で自動采配
c = np.arange(len(lang_group_df))
# 「s=」でマーカーのサイズに意味を持たせることもできる
# 今回であれば'vote_count'の平均が大きいほど、プロットが大きくなる
plt.scatter('revenue', 'budget',c=c, s='vote_count' ,data=lang_group_df)
# 各マーカーにtextをいれる
for idx, row in lang_group_df.iterrows():
plt.annotate(idx, (row['revenue'], row['budget']))
plt.xlabel('revenue')
plt.ylabel('budget')
▶ヒストグラム(hist)
何か連続値の比較や統計を確認したいときに使用するグラフ。
plt.hist(x)
でグラフの作成をしてくれる。
このままではndarrayの返り値も表示されるので、それが煩わしい場合はplt.show()
でグラフのみを表示してくれる。
引数にbins=n
を渡すことで、グラフのx軸のプロットをn個に区切るように表示してくれる。
# 映画の評価スコアのヒストグラム
df = pd.read_csv('tmdb_5000_movies.csv')
plt.hist(df['vote_average'])
plt.xlabel('vote_average')
# bins=nを引数に渡すと、x軸のプロット数をその数に分割
df = pd.read_csv('tmdb_5000_movies.csv')
plt.hist(df['vote_average'], bins=50)
plt.xlabel('vote_average')
Challenge
profit(revenue - budget)をヒストグラムで表示
※revenueとbudgetが0のものは排除
※x軸のticksはlogスケールにする ⇒ ヒント
想定グラフ
解答例
#profitのヒストグラム
fig, axes = plt.subplots()
df = df[(df['revenue'] != 0) & (df['budget'] != 0)]
df['profit'] = df.apply(lambda row: row['revenue'] - row['budget'], axis=1)
#x軸をlogスケールにする
logbins = np.logspace(0,np.log10(df['profit'].max()),100)
axes.hist(df['profit'], bins=logbins)
# x軸をlogスケールで表示
axes.set_xscale('log')
▶棒グラフ(bar)
plt.bar(x, y)
で棒グラフの作成ができる。
# 棒グラフの作成
df = pd.DataFrame({'categorical':['A', 'B', 'C'], 'val':[10, 30, 20]})
plt.bar('categorical', 'val', data=df)
# 下記のような書き方もできる
# plt.bar(df['categorical'], df['val'])
▶DataFrameのbuilt in plot
今まではMatPlotlibを使用してグラフの描画してきたが、DataFrameにも描画関数が存在する。
df.plot(x, y, kinb='line')
とすることで、DataFrameのグラフを描画できる。
kind=
によって、グラフの種類を指定することができ、'line', 'scatter', 'hist', 'bar'
など様々存在する。(デフォルトは'line')
df.plot('categorical', 'val', kind='bar', rot=0)
# .plot.bar()でもOK
# df.plot.bar('lab', 'val', rot=0)
# Seriesにも使える.(value_counts()に対してはよく使う)
df = pd.read_csv('tmdb_5000_movies.csv')
df['original_language'].value_counts().plot(kind='bar')
plt.show()
▶箱ひげ図(boxplot)
plt.boxplot(データ)
で表示可能
MatPlotlibでの箱ひげ図の見方は下記のようになる。
中央値:箱の中ほどにある線、データをsortした際に50%に当たる数値
Q3:箱の上端、データをsortした際に75%に当たる数値
Q1:箱の下端、データをsortした際に25%に当たる数値
IQR:Q3 - Q1
髭の上端:Q3 + 1.5 * IQR
髭の下端:Q3 - 1.5 * IQR
外れ値:髭の上端下端外の数値
# 箱ひげ図 (boxplot)
plt.boxplot(df['vote_average'])
▶グラフのサイズ指定
plt.figure(figsiza=(width, height), dpi=n
でグラフのサイズを指定することができる。
(width, height)
はinchスケールで、dpi=n
はnドット/inchを指定できる。
subplots(figsiza(width, height)、dpi=n)
でも指定可能。
※特別理由がなければ、dpi=n
は使わずにMatPlotlibのデフォルトの大きさで使用する
x = np.linspace(-3, 3, 10)
# figsize=(width, height)をinchスケールで,dpiでdots per inchを指定
plt.figure(figsize=(10, 5), dpi=100)
plt.plot(x, x**2)
# オブジェクト指向ではsubplotsの引数に入れる
# fig, axes = plt.subplots(figsize=(10, 5), dpi=100)
# axes.plot(x, x**2)
▶グラフの保存
・pngで保存
plt.savefig('path')
で指定したpathにpng形式で保存可能
オブジェクト指向の場合はfig.savefig('path')
で可能
# png形式で保存
plt.savefig('path')
# オブジェクト指向の場合
fig, axes = plt.subplots(1, 1)
fig.savefig('path')
・PDFで保存
PDFの場合、別でPdfPages
をimportする必要がある。
それからPdfPages('path')
でインスタンスの作成とpathの指定を行い、pdf.savefig(plt)
で保存することができる。
保存後にそれ以上Pdfインスタンスを使用しない場合は、.close()
で閉じるようにする。
# PdfPagesをimport
from matplotlib.backends.backend_pdf import PdfPages
# pdfインスタンス作成
pdf = PdfPages('path')
fig, axes = plt.subplots()
axes.plot(x, x**2)
pdf.savefig(fig)
pdf.close()