Open In Colab

4. ライブラリ/パッケージ/モジュールとデータの可視化(Matplotlib)#

Pythonでは(他のプログラミング言語と同様)特定の作業がパッケージ化されたプログラム群が用意されていてこれらをライブラリ/パッケージ/モジュールなどと呼ぶ。 モジュールはPythonのコードをまとめた単位で、典型的には一つの .py ファイルに対応する。パッケージはモジュールなどを階層的にまとめたもの、ライブラリは再利用できる機能の集まりを広く指す呼び名である。この授業でも、文脈に応じて呼び方が混在している。

Pythonのライブラリ/モジュールの多くはGitHub上で開発・公開されていて、簡単にインストールしたりインポートして使うことができる。 データ分析, AI・機械学習, エクセル等の操作, Webスクレイピングなど、非常に多岐にわたるライブラリが存在する。 こうしたライブラリの充実も、Pythonを使う大きな利点の一つである。

4.1. ライブラリのインポート(import)#

幾つかのライブラリ/モジュールは標準で組み込まれているため、特段インストール作業をすることなく、以下のように簡単にインポートして使うことができる。

たとえばmathという名前のモジュールをインポートする際には

import math

とする。カンタン。

このmathモジュールはPythonの標準ライブラリの一つで、数学関数を提供するモジュールである。

上のコードを実行しmathモジュールを一度importしてやれば、以降のコードで、

  • 円周率\(\pi\): pi

  • 自然対数: log

  • 常用対数: log10

  • 指数関数: exp

  • 三角関数: sin,cos

などを使うことができる。

モジュール内に用意されている定数や関数を利用するときは通常、モジュール名.定数やモジュール名.関数(引数)といった形で使う。

print(math.pi)  # 円周率pi
print(math.e)  # ネイピア数e
print(math.log(2.0))  # 自然対数
print(math.log10(2.0))  # 常用(底が10)対数
print(math.exp(2.0))  # 指数関数
print(math.sin(math.pi))  # sin(pi)
3.141592653589793
2.718281828459045
0.6931471805599453
0.3010299956639812
7.38905609893065
1.2246467991473532e-16

注:\(sin(\pi)\)は本来0だが、1章で述べたように実数が有限の精度なので、\(\pi\)の計算機上での数値が厳密には円周率と異なるため、\(sin(\pi)\)の値も僅かに0からズレることになる。

4.2. ライブラリのインストール#

Google Colaboratory環境では、Pythonの標準ライブラリ以外のライブラリを、pipコマンドを用いてインストールすることができる.

コードセルで以下のようにすれば良い:

%pip install package_name

ただし、Google Colaboratory環境では、よく使われるライブラリは標準でインストールされているので、
特殊なライブラリや特定のバージョンを使用したいといった状況でなければ、別途インストールする必要はない。
また、ユーザーが別途インストールしたライブラリは、そのセッションが終了すると消えてしまうので、
時間を空けて作業を再開する場合などは、新しいランタイムでは再びインストールが必要になることがある。

ローカルのPython環境におけるライブラリのインストールなどについては、

などを参照。

4.3. NumPy#

データ分析などで非常によく使われるNumPyというライブラリがある。
NumPyはおもにベクトルや行列の演算などを高速に行うことが可能という利点があり、データ分析においては必須のライブラリと言っても過言ではない。

ndarrayと呼ばれるNumPy独自の配列を用いることで、ベクトルや行列の演算を高速に行うことができたり、グラフの描画に配列を使う際にも便利な機能が用意されている。 簡単な作業ならリストでも代用できるので必須ではないが、コードを大幅に簡略化することもできるため、今後ノートブックでも適宜NumPyが用いられる。

NumPyの詳細についてはこちらのノートブックを参照。

NumPyにも math と同じ名前の関数があり、上で行った操作を次のように書ける。ただし、引数や返り値が常に同じとは限らない:

import numpy as np  # numpyをnpという名前で使う

print(np.log(2.0))
print(np.log10(2.0))
print(np.exp(2.0))
print(np.pi)
print(np.sin(np.pi))
0.6931471805599453
0.3010299956639812
7.38905609893065
3.141592653589793
1.2246467991473532e-16

また、以下でやるように、数値を要素に持つリストを使って演算やグラフを描画するときは、データのリストなどをndarray型に変換して使う事も多い。

リストをndarray型に変換するには、numpyのarray関数を用いればよい。

import numpy as np

list_a = [1.23, 9341.22, -32.33]
ndarray_a = np.array(list_a)
print(ndarray_a, type(ndarray_a))
[ 1.23000e+00  9.34122e+03 -3.23300e+01] <class 'numpy.ndarray'>

グラフの描画で便利な理由は以下のような人単位のデータを持つ入れ子のリストがあったときに、成分の転置を取ってx軸方向のデータ, y軸方向のデータに整形が容易となる。

