散布図を描く方法を学びます。分析をしているときかなりの頻度で使うので、ぜひマスターして欲しいです。 以下、おまじないとして書いてください。乱数を生成するコードです。
import numpy as np
# 右上に集中させた乱数
mu = [1.0, 1.0]
sigma = [[0.1, 0], [0, 0.1]]
Dat01 = np.random.multivariate_normal(mu, sigma, 100)
# 右下に集中させた乱数
mu = [1.0, -1.0]
sigma = [[0.1, 0], [0, 0.1]]
Dat02 = np.random.multivariate_normal(mu, sigma, 100)
# 左上に集中させた乱数
mu = [-1.0, 1.0]
sigma = [[0.1, 0], [0, 0.1]]
Dat03 = np.random.multivariate_normal(mu, sigma, 100)
# 左下に集中させた乱数
mu = [-1.0, -1.0]
sigma = [[0.1, 0], [0, 0.1]]
Dat04 = np.random.multivariate_normal(mu, sigma, 100)
以下がテンプレートです。コメントを見ればわかると思います。変えながらどう変化するかチェックして見てください。
import matplotlib.pyplot as plt
x = Dat01[:,0]
y = Dat01[:,1]
plt.figure(figsize=(5, 4)) # figureの縦横の大きさ
plt.scatter(x, y, # 横軸、縦軸の値
s=30, # マーカサイズ
c='orange', # マーカの色(red, blue, pink, yellow, orange, blackなど)
marker='s', #マーカの形(.osなど:下記参照)
alpha=0.8, # 塗りつぶしの透明度(0:完全に透明〜1:透明にしない)
linewidths=0.5, # マーカの線の太さ
edgecolors='black') # マーカの線の太さ(マーカの色と同じ。不要の場合は''なしでNone)
plt.title("Title") # タイトル
plt.xlabel("x axis") # 軸名
plt.ylabel("y axis") #軸名
plt.grid(True) #グリッド線(True:引く、False:引かない)
plt.xlim(-2.5, 2.5) # 横軸最小最大
plt.ylim(-2.5, 2.5) # 縦軸最小最大
plt.show() # グラフの表示
いっぱいあります。 https://matplotlib.org/examples/color/named_colors.html
基本的には、並べればokです。重ねる回数が多くなる場合には、for文の利用も検討してください。複数重ねる場合は、どのデータかわかりやすくするために、色やマーカの形を変更させます。公表する論文誌がグレースケールでわかるようにせよ、とか指示が出てくるので、マーカの形を変えたほうが無難です。また、どのプロットがなんなのかわかりやすくするために、凡例をつけます。以下のlegendを参照してください。
# リストに、生成したデータを入れます。
x = [Dat01[:,0], Dat02[:,0], Dat03[:,0], Dat04[:,0]]
y = [Dat01[:,1], Dat02[:,1], Dat03[:,1], Dat04[:,1]]
plt.figure(figsize=(5, 4)) # figureの縦横の大きさ
# 1つ目
plt.scatter(x[0], y[0], # 横軸、縦軸の値
s=30, # マーカサイズ
c='orange', # マーカの色(red, blue, pink, yellow, orange, blackなど)
marker='s', #マーカの形(.osなど:下記参照)
alpha=0.8, # 塗りつぶしの透明度(0:完全に透明〜1:透明にしない)
linewidths=0.5, # マーカの線の太さ
edgecolors='black') # マーカの線の太さ(マーカの色と同じ。不要の場合は''なしでNone)
# 2つ目
plt.scatter(x[1], y[1], # 横軸、縦軸の値
s=30, # マーカサイズ
c='red', # マーカの色(red, blue, pink, yellow, orange, blackなど)
marker='*', #マーカの形(.osなど:下記参照)
alpha=0.8, # 塗りつぶしの透明度(0:完全に透明〜1:透明にしない)
linewidths=0.5, # マーカの線の太さ
edgecolors='black') # マーカの線の太さ(マーカの色と同じ。不要の場合は''なしでNone)
# 3つ目
plt.scatter(x[2], y[2], # 横軸、縦軸の値
s=30, # マーカサイズ
c='blue', # マーカの色(red, blue, pink, yellow, orange, blackなど)
marker='^', #マーカの形(.osなど:下記参照)
alpha=0.8, # 塗りつぶしの透明度(0:完全に透明〜1:透明にしない)
linewidths=0.5, # マーカの線の太さ
edgecolors='black') # マーカの線の太さ(マーカの色と同じ。不要の場合は''なしでNone)
# 4つ目
plt.scatter(x[3], y[3], # 横軸、縦軸の値
s=30, # マーカサイズ
c='black', # マーカの色(red, blue, pink, yellow, orange, blackなど)
marker='o', #マーカの形(.osなど:下記参照)
alpha=0.8, # 塗りつぶしの透明度(0:完全に透明〜1:透明にしない)
linewidths=0.5, # マーカの線の太さ
edgecolors='black') # マーカの線の太さ(マーカの色と同じ。不要の場合は''なしでNone)
plt.title("Title") # タイトル
plt.xlabel("x axis") # 軸名
plt.ylabel("y axis") #軸名
plt.grid(True) #グリッド線(True:引く、False:引かない)
plt.xlim(-2.5, 2.5) # 横軸最小最大
plt.ylim(-2.5, 2.5) # 縦軸最小最大
plt.legend(["orange", "red", "blue", "black"], loc="upper right") # 凡例
plt.show() # グラフの表示
散布図を個別に作り、並べるためにはsubplotを用います。コードの中に、suplot(1,2,x)という記述があります。これは、1行2列の描画スペースを用意し、そのx番目にグラフを描きます、という意味を持ちます。1行2列なので、合計2枚のグラフをかくことが出来ますね。
# リストに、生成したデータを入れます。
x = [Dat01[:,0], Dat02[:,0], Dat03[:,0], Dat04[:,0]]
y = [Dat01[:,1], Dat02[:,1], Dat03[:,1], Dat04[:,1]]
# 描画領域の生成(2枚横に並べたいので、横の長さを広めにとる)
fig = plt.figure(figsize=(12, 4))
# 複数画像を保持するリストを生成
# *** Dat01 ***
plt.subplot(1,2,1)
plt.scatter(x[0], y[0], # 横軸、縦軸の値
s=30, # マーカサイズ
c='orange', # マーカの色(red, blue, pink, yellow, orange, blackなど)
marker='s', #マーカの形(.osなど:下記参照)
alpha=0.8, # 塗りつぶしの透明度(0:完全に透明〜1:透明にしない)
linewidths=0.5, # マーカの線の太さ
edgecolors='black') # マーカの線の太さ(マーカの色と同じ。不要の場合は''なしでNone)
plt.title("Dat01") # タイトル
plt.xlabel("x axis") # 軸名
plt.ylabel("y axis") #軸名
plt.grid(True) #グリッド線(True:引く、False:引かない)
plt.xlim(-2.5, 2.5) # 横軸最小最大
plt.ylim(-2.5, 2.5) # 縦軸最小最大
# *** Dat02 ***
plt.subplot(1,2,2)
plt.scatter(x[1], y[1], # 横軸、縦軸の値
s=30, # マーカサイズ
c='red', # マーカの色(red, blue, pink, yellow, orange, blackなど)
marker='*', #マーカの形(.osなど:下記参照)
alpha=0.8, # 塗りつぶしの透明度(0:完全に透明〜1:透明にしない)
linewidths=0.5, # マーカの線の太さ
edgecolors='black') # マーカの線の太さ(マーカの色と同じ。不要の場合は''なしでNone)
plt.title("Dat02") # タイトル
plt.xlabel("x axis") # 軸名
plt.ylabel("y axis") #軸名
plt.grid(True) #グリッド線(True:引く、False:引かない)
plt.xlim(-2.5, 2.5) # 横軸最小最大
plt.ylim(-2.5, 2.5) # 縦軸最小最大
plt.show()
4枚を並べたい場合には、以下のように描きます。2行2列で4枚を並べたいので、subplot(2, 2, x)とします。
別のグラフ同士が重なってしまう場合が多いので、
fig.subplots_adjust(wspace=0.3, hspace=0.4) # 横のグラフ同士の幅、縦のグラフ同士の幅
で調整します。
# リストに、生成したデータを入れます。
x = [Dat01[:,0], Dat02[:,0], Dat03[:,0], Dat04[:,0]]
y = [Dat01[:,1], Dat02[:,1], Dat03[:,1], Dat04[:,1]]
# 描画領域の生成
fig = plt.figure(figsize=(7, 7))
fig.subplots_adjust(wspace=0.3, hspace=0.4) # 横のグラフ同士の幅、縦のグラフ同士の幅
# *** Dat01 ***
plt.subplot(2,2,1)
plt.scatter(x[0], y[0], # 横軸、縦軸の値
s=30, # マーカサイズ
c='orange', # マーカの色(red, blue, pink, yellow, orange, blackなど)
marker='s', #マーカの形(.osなど:下記参照)
alpha=0.8, # 塗りつぶしの透明度(0:完全に透明〜1:透明にしない)
linewidths=0.5, # マーカの線の太さ
edgecolors='black') # マーカの線の太さ(マーカの色と同じ。不要の場合は''なしでNone)
plt.title("Dat01") # タイトル
plt.xlabel("x axis") # 軸名
plt.ylabel("y axis") #軸名
plt.grid(True) #グリッド線(True:引く、False:引かない)
plt.xlim(-2.5, 2.5) # 横軸最小最大
plt.ylim(-2.5, 2.5) # 縦軸最小最大
# *** Dat02 ***
plt.subplot(2,2,2)
plt.scatter(x[1], y[1], # 横軸、縦軸の値
s=30, # マーカサイズ
c='red', # マーカの色(red, blue, pink, yellow, orange, blackなど)
marker='*', #マーカの形(.osなど:下記参照)
alpha=0.8, # 塗りつぶしの透明度(0:完全に透明〜1:透明にしない)
linewidths=0.5, # マーカの線の太さ
edgecolors='black') # マーカの線の太さ(マーカの色と同じ。不要の場合は''なしでNone)
plt.title("Dat02") # タイトル
plt.xlabel("x axis") # 軸名
plt.ylabel("y axis") #軸名
plt.grid(True) #グリッド線(True:引く、False:引かない)
plt.xlim(-2.5, 2.5) # 横軸最小最大
plt.ylim(-2.5, 2.5) # 縦軸最小最大
# *** Dat03 ***
plt.subplot(2,2,3)
plt.scatter(x[2], y[2], # 横軸、縦軸の値
s=30, # マーカサイズ
c='blue', # マーカの色(red, blue, pink, yellow, orange, blackなど)
marker='^', #マーカの形(.osなど:下記参照)
alpha=0.8, # 塗りつぶしの透明度(0:完全に透明〜1:透明にしない)
linewidths=0.5, # マーカの線の太さ
edgecolors='black') # マーカの線の太さ(マーカの色と同じ。不要の場合は''なしでNone)
plt.title("Dat03") # タイトル
plt.xlabel("x axis") # 軸名
plt.ylabel("y axis") #軸名
plt.grid(True) #グリッド線(True:引く、False:引かない)
plt.xlim(-2.5, 2.5) # 横軸最小最大
plt.ylim(-2.5, 2.5) # 縦軸最小最大
# *** Dat04 ***
plt.subplot(2,2,4)
plt.scatter(x[3], y[3], # 横軸、縦軸の値
s=30, # マーカサイズ
c='black', # マーカの色(red, blue, pink, yellow, orange, blackなど)
marker='o', #マーカの形(.osなど:下記参照)
alpha=0.8, # 塗りつぶしの透明度(0:完全に透明〜1:透明にしない)
linewidths=0.5, # マーカの線の太さ
edgecolors='black') # マーカの線の太さ(マーカの色と同じ。不要の場合は''なしでNone)
plt.title("Dat04") # タイトル
plt.xlabel("x axis") # 軸名
plt.ylabel("y axis") #軸名
plt.grid(True) #グリッド線(True:引く、False:引かない)
plt.xlim(-2.5, 2.5) # 横軸最小最大
plt.ylim(-2.5, 2.5) # 縦軸最小最大
plt.show()
上のグラフは、以下のようにfor文を利用することで、まとめて描くことが出来ます。よくわからない場合は、for文とリストを復習してから解読してみてください。
# リストに、生成したデータを入れます。
x = [Dat01[:,0], Dat02[:,0], Dat03[:,0], Dat04[:,0]]
y = [Dat01[:,1], Dat02[:,1], Dat03[:,1], Dat04[:,1]]
col=["orange", "red", "blue", "black"]
figtitle=["Dat01", "Dat02", "Dat03", "Dat04"]
# 描画領域の生成
fig = plt.figure(figsize=(7, 7))
fig.subplots_adjust(wspace=0.3, hspace=0.4) # 横のグラフ同士の幅、縦のグラフ同士の幅
# for文を利用して、4つのグラフを描画
for i in range(0, len(x)):
plt.subplot(2,2,i+1)
plt.scatter(x[i], y[i], # 横軸、縦軸の値
s=30, # マーカサイズ
c=col[i], # マーカの色(red, blue, pink, yellow, orange, blackなど)
marker='s', #マーカの形(.osなど:下記参照)
alpha=0.8, # 塗りつぶしの透明度(0:完全に透明〜1:透明にしない)
linewidths=0.5, # マーカの線の太さ
edgecolors='black') # マーカの線の太さ(マーカの色と同じ。不要の場合は''なしでNone)
plt.title(figtitle[i]) # タイトル
plt.xlabel("x axis") # 軸名
plt.ylabel("y axis") #軸名
plt.grid(True) #グリッド線(True:引く、False:引かない)
plt.xlim(-2.5, 2.5) # 横軸最小最大
plt.ylim(-2.5, 2.5) # 縦軸最小最大
plt.show()
分析しているとき、条件によってマーカの色を変えたいときがかなりよくあります。このテクニックについて説明します。まず、以下のデータを見てください。
plt.figure(figsize=(5, 4)) # figureの縦横の大きさ
plt.scatter(Dat01[:,0], Dat01[:,1], s=30, c='orange', marker='s')
plt.grid(True) #グリッド線(True:引く、False:引かない)
plt.xlim(0, 2) # 横軸最小最大
plt.ylim(0, 2) # 縦軸最小最大
plt.show() # グラフの表示
横軸が1.00以上のものだけ青にしてみたいとします。以下のコードを実行して見てください。Dat01の0列目のデータの中から、1を超える部分だけ、Trueが返されます。
print(Dat01[:,0] > 1)
なので、Dat01[Dat01[:,0] > 1, 0]と指定すると、Dat01の0列目の、1以上のデータのみが対象となります。
print(Dat01[Dat01[:,0]>1,0])
このように、Dat01の0列目の、1以上のデータだけが抜き出されています。これを応用すると、以下のように条件を満たしているときだけ色を変える、ということも容易に行えます。ちょっと複雑ですが、気合いを出して解読して見ましょう!
plt.figure(figsize=(5, 4)) # figureの縦横の大きさ
# 横軸の値(0列目)が0未満のデータのみを散布図として描画
plt.scatter(Dat01[Dat01[:,0] < 1, 0], Dat01[Dat01[:,0] < 1, 1], s=30, c='orange', marker='s')
plt.grid(True)
plt.xlim(0, 2)
plt.ylim(0, 2)
# 横軸の値(0列目)が0以上のデータのみを散布図として描画
plt.scatter(Dat01[Dat01[:,0] >= 1, 0], Dat01[Dat01[:,0] >= 1, 1], s=30, c='blue', marker='s')
plt.grid(True)
plt.xlim(0, 2)
plt.ylim(0, 2)
plt.show() # グラフの表示
Aさんは、どういう人が試験で高い点数を取れるのか調べてみることにしました。仮説として、授業に出た回数と、試験前の勉強時間が重要だと考え、以下のデータを集めました。(架空のデータです)
# リストで定義(本当はcsvでデータを保存しておき、それをロードしますが。。。)
X1 = [3, 1, 2, 5, 3, 9, 8, 7, 4, 3, 9, 6, 9, 8, 9, 1, 1, 2, 6, 6, 8]
X2 = [7, 1, 1, 3, 4, 1, 2, 9, 2, 1, 3, 5, 9, 5, 1, 7, 8, 5, 7, 1, 1]
Y = [68, 23, 29, 58, 56, 52, 54, 89, 21, 32, 63, 73, 98, 73, 43, 45, 62, 63, 49, 35, 65]
# ndarray型にキャスト
import numpy as np
X1 = np.array(X1)
X2 = np.array(X2)
Y = np.array(Y)
データだけを見ても、よくわかりません。傾向を掴むために、60点未満を赤、60点以上を青にして、散布図を描いて見ます。
plt.figure(figsize=(5, 4))
# 60点未満のプロット
plt.scatter(X1[Y<60], X2[Y<60], c="red", marker="o")
plt.grid(True)
plt.xlim(0, 10)
plt.ylim(0, 10)
plt.xlabel("Number of Attending Lectute")
plt.ylabel("Studing Time")
# 60点未満のプロット
plt.scatter(X1[Y>=60], X2[Y>=60], c="blue", marker="s")
plt.grid(True)
plt.xlim(0, 10)
plt.ylim(0, 10)
plt.xlabel("Number of Attending Lectute")
plt.ylabel("Studing Time")
plt.legend(["less than 60", "over 60"], loc="upper right", bbox_to_anchor=(1.5, 1))
plt.show()
データの羅列を見るだけではよくわかりませんでしたが、7回以上授業に出席した方が良い、5時間以上は勉強した方が良いなどのことがわかりました。このように、散布図はシンプルな分析手法ですが、割と強力なので良く使います。
別の方法として、scatterの引数のcにYを入れ、cmapに色合いを指定する方法があります。濃度が試験得点を表すわけです。先ほどとは異なり少し見にくいですが、情報量は多くなります。
plt.figure(figsize=(5, 4))
plt.scatter(X1, X2, c=Y, cmap="Blues", marker="o")
plt.grid(True)
plt.xlim(0, 10)
plt.ylim(0, 10)
plt.xlabel("Number of Attending Lectute")
plt.ylabel("Studing Time")
plt.colorbar()
作成した画像を保存するには、plt.show()を使わずに、以下のように書けばokです。
plt.savefig('figure.png')
plt.savefig('figure.pdf')
別の表し方として、以下のように書くことで、3次元の散布図を描くことができます。ただし、傾向を読み取るのが難しくなるので、(立体的でかっこいいので、なんか分析してるっぽい感じはしますが)あまりおすすめしません。
from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(7, 5))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(X1, X2, Y)
ax.set_xlabel("Number of Attending Lectute")
ax.set_ylabel("Studing Time")
ax.set_zlabel("Academic Score")
ax.set_title("3D plot")
plt.show()