こんにちは。
今回は matplotlib の使い方、すなわちグラフの描図の仕方について入門編から実務で使用するテクニックまでをピックアップして解説していきます。
本記事の学習内容
- matplotlibを使った描図の基本 -折れ線グラフの描き方-
- 代表的なグラフの紹介
- 多数のグラフを同時に描図する方法
- 近似直線の描き方
では早速みていきましょう。
matplotlibの使い方【描図の基本編】
matplotlibの使い方|折れ線グラフの描き方【手順あり】
早速、matplotlibの使い方のうち、グラフの描図の仕方について解説していきます。
まずカンタンなグラフの描き方について折れ線グラフの描き方で解説していきます。
Matplotlibを使用したグラフを描く手順は以下のとおりです。
グラフを描く手順
- matplotlib.pyplot をimportします
- グラフ化したいデータを読み込みます
- グラフを作成します
- 作成したグラフを表示します
これだけの手順です。
早速グラフを描いてみましょう。
matplotlib.pyplot をimportする方法
この3行をコピペして貼り付けてください。
たったこれだけでグラフを描くモジュールをインポートできます。
1 2 3 4 | %matplotlib inline import matplotlib.pyplot as plt import numpy as np |
これを呪文の様に覚えておきましょう。
ちなみに一行目の %matplotlib inline はJupyter Notebookでは必須です。(Pythonファイルからであれば記載する必要がありません。)
また、2行目の import matplotlib.pyplot as plt
を記入することで、matplotlib.pyplot
を plt
という名前で使うことができます。matplotlib.pyplot
をメソッドと合わせて使用する際には plt.メソッド()
と記入だけでokです。
エラーの対応策
以下の様なエラーが出てきた場合の解決策
1 | ModuleNotFoundError: No module named 'matplotlib.artist' |
または
1 | ModuleNotFoundError: No module named 'matplotlib' |
この様なエラーが出てきた場合には、インストールしていたmatplotlibが壊れている可能性もあります。
その際には、以下のコードをまず実行し、強制的にmatplotlibをインストールしましょう。
1 | conda install matplotlib --force |
matplotlib.piplot でデータを準備して描図してみる
まず、グラフとして描きたいデータを ndarray 形式で入力します。
ここでは、np.random.rand()
を用いて数値 x, y をランダムに20個用意します。
ランダムに20個用意下あとはx に 1を加えた値と、y を3倍下値を代入し、グラフに表示させます。
1 2 3 4 5 6 7 | x = np.random.rand(20) y = np.random.rand(20) x += 1 y *= 3 plt.plot(x, y) |
これを表示すると以下の様な図ができます。
あちこちに散らばっていて分かりにくいですね。
原因は $x$, $y$ が非常にバラバラなのに対して直線で一点一点ずつ結んで行こうとしたからです。
もう少し直線のグラフを作っていきましょう。
matplotlib.piplot で滑らかなグラフを描図してみる
先ほどはめっちゃ折れ曲がったグラフができましたので、比較的きれいな直線を描いてみましょう。
1 2 3 4 5 6 7 8 9 | %matplotlib inline import matplotlib.pyplot as plt import numpy as np x = np.arange(1, 21) y = np.random.rand(20) y *= 3 plt.plot(x, y) |
$x $ 軸は np.arange(1, 21)
としたので、1〜21までの配列です。
$y$ 軸は、1未満の値でランダムな数の要素を20個集めた配列です。
$x$ と $y$ を各々20個ずつ集めるのがポイントですね。
それだと値が小さすぎるので、値を3倍にしています。
グラフを表示する際にはplt.plot(横軸$x$, 縦軸$y$)
と記載します。
こちらが、描図したグラフとなります。
描図するグラフの種類について
グラフのスタイル(破線や点、色など)を決定するには plot()
の引数() に追加で情報を記入します。
スタイル | キーワード引数 | コード | 種類 |
線の種類 | linestyle | linestyle = "--" | 破線 |
点の記号 | marker | marker = "<" | triangle_leftマーカー |
線の色 | color | color = "b" | 青色 |
他にも色々な種類のマーキングの仕方があります。
matplotlib.piplot のNtes の欄を参照して色々な表示の仕方について確認してみてください。
描図するグラフに装飾を加える
グラフに装飾を加える plt.plot()
描画するグラフに色々な装飾を加える差異には plt.plot() の引数に色々加えます。
1 2 3 4 5 6 7 8 9 10 11 12 | # '-.' : 一点鎖線のスタイル # o: サークルマーカー # m: マゼンタ %matplotlib inline import matplotlib.pyplot as plt import numpy as np x = np.arange(1, 21) y = np.random.rand(20) y *= 3 plt.plot(x, y, linestyle = "-.", marker = "o", color = "m") |
※ グラフの装飾は plt.plot()
を実行すると毎回削除されてリセットできます。
グラフにパーツを加える plt.title()
グラフのタイトルや横軸、縦軸のラベルや目盛の有無などを加える方法もあります。
メソッド | 利用例 | |
---|---|---|
タイトル | title() | plt.title("time - salary") |
横軸 | xlabel() |
|
縦軸 | ylabel() | plt.ylabel("salary") |
目盛 | grid() | plt.grid(False) |
※ そのほかの設定項目は、以下の公式サイトをご参照ください。
>> The pyplot API - Matplotlib documentation
では格子も使用してグラフを描いてみましょう。
1 2 3 4 5 6 7 8 | x = np.array([2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017]) y = np.array([300, 400, 450, 550, 600, 1200, 1300, 1450]) plt.title("time - salary") plt.xlabel("time") plt.ylabel("salary") plt.grid(True) plt.plot(x, y) |
代表的なグラフの種類
棒線グラフ(縦は plt.bar()
, 横は plt.barh()
)
縦の棒グラフは plt.bar()
、横の棒グラフは plt.barh()
となります。
まずは 横棒グラフ plt.barth()
から描きます。
1 2 3 | time = np.array([2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017]) salary = np.array([300, 400, 450, 550, 600, 1200, 1300, 1450]) plt.barh(time, salary) |
次に縦棒のグラフplt.bar()
を描いていきます。
1 2 3 | time = np.array([2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017]) salary = np.array([300, 400, 450, 550, 600, 1200, 1300, 1450]) plt.bar(time, salary) |
以下の公式ドキュメントも参考にしてください。
matplotlib.pyplot.bar - Matplotlib documentation
matplotlib.pyplot.barh - Matplotlib documentation
散布図
散布図は plt.scatter()
を使用します。
例えばカップラーメンの値段とバナナの値段をお店別にプロットした表を作成してみます。
1 2 3 4 | noodle = np.array([70, 95, 83, 100, 72, 71, 75, 85, 67, 75]) banana = np.array([90, 82, 100, 95, 50, 81, 52, 56, 67, 71]) plt.scatter(noodle, banana) |
こんな感じになります。plt.scatter()
公式ドキュメントも参照してください。
円グラフ
円グラフは plt.pie()
を使用します。
1 2 3 4 5 6 7 8 9 10 11 12 | %matplotlib inline import matplotlib.pyplot as plt import numpy as np cause_of_death = np.array(["malignant_neoplasm", "heart_disease", "pneaumonia", "cerebrovascular_disease", "aging", "accident", "suicide","oters"]) percent = np.array([29, 15, 10, 9, 6, 3, 2, 26]) # %.1f%% は小数点以下が1桁でパーセント記号を表示するという指定 # startangle は 円グラフを開始する角度で、時計でいう3時の方向を0度として反時計回りに何度か、という指定をします。 # このキーワードには90と指定したので、時計でいう12時の方向から反時計回りにグラフを描きます。 plt.pie(percent, labels = cause_of_death, autopct = "%.1f%%", startangle = 90) |
少し見えにくいかもしれませんが、描図するとこの様な感じになります。
普通時計回りかと思いきや、半時計回りに描かれるのがポイントです。autopct
はデータの書式設定のことです。%.1f%%
は小数点以下が1桁で%で表示する、という意味を持ちます。%%
としているのは「%
をパーセント記号として表示」するという意味です。startangle
は 円グラフをスタートさせる角度です。時計の3時方向をスタートと地点して反時計回りに何度か、という指定をします。
上にも記載しましたが、謎に半時計回りです。
ヒストグラム
次にヒストグラムについて解説します。
まずはライブラリを読み込みます。
1 2 | import numpy as np import matplotlib.pyplot as plt |
正規分布( 平均0、分散1
)のデータを作成します。
1 2 | a = np.random.randn(100) b = np.random.randn(100) |
シンプルに1つ正規分布を描画します。
※ 乱数なので結果は都度変わります。
1 | plt.hist(a) |
これだけでは実用的ではないので、パラメータ(表示オプション)指定しつつ、a
、b
の二つを並べて表示します。
パラメータは10数個あるので、今回は代表的なものを使っています。
パラメータは、「引数を個別にする場合」と「辞書型で指定する場合」の両方を試してみましょう。
辞書型の場合、引数に渡すときに **変数名
とします。
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 辞書型で指定 param_a = {'x': a, 'range': (-5, 5), #x軸範囲 'bins': 10, #ピン数 'color': 'red', #色 'alpha':0.3,#透明度, 'label': 'a' #凡例 } plt.hist(**param_a) # 個別に指定 plt.hist(x=b, range=(-5, 5), bins=10, color='blue', alpha=0.5, label='b') # 凡例を表示 plt.legend() |
っこで、2つのデータを並べたり、データを積み上げて表示する場合には、x
, color
, label
に2つ分渡します。
1 2 3 4 5 6 7 8 9 10 11 12 | a = np.random.randn(100) b = np.random.randn(100) param = {'x': [a, b], 'range': (-5, 5), #x軸範囲 'bins': 10, #ピン数 'color': ['red', 'blue'], #色 'alpha':0.3,#透明度, 'label': ['a', 'b'], #凡例 'stacked': False #積み上げ棒にするかどうか } plt.hist(**param) plt.legend()# 凡例の表示 |
以下stacked
を True
にした場合のグラフになります。
以下stacked
を False
にした場合のグラフになります。
» matplotlib.pyplot.hist の公式ドキュメント
ボックスプロット
次に、ボックスプロットに関する解説です。
まず、ライブラリを読み込みます。
1 2 | import numpy as np import matplotlib.pyplot as plt |
データを準備します。
今回は先ほどヒストグラムで使った、乱数を10個をリストに入れます。
1 2 | # np.random.randn(100)を10個用意します。 data = [np.random.randn(100) for i in range(10)] |
では、グラフを描写していましょう。
1 2 | plt.boxplot(data) plt.show() |
boxplot
は横軸がカテゴリ名の場合が多いので、$X$ 軸のラベルの変更をします。
それと、$Y$ 軸の変更もしてみましょう。
$Y$軸の範囲は棒グラフとかでも使う、pyplot
の ylimメソッド
を使います。
おまけで、ボックスの幅を変えてみます。
1 2 3 4 5 6 7 | labels = ['one','two','three','four','five','six','seven','eight','night','ten'] plt.boxplot(data, widths=0.2 , # ボックスの幅 labels=labels #凡例 ) plt.ylim(-5, 5) # pltのylimで範囲指定 plt.legend() # 凡例の表示 |
» matplotlib.pyplot.boxplot の公式ドキュメント
多数のグラフを同時に表示する
あるグラフに別のグラフを追加する
ある青い線のグラフと同じ領域に赤い線のグラフを描く場合、plt.plot()
を指定します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | x1 = np.array([2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017]) y1 = np.array([300, 400, 450, 550, 600, 1200, 1300, 1450]) x2 = np.array([2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017]) y2 = np.array([1350, 1100, 950, 850, 800, 700, 550, 350]) plt.title("time - salary") plt.xlabel("time") plt.ylabel("salary") plt.grid(True) plt.plot(x1, y1, color="red", label = "salary_man1") plt.plot(x2, y2, color="blue", label = "salary_man2") plt.legend(loc = "upper left") |
plt.legend()
はグラフのラベルを表示するメソッドです。
このグラフでは左上にラベルを表示させてみました。表示場所の指定の仕方については、以下のサイトを参考にしてください。
>>matplotlib.pyplot.legend - Matplotlib documentation
2つのグラフを横に並べて表示する
次に、2つのグラフを作って横並びにするメソッドを紹介します。
plt.figure()
を実行するだけです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | x1 = np.array([2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017]) y1 = np.array([300, 400, 450, 550, 600, 1200, 1300, 1450]) x2 = np.array([2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017]) y2 = np.array([1350, 1100, 950, 850, 800, 700, 550, 350]) fig = plt.figure() sp1 = fig.add_subplot(1, 2, 1) sp1.plot(x1, y1, color="red", label = "salary_man1") sp2 = fig.add_subplot(1, 2, 2) sp2.plot(x2, y2, color="blue", label = "salary_man2") |
ココがポイント
- add_subplot(x,
y, z)
の引数の書き方について解説します。 - 引数のうちの最初の2つ(x と y)は「縦 x 行、横 y 列」のグラフを作るという意味です。
- 3つ目の引数 z は何番目にグラフを表示するかを意味します。
複数表示のレイアウト
subplot
は均等にグラフが配置されますが、1つのグラフは大きめに表示したい場合などあると思います。
その場合は、subplot2grid
を使います。
使い方は、下記となります。何行、何列目の指定は0からの数字です。
1 | plt.subplot2grid((行数, 列数), (何行, 何列), rowspan=? ,colspan=?) |
実際に、先ほどの折れ線グラフにヒストグラムを足してみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | x1 = np.array([2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017]) y1 = np.array([300, 400, 450, 550, 600, 1200, 1300, 1450]) x2 = np.array([2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017]) y2 = np.array([1350, 1100, 950, 850, 800, 700, 550, 350]) a = np.random.randn(100) fig = plt.figure() # 2行×2列の1行目、1列目 plt.subplot2grid((2,2), (0,0)) plt.plot(x1, y1, color="red", label = "salary_man1") # 2行×2列の1行目、2列目 plt.subplot2grid((2,2), (0,1)) plt.plot(x2, y2, color="blue", label = "salary_man2") # 2行×2列の2行目、1列目 で列を2つ結合 plt.subplot2grid((2, 2), (1, 0), colspan=2) plt.hist(x=a, range=(-5, 5), bins=10, color='blue', alpha=0.5, label='b') plt.show() |
如何でしょうか。上記の様に表示されましたでしょうか。
近似直線の描いてみる
最後に散布図のグラフに近似直線を描いてみましょう。
近似直線を描くためには単回帰分析が必要ですが、単回帰分析と最小2乗法については以下の記事で紹介していますので、参考にしてください。
【Python】単回帰分析と最小2乗法の求め方【機械学習入門】
続きを見る
もしくは、こちらのサイトも参考になるのでご参照ください。
>> 最小二乗法 - Wikipedia
さらにNumPyでは、最小二乗法による近似直線の式を簡単に導出できるメソッドが用意されています。np.polyfit()
です。
こちらを用いることで、近似直線(一次関数)の式 y = ax + b
の a
と b
を求めることができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # サンプルデータ x = np.array([55, 59, 62, 76, 64, 65, 68, 55, 64, 72, 85, 77, 58, 65]) y = np.array([166, 169, 171, 182, 177, 182, 175, 167, 172, 168, 179, 185, 163, 175]) plt.title("weight - length") plt.xlabel("weight") plt.ylabel("length") plt.grid(True) # 近似直線の式の a と b が入ったタプルを得る p = np.polyfit(x, y, 1) # 一次関数の式のオブジェクトを生成する f = np.poly1d(p) # 散布図と近似直線を描く plt.scatter(x, y, color = "b", label="score") plt.plot(x, f(x), color = "r", label="Ism") plt.legend(loc='lower right') |
np.polyfit()
の引数は3つあります。
1番目と2番目の引数は、それぞれ横軸と縦軸のデータの配列です。
3つ目は、●次関数の●を示しています。
このメソッドの戻り値は y = ax + b
のうち a
と b
の値が入ったタプルのデータです。
次に np.poly1d()
を実行しています。これは先ほど出した式(一時関数)のオブジェクトを生成するという意味があります。a * x + b
と自分で式を記述しても良いですが、np.poly1d()
と記載することで、plt.plot(x, f(x))
の中に f(x)
と書くことができます。np.polyfit()
→ np.poly1d()
→ plt.plot(x, f(x))
この流れをつかみましょう。
便利機能|グラフを画像として保存する機能
現場で上司に報告するためのレポート作成する時があるかと思います。
その際に、jupyter notebokで表示されたものをそのまま見せるわけにもいかないので、グラフをレポートに貼り付けると便利です。
そんな時、MacやWindowsのスクリーンショット機能でもよいですが、グラフを画像として保存する機能があるので、使うと便利です。
グラフを表示する前に下記を追加してみましょう。
1 2 3 4 | fig = plt.figure() #グラフのサイズは 引数にfigsize=(幅,高さ)を指定すると変更可能 fig = plt.figure(figsize=(10,8)) |
表示後にファイル名を引数に渡して下記を追加します。
1 | fig.savefig(ファイル名) |
非常に簡単ですね。実際の保存しみましょう。
1 2 3 4 5 | time = np.array([2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017]) salary = np.array([300, 400, 450, 550, 600, 1200, 1300, 1450]) fig = plt.figure() # 追加 plt.bar(time, salary) fig.savefig('graph.png') # 追加 引数に保存ファイル名 |
これだけで保存することが可能です。
便利な機能ですので、是非利用して下さい。
まとめ|matplotlibの使い方【基礎から応用まで】
matplotlibの基本的な内容から具体的な描図の方法まで解説させて頂きました。
さらっと流していますが、この記事を読み終えた頃には最終的に最小2乗法を用いて単回帰分析を用いて近似曲線をpythonを使用して描くことができる様になっています。
今回は以上でおわりとします。