# 身長体重のデータ
data = [[180, 70], [175, 65], [160, 58], [170, 60]]
print(data)
# データをndarrayに変換
data = np.array(data)

# 転置を行うメソッドを適用することで、0行目が身長、1行目が体重と整形できる
data = data.T
x = data[0]
y = data[1]

print(data)
print("x", x)
print("y", y)
[[180, 70], [175, 65], [160, 58], [170, 60]]
[[180 175 160 170]
 [ 70  65  58  60]]
x [180 175 160 170]
y [70 65 58 60]

なお、numpyのndarrayをprintすると上のようにデータを区切るカンマを省略したり、データの数が多いときは省略して表示してくれる。 これは、print関数がndarray型のデータを表示する際に、専用の表示方法を用いているためである。

4.4. Matplotlibを用いた作図#

次に、Matplotlibと呼ばれるライブラリを使って、各種のグラフを作成する方法を見ていこう.

Matplotlibは様々なグラフが描ける一方で少々テクニカルな部分が多いので細かい部分は分からなくても心配は不要である。 「こういうおまじないを唱える(書くと)こうなる」というざっくりとした理解でまずはOKなのでどんどん触りながら、少しずつ、グラフの詳細を調整する方法をマスターしていけば良い。 初めて作る料理についてはレシピを見ながら、2回目以降は少しアレンジを加えて、より自分好みの料理にしていくようなイメージが近いかもしれない。

Pythonのライブラリの細かな使い方を調べる時、真っ先に思いつくのがググることになるかと思う。 最近だと日本語で書かれた情報に気軽にアクセスできるのは良いことだが、不正確な記述が含まれていてかえって理解を遠ざける危険性もある。なにか困ったときには、まず大元のライブラリの公式ドキュメントを確認しよう。使える引数や返り値、使用例を確かめる基本の資料になる。ページ内にあれこれと広告が貼り付けてあるようなブログ記事を見て、不正確な情報に振り回されたり不快な思いをするくらいなら、公式ドキュメントを参照しよう.

Matplotlibの公式ドキュメントは例えばこちら

はじめは授業資料にあるコードなどを少しずつ流用し、自分の目的のためにどうすれば良いか類推しながら改良していって、自分の描きたいグラフに近づけていくのが良い。(私もよく過去の自分が作成したコードを流用して作図している。) 慣れてくるといろんな図を作ったり、細かいところにこだわったりしたくなる。 そんなときは以下のチートシートが役に立つかもしれない。 matplotlib/cheatsheets

あるいは、最近だとChatGPTやGeminiなどのAIに「二次元配列をプロットするPythonコードを書いてください」「さっきのコードをさらに拡張して、棒グラフにハッチをつけてください」などと聞いてみても良いかも.
もちろん、コードを貼り付けるだけで個々の部品に関する理解を放棄しているといつまでたっても有効なプログラムを自分で書けるようにはならず、望むコードが生成されるまでAIに質問をし続けたり、誤りに気が付かずに間違った図を世に出す、という皮肉な状況に陥る恐れがある。その辺りのバランスを取りながら学習を進めよう。

4.4.1. Matplotlibのインポートと使い方#

まず、以下のコードを実行して、matplotlib内のpyplotモジュールをインポートしよう.
matplotlib.pyplotだと名前が長いのでpltという名前で使えるようにimport XXX as YY などとする.

import matplotlib.pyplot as plt
from matplotlib import pyplot as plt  # でも同じ

パッケージには、たとえば以下のような階層構造がある。

package_a/
├── __init__.py
├── module1.py
└── subpackage/
    ├── __init__.py
    └── module2.py

下位のモジュールは package_a.module1 のようにピリオドで指定する。上の matplotlib.pyplot もその一例である。

4.4.2. 日本語を表示するための準備#

Matplotlibでは、使用するフォントに日本語の文字がないと、ラベルが四角などで表示される。その対策の一つが japanize-matplotlib である。

次のセルで、インストールとインポートをまとめて行う。Colabで新しいランタイムを使うときも、このセルから準備しよう。

%pip -q install japanize-matplotlib

from matplotlib import pyplot as plt
import japanize_matplotlib
Note: you may need to restart the kernel to use updated packages.

インストール時の名前は japanize-matplotlib、インポート時の名前は japanize_matplotlib である。これはこのライブラリでの対応で、すべてのライブラリでハイフンを置き換えればよいわけではない。

Pythonでグラフを作る際の基本は、データ(描画したいもの)が入った配列を作ることになる.

以下では、リスト-likeなデータ(例えばrangeやndarrayなど)を使って、グラフを描画する方法を見ていく. 毎回リスト-likeと書くのは面倒なので、以降はリスト-likeなデータを単にリストと呼ぶことにするが、 必ずしも描画につかうデータはリストに限らず、リストと互換性のあるndarrayなど、一般の配列も使えることに注意.

