Pythonでグラフを描こう ― 棒グラフ/ヒストグラム/散布図/ヒートマップ:数学×Pythonプログラミング入門(3/3 ページ)
「モデルとデータの可視化」というテーマで各種グラフの描画方法を前後編で解説。後編である今回は、棒グラフ/ヒストグラム/箱ひげ図/散布図/ヒートマップを作成し、複数のグラフを並べて表示する方法を説明する。
練習問題
練習問題については、プログラムの作成から実行までの流れが分かるように、動画を用意してあります。全体像と重要なポイントを把握するのに役立つのでぜひご覧ください(解答例のコードを1行ずつ細かく解説するのではなく、ポイントを押さえたものにしてあります)。
動画4 練習問題の実行例〜3D散布図と個別の2D散布図、回帰直線の表示
(1)3D散布図と個別の2D散布図を並べて描画する
英語、数学、国語の成績が以下のようなリストで表されているものとします。
english = [98, 77, 64, 45, 58, 62, 89, 30]
mathmatics = [88, 54, 72, 85, 70, 81, 63, 27]
language = [87, 84, 61, 46, 66, 68, 78, 33]
次の実行例(図26)に示すようなグラフを描くプログラムを作ってみてください。関数にしなくても構いません。
(ヒント) 今回の内容を組み合わせるだけでできるので、ノーヒントとします。
(2)回帰分析を行い、散布図に回帰直線を重ねて描画する
表2のような形式の物件データのファイル(CSV形式、UTF-8 BOMなし)が、https://raw.githubusercontent.com/Gessys/math/main/data/estate.csvに置いてあります。このデータを基に散布図を作るとともに、面積を独立変数、家賃を説明変数とした単回帰分析を行い、回帰直線を描いてみてください。単回帰分析とは、データを基に、それらのできるだけ近くを通る直線の方程式(y=b+ax)を求めるというものです。ただし、単回帰分析はこれまでの内容だけではできないので、既に作られたコードを利用するものとします(ヒントを参照してそのまま入力してください)。
| No. | 駅歩 | 築 | 階 | 間取り | 面積 | 家賃 |
|---|---|---|---|---|---|---|
| 1 | 7 | 19 | 2 | 2LDK | 38.35 | 14.9 |
| 2 | 3 | 22 | 2 | 1K | 22.85 | 7.4 |
| 3 | 3 | 22 | 4 | 1K | 21.96 | 8 |
| : | : | : | : | : | : | : |
ある程度、実際の物件に近い値にしてあるが、架空のデータ。項目見出しが1行あり、その下にデータが50件記録されている。
グラフは図27のように描画されます。
(ヒント) 物件データを取得し、回帰分析により係数aと定数項bの値を求めるところまではリスト35の通りです。今回は詳しく説明しませんが、このまま入力し、関数regressionの引数に面積と家賃のリストを指定すればaとbの値が返されます。WebサイトからCSVファイルを取得し、pandasのデータフレームとして返すpd.read_csv関数はリスト23で見たものを使います。というわけで、リスト35の中にある関数linearの内容と、散布図と回帰直線を描くコードを書いてください。
import numpy as np
import pandas as pd
from sklearn.linear_model import LinearRegression # 回帰分析のために必要
import matplotlib.pyplot as plt
# 単回帰分析を行い、係数と定数項を返す関数(このまま入力すればよい)
def regression(x, y):
model = LinearRegression() # 回帰分析(ここでは単回帰分析)を行う
xdf = pd.DataFrame(x) # データフレームを作成する
ydf = pd.DataFrame(y) # データフレームを作成する
model.fit(xdf, ydf)
return model.coef_[0][0], model.intercept_[0] # 係数と定数項を返す
def linear(x, a, b):
# この関数の内容を書いてください(簡単)
# 物件データから、面積と家賃を取り出す
url = 'https://raw.githubusercontent.com/Gessys/math/main/data/estate.csv'
data = pd.read_csv(url) # リスト23でも使ったpd.read_csv関数を使う
area = data['面積'] # 面積の値を取得(pandasのSeries)
price = data['家賃'] # 家賃の値を取得(pandasのSeries)
# 単回帰分析により、係数aと定数項bを求める
a, b = regression(area, price)
print(a, b) # グラフの描画には必要ないので後で消しておくとよい
# 出力例:0.2576662166166691 1.138186363488293
# 指定した関数funcを基に、xminからxmaxまで、step刻みでデータを作る(前回作成したもの)
def makedata(func, xmin, xmax, step, **args):
x = np.arange(xmin, xmax, step)
y = func(x, **args)
return x, y
# この後に、散布図と回帰直線を描くコードを書いてください
回帰分析を行って、回帰式の係数aと定数項bを求めるコードは既に書かれている。また、データを取得するコードも既に書かれている。やるべきことは、回帰式の方程式を定義することと、散布図と回帰直線のグラフを描くことの2つ。
まず、回帰式を表す関数linearを定義しましょう。引数にはx、係数a、定数項bを与えます。xを基にyの値を返すようにしてください。これは中学で学んだ一次関数の式を作るだけなので簡単ですね。
散布図に関してはareaとpriceをプロットするだけでできます。
回帰直線を描くには前回の内容を少し思い出す必要があります。関数のグラフを描くので、plot関数を使って折れ線グラフを作成すればいいですね。xの値をareaの最小値から最大値まで0.1刻みで変えながら、回帰直線の式に当てはめたyの値を求め、それらの値をプロットすることになります。最小値は組み込み関数のmaxで、最大値は組み込み関数のminで求められます。xとyの値を作るには、前回作成した関数makedataが使えます(そのコードも含めておきました)。なお、plot関数にlinestyle='dotted'を指定すれば、折れ線グラフが点線で描画できます。
練習問題の解答例
以下、解答とプログラムの作成例です。もちろん、異なるやり方もあるので、これらが唯一の答えというわけではありません。
(1)3D散布図と個別の2D散布図を並べて描画する例
subplot関数を使って4つの描画領域を作ります。最初の描画領域だけ3Dにすればいいですね。グラフが4つだと個々のグラフが小さくなるので、全体のサイズを幅12、高さ8にしてあります(単位はインチでしたね)。繰り返し処理で表すこともできなくはないですが、素直に一つずつ記述した方が手っ取り早いでしょう。
import matplotlib.pyplot as plt
english = [98, 77, 64, 45, 58, 62, 89, 30]
mathmatics = [88, 54, 72, 85, 70, 81, 63, 27]
language = [87, 84, 61, 46, 66, 68, 78, 33]
plt.figure(figsize=[12,8])
ax1 = plt.subplot(2,2,1, projection='3d') # 最初のだけ3D
ax1.scatter(english, mathmatics, language)
ax1.set_xlabel('English')
ax1.set_ylabel('Math')
ax1.set_zlabel('Language')
ax2 = plt.subplot(2,2,2)
ax2.scatter(english, mathmatics)
ax2.set_xlabel('English')
ax2.set_ylabel('Math')
ax3 = plt.subplot(2,2,3)
ax3.scatter(mathmatics,language)
ax3.set_xlabel('Math')
ax3.set_ylabel('Language')
ax4 = plt.subplot(2,2,4)
ax4.scatter(language,english)
ax4.set_xlabel('Language')
ax4.set_ylabel('English')
(2)回帰分析を行い、散布図に回帰直線を重ねて描画する例
回帰分析のためのコードが長かったので、難しそうな印象を持たれたかも知れませんが、入力すべきコードは、前回と今回のおさらいレベルの簡単なものです。
単回帰分析の回帰式は一次関数なので、簡単に書けます。リスト37の通りです。
def linear(x, a, b):
return b + a*x
あとは、回帰直線のためのデータを作成して、プロットするだけです。リスト25の続きにリスト38のコードを書けば完成です。
# 回帰直線のためのデータを作成する
xmin = min(area) # 面積の最小値
xmax = max(area) # 面積の最大値
args = {'a': a, 'b': b}
x, y = makedata(linear, xmin, xmax, 0.1, **args)
# 散布図と回帰直線を描画する
plt.scatter(area, price)
plt.plot(x, y, linestyle='dotted')
今回は、ビジュアライズ(可視化)というテーマの後半として、収集したデータや分析結果を棒グラフやヒストグラム、散布図などで表し、データの特徴を可視化する方法を紹介しました。
次回は、数式の取り扱いに戻って、微分法に関するプログラミングを見ていこうと思います。内容としては微分法の簡単な数値計算法を出発点として、ニュートン法により方程式の解を求める方法、ルンゲ・クッタ法による微分方程式の数値計算などについて紹介します。
Copyright© Digital Advantage Corp. All Rights Reserved.

