📈

ライブラリ「Matplotlib」基礎(可視化)

2023/05/11に公開

[!Important]+ Goals
データ可視化コースでは、Matplotlibを使ってデータを可視化する方法を学びます。折れ線グラフ、円グラフ、ヒストグラムなどの作成から3Dグラフの作成方法まで学びます。

[!abstract]+ Curriculum
1.データ可視化のための準備

  • 様々なグラフ
  • 乱数生成
  • 時系列データ
  • データの操作
  1. Matplotlibの使い方
  • 一種類のデータを可視化しよう
  • 複数のデータを可視化しよう 1
  • 複数のデータを可視化しよう 2
  1. いろいろなグラフを作ろう
  • 折れ線グラフ
  • 棒グラフ
  • ヒストグラム
  • 散布図
  • 円グラフ
  • 3Dグラフ
  • 添削問題

データ可視化のための準備

乱数生成

  • シード設定
    #np/random/seed
import numpy as np


# シードを設定せずに、X, Y にそれぞれ5つの乱数を格納し表示する
print("シードを設定しない場合")

X = np.random.randn(5)
print("X:", X)

Y = np.random.randn(5)
print("Y:", Y)
print()


# シードを設定して、x, y にそれぞれ5つの乱数を格納し表示する
print("シードを設定した場合")

np.random.seed(0)    # シードを設定
x = np.random.randn(5)
print("x:", x)

np.random.seed(1)    # シードを設定
y = np.random.randn(5)
print("y:", y)

# 何も書き込まずに実行してください
  • 正規分布に従う乱数を生成する
    #np/random/normal
import numpy as np
import matplotlib.pyplot as plt

# シードの値を0に設定してください
np.random.seed(0)

# 正規分布に従う乱数を10,000個生成し、変数x に代入してください
x = np.random.randn(10000)

# 可視化
plt.hist(x, bins='auto')
plt.show()
  • 二項分布に従う乱数を生成する
    #np/random/binomial
import numpy as np

# シードを設定
np.random.seed(0)

# 0.5の確率で成功する試行を100回行なったときの成功数を10,000回分求めて変数nums に代入してください
nums = np.random.binomial(100, 0.5, 10000)

# 成功率の平均を出力します
print(nums.mean()/100)
  • リストからランダムに選択
    #np/random/choice
import numpy as np

x = ['Apple', 'Orange', 'Banana', 'Pineapple', 'Kiwifruit', 'Strawberry']

# シードを設定
np.random.seed(0)

# リストx の中からランダムに5個選んで変数y に代入してください
y = np.random.choice(x,5)

print(y)

時系列データ

  • データタイム 타입
    #dt/datetime
import datetime as dt

# 1992年10月22日を表すdatetimeオブジェクトを作成して、変数x に代入してください
x = dt.datetime(1992,10,22)

# 出力
print(x)
  • タイメデルタ 타입
    #dt/timedelta
import datetime as dt

# 1時間半を表すtimedeltaオブジェクトを作成して、変数x に代入してください
x = dt.timedelta(hours = 1.5)

# 出力
print(x)
  • datetime タイプと timedelta タイプの演算
import datetime as dt

# 1992年10月22日を表すdatetimeオブジェクトを生成して、変数x に代入してください
x = dt.datetime(1992,10,22)

# 変数x から1日後を表すdatetimeオブジェクトを変数y に代入してください
y = x + dt.timedelta(days=1)

# 出力
print(y)
  • 時間を表す文字列から datetime オブジェクトを作成します。
    #dt/datetime/str
import datetime as dt

# 1992年10月22日を表す文字列を"年-月-日"の形式で変数s に代入してください
s = "1992-10-22"

# 変数s を1992年10月22日を表すdatetimeオブジェクトに変換して、変数x に代入してください
x = dt.datetime.strptime(s, "%Y-%m-%d")

# 出力
print(x)

データ操作

  • 変換 : 文字列タイプ → 数値タイプ
# 変数x, y に文字列を代入
x = '64'
y = '16'

# 変数x, y を int() を用いて数値型に変換し、数値的な和を変数z に代入してください
z = int(x) + int(y)

# 変数x, yを文字列のまま足したものを変数cに代入してください。
c = x+y

# 変数の値を出力
print(z)
print(c)
  • 等間隔数列生成 1 : 間隔指定
    #np/arange
import numpy as np

# 変数x に0から10までの偶数列を代入してください
x = np.arange(0, 11, 2)