プログラムでグラフを描くのは、人間が手で絵やグラフを描く工程とは少し異なる. 線や棒、いろんな形のシンボルを描いたりして、どんどんグラフを構成する要素を足しながら、それらの色や線種、透過度や太さ,背景色などを変えつつ徐々に望むようなグラフにしていく作業になる. 場合によっては、どの要素を前面に配置するかといったレイヤーの意識も必要になる.

以下では代表的なグラフを例に、Matplotlibを使った作画を試してみよう.

4.4.3. 棒グラフ#

Aさんの共通テスト?の得点をリストとして定義してみよう 順番(各科目の名前(ラベル))は、国語,英語,数IA,数IIB,化学,物理,世界史,情報として...

data = [152, 170, 82, 85, 79, 92, 88, 100]
label = ["国語", "英語(R+L)", "数IA", "数IIB", "化学", "物理", "世界史", "情報"]
total = sum(data)
print("合計得点は", total, "/1000 点で、得点率は" + str("%6.1f" % (100 * total / 1000)) + "%です")
合計得点は 848 /1000 点で、得点率は  84.8%です

Aさん優秀。これを棒グラフにでもしてみよう。

plt.figure(figsize=(10, 2))
plt.bar(label, data, align="center", width=0.5, color="red")
plt.xlabel("各科目")
plt.ylabel("Aさんの得点")
plt.show()
plt.close()
../_images/1fcd6c7655a697ea8a1b4586606a8fc8bbac3a7b5735c926637ea6121ef44d53.png
  • 1行目: plt.figure(figsize=(10,2))

    上でmatplotlibモジュール内のpyplotというモジュールをpltという名前でインポートしたのでplt.figureというのはpyplot内のfigureという関数を使うことを意味する。その役割は、図を描くキャンバスを用意しているようなイメージ。
    ここではfigsize=(10,2)という引数を指定した(指定しなければ自動で図のサイズが決まる).
    figsize=(横,縦)で大きさが指定できるので、figsizeを変えて試してみよう

  • 2行目: plt.bar(label,data,align='center',width=0.5,color="red")

    pyplot内のbarという関数(棒グラフを描く関数)を呼んでいる。1つめの引数はx軸上の値で、2つめはy軸に対応する値
    x軸用のリストが数値以外のときは整数値を割り当ててプロットしてくれる(7個データがあれば、x=0,1,...,6に割り当てられる)。

  • 3行目: plt.xlabel("各科目"); plt.ylabel("Aさんの得点")

    ここではx軸とy軸のデータの種類(ラベル/labelと呼ぶ)を指定している。

  • 4行目: plt.show()

    それまでに指定した条件で絵を描いて表示する

  • 5行目: plt.close()

    キャンバスを閉じる。とくに一つのプログラムで複数絵を描くときはこれを書く必要がある。 (closeしないと、どこまでがどのグラフのための指示かわからず意図しない絵になることがあります)

ライブラリを使用する際には、見慣れない関数がたくさん出てくるので、その全てについて今の段階でオプションの指定の仕方を覚える必要はない. とりあえず、既に指定されているオプションのいくつかを変更してみよう。

その際、colorやwidth, alignなどから「widthは数値だから増減するとどうなるかな?」「align="center"がいけるならleftとかrightもあるか?」「こう変えるとこうなるんじゃ...?」と類推しながらやってみよう。

練習

いくつかの得点や、棒グラフの色・幅を変えてプロットしてみよう。
例えばcolorの場合、一般的な色の名前を指定するか、カラーコード(真っ黒="#000000"など)やRGBの値(0~1の値を3つ並べたもの,例->(0.2,0.5,1))を指定することで色を変更できる。
※ align に指定できるのは "center" または "edge"。類推したら、実行結果や公式ドキュメントで確かめよう。日本語が表示されない場合は、上のインストールとインポートを確認しよう。


4.4.4. plot: 線の描画#

説明変数\(x\)と目的変数\(y\)があって、とくに \(x\)に対する\(y\)の振る舞い に興味がある場合にはplotを使う。

例として、以下に日本の一人当たりGDP($, 購買力平価・インフレ調整済)の推定値をリストとして与えた。 これを線グラフにしてみよう。

この系列は教材に保存された1800〜2040年の推計値で、将来の推計も含む。現在までの実績だけを示すグラフではないことに注意しよう。

