伝わる?
不定期に「スコア分布」を収集しているとする。一回のスナップショットだとこんなヒストグラム:
つまりこういう分布データを以下のように収集してるわけだ:
1 '2017-12-20 17:18:01', [45, 30, 60, 167, 278, 510, 1236, 2110, 1957, 1615]
2 '2017-12-20 20:09:01', [46, 30, 60, 167, 278, 508, 1237, 2117, 1961, 1620]
3 '2017-12-21 02:35:34', [48, 30, 61, 169, 280, 511, 1237, 2130, 1964, 1629]
4 '2017-12-21 08:09:10', [48, 29, 61, 170, 278, 517, 1239, 2131, 1973, 1633]
5 ...(snip)...
6 '2017-12-30 10:58:17', [60, 39, 68, 191, 354, 735, 2227, 4926, 5559, 3782]
7 '2017-12-30 14:09:19', [60, 39, 68, 192, 354, 737, 2242, 4953, 5594, 3805]
8 '2017-12-30 20:09:12', [61, 38, 68, 193, 357, 748, 2252, 5008, 5666, 3844]
ほんとは boxplot を時間軸に沿って並べたかった。金融系でよくみるアレね。けど matplotlib の boxplot はすごく使いにくい。X が 2、3 個ならちゃんと boxplot になるけど、多くなるとすぐにダメになる。(箱にならずに縦線が並んでるようにみえる。)
なので代替案として coutourf しちゃおうかと:
1 def build_score_dist_boxplot(dba, name):
2 from datetime import datetime
3 import numpy as np
4 import matplotlib.pyplot as plt
5
6 fig, ax = plt.subplots()
7 x_f = []
8 x_d = []
9 z = []
10 first = None
11 for dtstr, dist in dba.query_score_dist_by_name(name):
12 dt = datetime.strptime(dtstr[:-3], "%Y-%m-%d %H:%M")
13 if first is None:
14 first = dt
15 x_f.append((dt - first).total_seconds())
16 x_d.append(dtstr[5:-3])
17 z.append([float(d) / max(dist) for d in dist])
18
19 X, Y = np.meshgrid(x_f, list(range(1, 11)))
20 pc = ax.contourf(X, Y, np.array(z).T, 15, cmap=plt.get_cmap("rainbow"))
21 ax.set_xticks(())
22 fig.tight_layout()
23 fig.savefig(name + ".png")
24 plt.close(fig)
dba.query_score_dist_by_name
が上に示したデータを返してくる。
地味に colormap (の刻み幅) と X の ticks で苦労した。15 してるのが色の刻み幅、これをしないとデフォルトで 7 で、粗くて滅茶苦茶かっこ悪い(し、みにくい)。ticklabels は、countorf は X として数値しか受け付けないので、てこと。set_xticklabels でもうまくいってないので、今回は諦めた。
てわけで、2つの結果:
特定の X で縦に切って断面図を取れば最初に示したヒストグラムに似たものが出てくる、と言葉で伝わるかなぁ。上のグラフが 9 に集中しつつあって、下のグラフが 8 が 7~8 に広がりつつある(おそらく 7 に集中し始めてる兆候)。
なお、見栄えこそ良いけれど、boxplot のような「情報の要約」を持たないので、まぁ単独のヒストグラムと同じく「雰囲気」がわかるだけ、ということはわかっておくんなまし。