# 出力
print(x)
  • 等間隔列生成2:個数指定。指定がなければ50個がデフォルト。
    #np/linspace
import numpy as np

# 0から10までの範囲を等間隔に分ける5点を変数x に代入してください
x = np.linspace(0,10,5)

# 出力
print(x)

Matplotlib の使い方

#matplotlib(マットプロットリブ

一種類のデータを可視化しよう

#plt #plt/lim #plt/title #plt/label #plt/grid #plt/ticks

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 2*np.pi)
y = np.sin(x)

# グラフのタイトルを設定する
plt.title("y=sin(x)")

# グラフのx軸とy軸にラベルを設定する
plt.xlabel("x-axis")
plt.ylabel("y-axis")

# グラフにグリッドを表示する
plt.grid(True)

plt.ylim([-1.5, 1.5])

# positionsとlabelsの設定
positions = [0, np.pi/2, np.pi, np.pi*3/2, np.pi*2]
labels = ["0°", "90°", "180°", "270°", "360°"]

# グラフのx軸に目盛りを設定してください
plt.xticks(positions, labels)

# データx, yをグラフにプロットし、表示する
plt.plot(x, y)
plt.show()

様々な種類のデータを可視化しよう 1

#plt/レジェンド #plt/カラー

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 2*np.pi)
y1 = np.sin(x)
y2 = np.cos(x)

# グラフのタイトルを設定する
plt.title("graphs of trigonometric functions")

# グラフのx軸とy軸にラベルを設定する
plt.xlabel("x-axis")
plt.ylabel("y-axis")

# グラフにグリッドを表示する
plt.grid(True)

# positionsとlabelsの設定
positions = [np.pi/2, np.pi, np.pi*3/2, np.pi*2]
labels = ["90°", "180°", "270°", "360°"]

# グラフのx軸に目盛りを設定する
plt.xticks(positions, labels)

# データx, y1 をグラフにプロットし、"y=sin(x)"と系列ラベルを設定して赤で表示してください
plt.plot(x,y1,label="y=sin(x)", color='r')

# データx, y2 をグラフにプロットし、"y=cos(x)"と系列ラベルを設定して青で表示してください
plt.plot(x,y2,label="y=cos(x)", color='b')

# 系列ラベルを表示してください
plt.legend()

plt.show()

様々な種類のデータを可視化しよう 2

#plt/figsize #plt/subplot #plt/adjust #plt/subplot/lim #plt/subplot/title #plt/subplot/label #plt/subplot/grid #plt/subplot/ticks

import matplotlib.pyplot as plt
import numpy as np

x = np.linspace(0, 2*np.pi)
y = np.sin(x)

positions = [0, np.pi/2, np.pi, np.pi*3/2, np.pi*2]
labels = ["0°", "90°", "180°", "270°", "360°"]

# figureオブジェクトを作成
fig = plt.figure(figsize=(9, 6))

# figureを2×3に分割
# 5番目にはデータx, yをプロットし、他は空白のままにしておく
ax1 = fig.add_subplot(2, 3, 1)
ax2 = fig.add_subplot(2, 3, 2)
ax3 = fig.add_subplot(2, 3, 3)
ax4 = fig.add_subplot(2, 3, 4)
ax5 = fig.add_subplot(2, 3, 5)
ax5.plot(x, y)
ax6 = fig.add_subplot(2, 3, 6)

# サブプロットax5のグラフにグリッドを表示してください
ax5.grid(True)

# figure内のaxesを、縦横ともに1の間隔を空けてください。
fig.subplots_adjust(wspace = 1, hspace=1)

# サブプロットax5のy軸の表示範囲を 0〜1 に設定してください。
ax5.set_ylim([0,1])

# サブプロットax5のグラフのタイトルを "y=sin(x)" に設定してください
ax5.set_title("y=sin(x)")

# サブプロットax5のx軸のラベルを "x-axis"、y軸のラベルを "y-axis" に設定してください
ax5.set_xlabel("x-axis")
ax5.set_ylabel("y-axis")

# サブプロットax5のグラフのx軸に目盛りを設定してください
ax5.set_xticks(positions)

# サブプロットax5のグラフのx軸に目盛りのラベルを設定してください
ax5.set_xticklabels(labels)

plt.show()

いろいろなグラフを作ろう

折れ線グラフ

import numpy as np
import matplotlib.pyplot as plt

days = np.arange(1, 11)
weight = np.array([10, 14, 18, 20, 18, 16, 17, 18, 20, 17])

# 表示の設定
plt.ylim([0, weight.max()+1])
plt.xlabel("days")
plt.ylabel("weight")