x = [
    1800, 1801, 1802, 1803, 1804, 1805, 1806, 1807, 1808, 1809,
    1810, 1811, 1812, 1813, 1814, 1815, 1816, 1817, 1818, 1819,
    1820, 1821, 1822, 1823, 1824, 1825, 1826, 1827, 1828, 1829,
    1830, 1831, 1832, 1833, 1834, 1835, 1836, 1837, 1838, 1839,
    1840, 1841, 1842, 1843, 1844, 1845, 1846, 1847, 1848, 1849,
    1850, 1851, 1852, 1853, 1854, 1855, 1856, 1857, 1858, 1859,
    1860, 1861, 1862, 1863, 1864, 1865, 1866, 1867, 1868, 1869,
    1870, 1871, 1872, 1873, 1874, 1875, 1876, 1877, 1878, 1879,
    1880, 1881, 1882, 1883, 1884, 1885, 1886, 1887, 1888, 1889,
    1890, 1891, 1892, 1893, 1894, 1895, 1896, 1897, 1898, 1899,
    1900, 1901, 1902, 1903, 1904, 1905, 1906, 1907, 1908, 1909,
    1910, 1911, 1912, 1913, 1914, 1915, 1916, 1917, 1918, 1919,
    1920, 1921, 1922, 1923, 1924, 1925, 1926, 1927, 1928, 1929,
    1930, 1931, 1932, 1933, 1934, 1935, 1936, 1937, 1938, 1939,
    1940, 1941, 1942, 1943, 1944, 1945, 1946, 1947, 1948, 1949,
    1950, 1951, 1952, 1953, 1954, 1955, 1956, 1957, 1958, 1959,
    1960, 1961, 1962, 1963, 1964, 1965, 1966, 1967, 1968, 1969,
    1970, 1971, 1972, 1973, 1974, 1975, 1976, 1977, 1978, 1979,
    1980, 1981, 1982, 1983, 1984, 1985, 1986, 1987, 1988, 1989,
    1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
    2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,
    2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
    2020, 2021, 2022, 2023, 2024, 2025, 2026, 2027, 2028, 2029,
    2030, 2031, 2032, 2033, 2034, 2035, 2036, 2037, 2038, 2039,
    2040,
]
y = [
    1050, 1050, 1050, 1050, 1060, 1060, 1060, 1060, 1060, 1060,
    1060, 1070, 1070, 1070, 1070, 1070, 1070, 1070, 1080, 1080,
    1080, 1080, 1080, 1080, 1090, 1090, 1090, 1090, 1090, 1090,
    1090, 1100, 1100, 1100, 1100, 1100, 1100, 1100, 1110, 1110,
    1110, 1110, 1110, 1110, 1120, 1120, 1120, 1120, 1120, 1120,
    1130, 1130, 1130, 1140, 1140, 1150, 1150, 1150, 1160, 1160,
    1170, 1170, 1180, 1180, 1190, 1190, 1190, 1200, 1200, 1210,
    1210, 1220, 1220, 1230, 1230, 1320, 1280, 1300, 1290, 1350,
    1390, 1340, 1360, 1350, 1340, 1380, 1460, 1520, 1430, 1480,
    1610, 1520, 1600, 1590, 1760, 1770, 1650, 1660, 1950, 1790,
    1840, 1880, 1750, 1850, 1840, 1790, 2000, 2040, 2030, 2000,
    2000, 2070, 2100, 2100, 2000, 2150, 2440, 2480, 2480, 2700,
    2500, 2720, 2670, 2630, 2650, 2710, 2680, 2660, 2830, 2860,
    2600, 2570, 2740, 2950, 2900, 2920, 3090, 3180, 3350, 3850,
    3920, 3910, 3830, 3830, 3600, 1820, 1950, 2080, 2320, 2420,
    2580, 2760, 3060, 3210, 3330, 3520, 3700, 3900, 4060, 4360,
    4840, 5370, 5790, 6220, 6870, 7190, 7880, 8630, 9640, 10800,
    14500, 15000, 16100, 17100, 16700, 17000, 17500, 18100, 19000, 19800,
    20300, 21000, 21500, 22000, 22900, 24200, 24800, 25700, 27500, 28900,
    30400, 31400, 31500, 31500, 31700, 32400, 33300, 33600, 33200, 33000,
    33900, 33900, 33900, 34300, 35100, 35700, 36100, 36700, 36300, 34300,
    35800, 35800, 36400, 37100, 37300, 37800, 38200, 38600, 39100, 39400,
    39800, 40300, 40800, 41400, 42100, 42900, 43700, 44600, 45600, 46500,
    47600, 48600, 49700, 50800, 51900, 53100, 54300, 55500, 56700, 57900,
    59200,
]

plot関数は多数の引数を受け取ることができる。

まずは最小の引数であるyだけを指定してみよう。

fig = plt.figure(figsize=(12, 4))
plt.plot(y, color="blue")
plt.show()
../_images/9c7c02e992cbc0ef09eb1b11273f18744724bd8c96b107c89389239c92459b99.png

xを省略すると、0から始まる整数値が自動的に割り当てられる。 したがって、あるデータを起点に経過日数などで表す場合は、xを省略しても良い。 より一般の場合は、xを指定してやると良い。

fig = plt.figure(figsize=(12, 4))
plt.plot(x, y, color="red", linewidth=1, label="Japan")
plt.show()
../_images/913f81b157e6a52fee018918a80543e31b78d65a7c0effd650cc92103b9adf48.png