# 円マーカーを赤色でプロットし、青の破線の折れ線グラフを作成してください
plt.plot(days, weight, linestyle="--", color="b", marker="o", markerfacecolor="r")

plt.show()

バーグラフ

#plt/バー #plt/バー/tick_label #plt/バー/stacked

import numpy as np
import matplotlib.pyplot as plt

x = [1, 2, 3, 4, 5, 6]
y1 = [12, 41, 32, 36, 21, 17]
y2 = [43, 1, 6, 17, 17, 9]
labels = ["Apple", "Orange", "Banana", "Pineapple", "Kiwifruit", "Strawberry"]

# 積み上げ棒グラフを作成し、横軸にラベルを設定してください
plt.bar(x,y1 , tick_label=labels)
# bottomで値を指定することでその分の余白が出来る
plt.bar(x, y2, bottom=y1)

# 系列ラベルの設定が可能
plt.legend(("y1", "y2"))

plt.show()

ヒストグラム

#plt/hist #plt/hist/bins #plt/hist #plt/hist/normalize #plt/hist/cumulative

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(0)
data = np.random.randn(10000)

# 正規化されたビン数100の累積ヒストグラムを作成してください
plt.hist(data, bins=100, density=True, cumulative=True)

plt.show()

散布図

#plt/scatter #plt/scatter/marker #plt/scatter/marker_size

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(0)
x = np.random.choice(np.arange(100), 100)
y = np.random.choice(np.arange(100), 100)
z = np.random.choice(np.arange(100), 100)

# マーカーの種類を四角、色を赤に設定して散布図を作成してください
plt.scatter(x,y,marker="s",color='r', s = z)

plt.show()

#plt/スキャッター/グラデーション #plt/カラーバー

import numpy as np
import matplotlib.pyplot as plt

np.random.seed(0)
x = np.random.choice(np.arange(100), 100)
y = np.random.choice(np.arange(100), 100)
z = np.random.choice(np.arange(100), 100)

# 変数zに応じた値で、マーカーの色を青系統のグラデーションで表示してください
plt.scatter(x, y, c=z, cmap="Blues")

# カラーバーを表示してください
plt.colorbar()

plt.show()

円グラフ

#plt/パイ #plt/軸 #plt/パイ/ラベル #plt/パイ/エクスプロード

import matplotlib.pyplot as plt

data = [60, 20, 10, 5, 3, 2]
labels = ["Apple", "Orange", "Banana", "Pineapple", "Kiwifruit", "Strawberry"]
explode = [0, 0, 0.1, 0, 0, 0]

# 変数dataに変数labelsのラベルを指定し、Bananaを目立たせた円グラフを描画してください
plt.pie(data, labels = labels, explode = explode)

plt.axis("equal")
plt.show()

3Dグラフ

#plt/3d #plt/3d/surface #plt/3d/gradation

  • 3Dグラフを描くには、3D機能を持つサブプロットを作成する必要があります。
    • projection="3d" を指定します。
import numpy as np
import matplotlib.pyplot as plt

# 3D描画を行うために必要なライブラリ
from mpl_toolkits.mplot3d import Axes3D
# カラーマップを表示するためのライブラリ
from matplotlib import cm

t = np.linspace(-2*np.pi, 2*np.pi)
X, Y = np.meshgrid(t, t)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)

# Figureオブジェクトを作成
fig = plt.figure(figsize=(6, 6))
# サブプロットaxを追加
ax = fig.add_subplot(111, projection="3d")

# サブプロットaxにzの値にカラーマップを適用してください
ax.plot_surface(X,Y,Z,cmap=cm.coolwarm)

plt.show()

#plt/3d/バー

import matplotlib.pyplot as plt
import numpy as np

# 3D描画を行うために必要なライブラリ
from mpl_toolkits.mplot3d import Axes3D

# Figureオブジェクトを作成
fig = plt.figure(figsize=(5, 5))
# サブプロットaxを追加
ax = fig.add_subplot(1,1,1, projection="3d")

# x, y, zの位置を決める
xpos = [i for i in range(10)]
ypos = [i for i in range(10)]
zpos = np.zeros(10)

# x, y, zの変化量を決める
dx = np.ones(10)
dy = np.ones(10)
dz = [i for i in range(10)]

# 3次元のbarを作成してください
ax.bar3d(xpos,ypos,zpos,dx,dy,dz)

plt.show()

#plt/3d/スキャッター

import numpy as np
import matplotlib.pyplot as plt

# 3D描画を行うために必要なライブラリ
from mpl_toolkits.mplot3d import Axes3D

np.random.seed(0)
x = np.random.randn(1000)
y = np.random.randn(1000)
z = np.random.randn(1000)

# Figureオブジェクトを作成
fig = plt.figure(figsize=(6, 6))
# サブプロットaxを追加
ax = fig.add_subplot(1,1,1, projection="3d")

# 3D散布図を作成してください
ax.scatter3D(x,y,z)

plt.show()

添削問題

基本 : 2x2 サブプロット

  • マルチプロット、線の色とスタイルの指定
import math
import matplotlib.pyplot as plt
import numpy as np

# 描画用の点を用意しています
x1 = np.linspace(-1, 1, 200)
y1 = [x**4 - x**2 + 6 for x in x1]
x2 = np.linspace(-8, -1, 700)
y2 = [12 / (abs(x) + 1) for x in x2]
x3 = np.linspace(1, 8, 700)
y3 = [12 / (abs(x) + 1) for x in x3]
x4 = np.linspace(-2, 2, 400)
y4 = [1/2 * math.cos(6*x) + 7/2 for x in x4]
  
# figureオブジェクトを作成してください
fig = plt.figure()
  
# axesオブジェクトを2行2列に分割し、左上に (x1,y1) を描画してください
ax1 = fig.add_subplot(2,2,1)
ax1.plot(x1,y1)
  
# axesオブジェクトを2行2列に分割し、右上に (x2,y2), (x3,y3) を重ねて描画してください
# なお、グラフの色は全て赤色にしてください
ax2 = fig.add_subplot(2,2,2)
ax2.plot(x2,y2, 'r',
         x3,y3,'r')

# axesオブジェクトを2行2列に分割し、左下に (x4,y4) を描画してください
# なお、グラフのスタイルは破線にしてください
ax3 = fig.add_subplot(2,2,3)
ax3.plot(x4,y4, linestyle="--")
  
# axesオブジェクトを2行2列に分割し、右下に (x1,y1), (x2,y2), (x3,y3), (x4,y4) を重ねて描画してください
# なお、グラフの色は全て青色にしてください
ax4 = fig.add_subplot(2,2,4)
ax4.plot(x1,y1,'b',
         x2,y2,'b',
         x3,y3,'b',
         x4,y4,'b')

plt.show()

応用 : モンテカルロ法

import matplotlib.pyplot as plt
import numpy as np
import math
import time
  
np.random.seed(100)
X = 0  # 的に当たった回数です
  
# 試行回数Nを指定してください。
N = 100000
# 四分円の境界の方程式[y=√1-x^2 (0<=x<=1)]を描画しています。
circle_x = np.arange(0, 1, 0.001)
circle_y = np.sqrt(1 - circle_x * circle_x)
plt.figure(figsize=(5, 5))
plt.plot(circle_x, circle_y)
  
# N回の試行にかかる時間を計測します。
start_time = time.perf_counter()
  
#プロット用の空の配列を用意
internal_x = []
internal_y = []
external_x = []
external_y = []
  
# N回の試行を行っています。
for i in range(N):
    # 0から1の間で一様乱数を発生させ、変数score_xに格納してください。
    score_x = np.random.rand()
    # 0から1の間で一様乱数を発生させ、変数score_yに格納してください。
    score_y = np.random.rand()
    if score_x * score_x + score_y * score_y <= 1:
        # 的に入ったものはinternal_x, internal_yに追加してください。
        internal_x.append(score_x)
        internal_y.append(score_y)
        # 得点Xを1追加してください
        X += 1
  
    else:
        # 的から外れたものはexternal_x, external_yに追加してください。
        external_x.append(score_x)
        external_y.append(score_y)
  
# piの近似値をここで計算してください。
# 小数のpiを求めるため、明示的にXとNをfloat()に入れてください。
pi = 4 * float(X) / float(N)
  
# モンテカルロ法の実行時間を計算しています。
end_time = time.perf_counter()
time = end_time - start_time
  
# 円周率の結果を表示
print("円周率:%.6f" % pi)
print("実行時間:%f" % (time))
  
# 散布図を描画してください。四分円内にある点は赤で、四分円外にある点は青で描画してください。
plt.scatter(internal_x, internal_y, c = 'r')
plt.scatter(external_x, external_y, c = 'b')  

# 結果を表示
plt.grid(True)
plt.xlabel('X')
plt.ylabel('Y')
plt.show()

Discussion