カラーコードで色を指定、x軸ラベル, y軸ラベル, legend(判例), y軸のスケールをlogにするなど、 より複雑なオプションを指定してみよう.

fig = plt.figure(figsize=(12, 4))
plt.plot(x, y, color="#006036", linewidth=1, label="Japan")
plt.xlabel("年")  # x軸のラベル
plt.ylabel("GDP[$]")  # y軸のラベル
plt.yscale("log")  # y軸を対数スケールにする
plt.legend(loc="upper left")  # 凡例の位置を指定して表示
plt.show()
../_images/fa64e0ec839620deea0c21e8eb4b0a8c879555aabb029598db539524133d5e59.png

当然だが、x軸とy軸方向でデータの数が合っていないとエラーとなる.
「一緒にしているつもりなのにエラーが出る...」と言う場合は、len関数を使うなどして、リストの長さ/要素の数をチェックしてみよう。 カンマがピリオドになっていて数がずれる、といったことがよくある。

例:
(意図したリスト) [2,3,5] ←長さ3のリスト
(間違えて作ったリスト) [2.3, 5] ←カンマがピリオドになっていて、長さ2のリストになっている.

上記のようなミスを防ぐには、値を入力してカンマを打ったあと半角スペースを開けるようにすると分かりやすい, [2,3,5]→[2, 3, 5].

カンマの後ろにスペースを入れることは文法上の必要条件ではないが、コードの可読性を上げるために推奨される書き方である. 英文などでも基本となるため、癖づけておくと良い.

凡例について

上でも少し凡例について触れたが、barやplot、以下でやるscatterなどそれぞれのグラフを構成するオブジェクトに対して、labelという引数を指定することで凡例を付けることができる.

とくに複数のデータをまとめてプロットするときは、どのデータがどの線や棒に対応するのか分からなくなってしまうことがあるので、凡例をつけることが重要になる。用意した凡例はplt.legend()で有効化することができる.

凡例を設定することは、図の可読性を向上させるための重要な要素である一方で、 同じような色や形の凡例が多すぎると、かえって可読性を下げてしまうこともある。 例えば、散布図で一点ごとに描画してlabelをつけてしまうと、データの数だけ凡例ができてしまいとても不格好なグラフになってしまう。

最小限の数の凡例をつけるようデータを整形したり、凡例の一部をannotationにしたり、 図の横側に凡例を置いたりなど工夫が必要になることも多い。

4.4.5. scatter: 散布図の描画#

\(x\)と\(y\)、2つの量があって、どちらにも興味がある、
あるいは両者の間の相関に興味がある場合、散布図を描くと、見通しやすくなることが多い。

以下では、2017年の宇都宮の平均気温とアイスクリームの支出金額の相関を見てみよう。
気温・アイスクリームの支出金額ともに、1月から12月に順番にリストに入れていくことにする。

※実際のデータ分析の場合は、手でデータを入力してリストを作るのは面倒な上、人為的なミスが入り込む可能性が高いので、CSVファイルなどからデータを読み込むべきである。そうすると、ミスがあってもデータを作成した人のせいにできる、というより責任やミスの所在を明確にできる。

x = [3.1, 4.3, 6.6, 13.2, 19.1, 20.9, 26.4, 25.1, 21.9, 15.7, 9.6, 3.8]
y = [568, 572, 804, 833, 930, 965, 1213, 1120, 835, 540, 451, 502]

plt.figure(figsize=(4, 4))
plt.title("宇都宮市")  ## 図にはタイトルをつけることができます
plt.xlabel("平均気温 (℃)")  # 軸ラベルの指定
plt.ylabel("世帯あたりのアイスクリーム・シャーベットの消費金額 (円)")
plt.scatter(x, y)
plt.show()
plt.close()
../_images/2976f443fa00528c26ca14e9922999555c79280d64edc877d504b7ed09ebc676.png

相関係数などの情報を含んだもう少し凝った図を作ってみよう:

x = [3.1, 4.3, 6.6, 13.2, 19.1, 20.9, 26.4, 25.1, 21.9, 15.7, 9.6, 3.8]
y = [568, 572, 804, 833, 930, 965, 1213, 1120, 835, 540, 451, 502]

# Numpyを使ってx,yの配列間の相関行列を計算. 詳細は相関分析の際に.
r = np.corrcoef(x, y)
corrcoef = r[0, 1]  # 相関行列rの(0,1)成分を取り出す


# 季節ごとに適当に色を塗るために、月を入力すると色を返す関数を定義
def seasoncolor(month):
    if 1 <= month <= 2 or month == 12:
        return "blue"
    elif 3 <= month <= 5:
        return "green"
    elif 6 <= month <= 8:
        return "red"
    elif 9 <= month <= 11:
        return "orange"
    else:
        print("month", month, " is not supported")


# 図の描画部分
fig = plt.figure(figsize=(5, 5))
ax = fig.add_subplot(111)  # fig.add_subplot(1,1,1)と等価. 1行1列の1番目のグラフをaxとして取得
ax.set_facecolor("#D3DEF1")
ax.set_title("宇都宮市")
ax.set_xlabel("平均気温 (℃)")
ax.set_ylabel("世帯あたりのアイスクリーム・シャーベットの消費金額 (円)")
ax.grid(True, axis="both", color="w", linestyle="dotted", linewidth=0.8)
for i in range(len(x)):
    tcol = seasoncolor(i + 1)
    ax.scatter(x[i], y[i], marker="o", s=20, color=tcol, zorder=20000, alpha=0.7)
    ax.text(x[i], y[i], str(i + 1) + "月", color="k", fontsize=8, ha="left", va="bottom")
ax.text(0.1, 0.9, "r=" + str("%5.2f" % corrcoef), transform=ax.transAxes, fontsize=12)
plt.show()
plt.close()
../_images/4e24c04380247b7f512c9a23995e2072cdb3ef2812502ad9fb866adc350ce526.png

4.4.6. \(\clubsuit\) ax (matplotlib.axes)#

上では、axという見慣れないものが導入されている。

キャンバスの上に小さな作業領域axesを指定するためのadd_subplotやadd_axesといった関数がある。 axはこれらの関数で生成される作業領域に慣例的に用いる変数名で、とくに作業領域が一つの場合によく用いる。

axesを使うと、キャンバス上に複数のグラフを描くことができるので、たとえばキャンバスを四分割して、似たようなグラフを4つ同時に描いたりするのに便利.
axesを使いこなすのは少々テクニカルな点も多いので、よくわからない部分はとりあえず飛ばし読みで構わない。

使いこなせれば、論文に使う図表を作るなど、大変重宝するはずだ。細かい図の書き方は必要に応じて勉強していこう.

axesに関しては、日本語で書かれた以下の記事もおすすめ: https://qiita.com/skotaro/items/08dc0b8c5704c94eafb9

下ではadd_subplotを使って、キャンバス上に小さな作業領域を作成している. add_subplotの引数は、(行数, 列数, 作業領域番号)で、 3行2列の作業領域を作成する場合、左上から右下に向かって1,2,3,...と番号が振られる.

行数・列数・作業領域番号は整数で指定するが、いずれも10未満の場合であれば、 連続して書くことでも同じ意味になる. 具体的には、add_subplot(3,2,1)はadd_subplot(321)とも書けるが、 add_subplot(4,3,10)はadd_subplot(4310)とは書けない(全て一桁で無いとambiguityが生じるため).

fig = plt.figure(figsize=(10, 5))
axTL = fig.add_subplot(2, 2, 1)  # TL: Top Leftのつもり
axTR = fig.add_subplot(2, 2, 2)  # TR: Top Rightのつもり
axBL = fig.add_subplot(2, 2, 3)  # BL: Bottom Leftのつもり
axBR = fig.add_subplot(2, 2, 4)  # BR: Bottom rightのつもり
axTL.plot(data)
axTR.scatter(x, y)
axBL.bar(label, data, align="center", width=0.5, color="red")
axBR.text(0.5, 0.4, "右下だよ")
plt.show()
plt.close()
../_images/fdb56c512661b2e29f312e01ac380c8d465250079e2496386f1149dbe7ec77a8.png

4.4.7. ファイル操作とグラフの保存#

プログラムを実行して絵を描けるようになったら、次にそれを保存して、レポートに貼り付けたり、誰かに送ったりする必要が出てくる。

Google Colabでは、Google Driveをマウントすると、自分のドライブ上のファイルを読み書きできる。以下のセルを実行し、表示される案内に従って接続を許可しよう。準備のコードの意味は、今は分からなくても構わない。

from pathlib import Path

try:
    from google.colab import drive
except ImportError:
    drive = None

if drive is not None:
    drive.mount("/content/drive")
    base_dir = Path("/content/drive/MyDrive")
else:
    # 教材のルート、または notebooks フォルダから実行する
    book_dir = Path.cwd()
    if not (book_dir / "Chapter8_data").is_dir():
        book_dir = book_dir.parent
    if not (book_dir / "Chapter8_data").is_dir():
        raise FileNotFoundError("教材のルートか notebooks フォルダから実行してください。")
    base_dir = book_dir / "outputs"
    base_dir.mkdir(exist_ok=True)

print("保存先の起点:", base_dir)
保存先の起点: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs

Colabでは、アカウントの選択や画面の指示に従ってマウントする。成功すると Mounted at ... と表示される。

base_dir に保存先の起点が入ったので、その直下にあるファイルやフォルダを確認してみよう。

for path in sorted(base_dir.iterdir()):
    print(path.name)
Colab_pic
GDPvsWomenInSchool
chapter8

ここでは Path の iterdir() でディレクトリの中身を調べた。Colabでは !ls /content/drive/MyDrive のようなLinuxコマンドでも確認できる。

半角のスラッシュ / はディレクトリ階層の区切りである。このようにファイルの場所を指定するものをパスと呼ぶ。詳しくは第8章で扱う。

次に、図を保存する Colab_pic というフォルダを作っておこう。ここでは Path の mkdir メソッドを使う。

pic_dir = base_dir / "Colab_pic"
pic_dir.mkdir(parents=True, exist_ok=True)
print(pic_dir)
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/Colab_pic

エラーが出なければ、表示された場所に Colab_pic というディレクトリが作成されているはず。

exist_ok=True を付けると、フォルダが既にあってもエラーにならない。ノートを開く度に実行してもよい。

これで準備ができた。試しに以下のコードを実行して図を保存してみよう。

# 先程の図
fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(1, 1, 1)
ax.set_facecolor("#D3DEF1")
ax.set_title("宇都宮市")
ax.set_xlabel("平均気温 (℃)")
ax.set_ylabel("世帯あたりのアイスクリーム・シャーベットの消費金額 (円)")
ax.grid(True, axis="both", color="w", linestyle="dotted", linewidth=0.8)
for i in range(len(x)):
    tcol = seasoncolor(i + 1)
    ax.scatter(x[i], y[i], marker="o", s=10, color=tcol, zorder=20000, alpha=0.7)
    ax.text(x[i], y[i], str(i + 1) + "月", color="k", fontsize=8)
ax.text(0.1, 0.9, "r=" + str("%5.2f" % corrcoef), transform=ax.transAxes, fontsize=12)
###plt.show()の代わりに、savefigというメソッドを使い、グラフを保存する
plt.savefig(pic_dir / "scatter_Utsunomiya_ice.pdf")
plt.close()

上のコードを実行後に、pic_dir で指定したフォルダを確認してみよう。ColabでGoogle Driveに保存した場合、画面への反映に少し時間がかかることもある。

scatter_Utsunomiya_ice.pdf ができただろうか。Matplotlibは拡張子から保存形式を選ぶので、.jpg、.pdf、.eps、.png なども試してみよう。

注意

plt.show() の後では、実行環境によって図が閉じられ、続く plt.savefig() が空の図を保存してしまうことがある。保存するときは savefig()、show() の順にするとよい。

余談

プレゼンのスライドに載せるグラフは、可能ならベクタ形式(PDFなど)にしよう。拡大しても線や文字がガビガビにならない。PNGなどを使う場合も、必要な解像度を確保しておこう。

頑張って作った図なのに、細かい文字や線が潰れて読めないのはもったいない。実際に使う大きさで一度確認しておくと良い。

4.4.8. gifアニメーションの作成#

「なんだこの程度のグラフならExcelでも簡単にできるじゃん...」と思った皆さんのために、もう少し凝ったことをやってみましょう。

以下のリンクに、GDPと25〜34歳の平均就学年数の女性/男性比(%)を示したグラフを入れてある。Gapminderのデータをもとに、Pythonで幾つかの国を抜き出して作図したものである。

https://drive.google.com/file/d/1-Ko1pY3Pk4Wf05qMiMPFP9Yu-DM4vhpX/view?usp=sharing

この画像ファイルをパラパラ漫画のようにしてgifアニメーションにしてみよう.そのために必要なファイルにGoogle Colab.からアクセスできるよう、以下のいずれかの手順で作業しよう(授業ではより簡単な2を使う)

4.4.8.1. 方法1: Google Driveを開いて直接操作する方法#

  1. まず上記リンクからダウンロード

  2. Zip形式なので、それを解凍する

  3. 解凍したフォルダを自身のGoogle Driveの好きな場所にアップロードする ※以下のグラフを作成するコードをそのまま使いたければマイドライブ直下にアップロード

つまり、アップロードされた画像ファイルが、マイドライブ→GDPvsWomenInSchoolという階層にある状態になる。

4.4.8.2. 方法2: LinuxコマンドとPythonコードで行う方法#

授業ではこちらを使う。以下のセルを順に実行すれば、Colabの中でファイルの取得と解凍までできる。

  1. Google Driveをマウントしておく

  2. Pythonコードを使って、共有リンクからzipファイルを保存する

  3. unzipコマンドで、Google Driveに画像を取り出す

# 先ほどのセルでDriveをマウント済み。保存先を確認する
print(base_dir)
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs
# 手順2. 共有リンクからZIPファイルを取得する
import urllib.request

if drive is not None:
    url = "https://drive.google.com/uc?export=download&id=1-Ko1pY3Pk4Wf05qMiMPFP9Yu-DM4vhpX"
    filename = Path("GDPvsWomenInSchool.zip")
    urllib.request.urlretrieve(url, filename)
else:
    filename = book_dir / "data" / "GDPvsWomenInSchool.zip"
# 手順3. ZIP内のPNG画像をマイドライブに取り出す
# -o は上書きする指定。同じセルを繰り返し実行してもよい。
!unzip -o "{filename}" 'GDPvsWomenInSchool/*.png' -d "{base_dir}"
Archive:  /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/data/GDPvsWomenInSchool.zip
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1981.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1995.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1994.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1980.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1996.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1982.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1983.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1997.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1978.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1993.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1987.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1986.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1992.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1979.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1984.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1990.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1991.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1985.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2008.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2009.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2010.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2004.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2005.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2011.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2007.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2013.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2012.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2006.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2002.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2003.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2015.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2001.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2000.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2014.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1977.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1988.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1989.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1976.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1974.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1975.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1971.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1970.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1972.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1999.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1998.png  
  inflating: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1973.png  

4.4.8.3. PNGファイルを読み込んでGIFアニメーションを作成する#

Google Driveに画像が用意できたか、以下のセルで確認してみよう。

image_dir = base_dir / "GDPvsWomenInSchool"
!ls "{image_dir}"/*.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1970.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1971.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1972.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1973.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1974.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1975.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1976.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1977.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1978.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1979.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1980.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1981.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1982.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1983.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1984.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1985.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1986.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1987.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1988.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1989.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1990.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1991.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1992.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1993.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1994.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1995.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1996.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1997.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1998.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_1999.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2000.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2001.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2002.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2003.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2004.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2005.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2006.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2007.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2008.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2009.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2010.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2011.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2012.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2013.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2014.png
/Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/GDPvsWomenInSchool/GDPvsWomenInSchool_2015.png

上の手順で準備した場合は、このまま実行してよい。自分で別の画像フォルダを使うときは、image_dir を変更する。

ファイルが確認できたら、年代ごとに別々になったたくさんのグラフを、1つのパラパラ漫画にまとめてみよう。

pngファイルをまとめてgifにするコードは以下の通り(処理にしばし時間がかかる):

from PIL import Image

# まとめたいPNG画像をワイルドカード * で指定
files = sorted(image_dir.glob("GDPvsWomen*.png"))
if not files:
    raise FileNotFoundError(f"PNG画像が見つかりません: {image_dir}")

images = []
for file in files:
    with Image.open(file) as img:
        images.append(img.convert("RGB"))

# 出力名と保存場所を指定して、GIFアニメーションとして保存
oupf = pic_dir / "GDPvsWomen.gif"
images[0].save(oupf, save_all=True, append_images=images[1:], duration=400, loop=0)
for img in images:
    img.close()
print("保存先:", oupf)
保存先: /Users/sotair/lec_uu_drive/lecture_UtsunomiyaUniv/Lecture_DataScience_Polished/outputs/Colab_pic/GDPvsWomen.gif

エラーが出なければ、変数oupfで指定した場所に、gifファイルが生成されている。

作成例: ファイルへのリンクはこちら

4.4.9. \(\clubsuit\)おまけ#

その他のグラフ

二次元ヒストグラム

import matplotlib.cm as cm
import numpy as np

mu1 = [3.0, 2.0]
cov1 = [[1.0, 0.7], [0.7, 1.0]]
numS = 50000

sample1 = np.random.multivariate_normal(mu1, cov1, numS)
x1, y1 = sample1.T

fig = plt.figure(figsize=(6, 5))
ax1 = fig.add_subplot(111)
H1 = ax1.hist2d(x1, y1, bins=40, cmap=cm.jet)
ax1.scatter(mu1[0], mu1[1], color="k", marker="x")
ax1.set_title("sample1")
ax1.set_xlabel("x")
ax1.set_ylabel("y")
fig.colorbar(H1[3], ax=ax1)
plt.show()
plt.close()
../_images/d6f5bf7bdcf4cfd8b1f8d47e6a8a72f5b77b4c1d05cb97b124ee76635a063dab.png

日本地図。次のセルでライブラリの準備まで行う。

%pip -q install japanmap

from japanmap import picture
import matplotlib.pyplot as plt
Note: you may need to restart the kernel to use updated packages.
plt.figure(figsize=(6, 6))
plt.imshow(picture({"栃木県": "red", "群馬県": "blue"}))
plt.axis("off")
plt.show()
plt.close()
../_images/f1ed068d2044a6316769ca487f2571c0877e1377c5ee5039e91aeb815dc42c5d.png

4.5. 色に関する注意#

色は、データの可視化において非常に重要な要素である.一方で、色は人間の感覚に依存するため、その選択には注意が必要である。
例えば、男性の20人に1人程度の割合で何らかの色覚異常があるとされている。
Pythonでは、カラーマップやパレットといった、色の選択を補助するための機能が用意されているが、 カラーマップの中にも、colorblind friendlyなものが用意されており、学術論文などでも、色覚異常の読者に対する配慮が求められることがある。

自分が見ている世界と、他人が見ている世界は異なるという事実を意識するのは、色に限らずコミュニケーションなどにおいても重要である。