統計検定の問題を解いていて、ヒストグラムが出てきましたので、勉強がてら Ploty、と、Bokeh でそれぞれ描画してみます。
データセットは、訪日外国人消費動向調査 | 統計情報 | 統計情報・白書 | 観光庁ある、平成30年1月~3月期 の集計結果を用います。


データセット

イギリスの人の日本にきた回数と、回答した人の数を抜粋しました。

訪問回数回答数
1回目84
2回目18
3回目12
4回目4
5回目12
6~9回目5
10~19回7
20回以上12

前提

Bokeh と Ploty の バージョンは以下の通りです。

  • Bokeh

% python3 -m pip list | grep bokeh
bokeh                             0.12.16  

  • holoviews
    bokeh 0.12.16 で、graph描画する方法が見つけられず、holoviews 経由で描画したので、holoviewsもインストールしております。

    holoviews                         1.10.4 
    

  • Ploty

% python3 -m pip list | grep plotly
plotly                            2.7.0      

ヒストグラムについて

そもそも、棒グラフなのですが、真面目に考えるとあまりよくわかっていなかったので、調べてみました。

Bokeh でヒストグラムを描画する

まず、Bokeh でヒストグラムを描画します。
調べた限りだと、区間決定後のヒストグラムを描画する方法がわからず、区間決定後の値を再度集計して、bins を 20 に指定して描画しました。
警告が出ましたが、そのまま描画しております。

import numpy as np
import holoviews as hv
import random
hv.extension('bokeh')
# ヒストグラムの値 区間決定後の値 を np.repeat、np.concatenate を使って再度集計
values = np.concatenate([np.repeat([1], 84), 
                np.repeat([2], 18), 
                np.repeat([3], 12), 
                np.repeat([4], 4), 
                np.repeat([5], 12), 
                np.repeat([random.randint(6,9)], 5), 
                np.repeat([random.randint(10,19)], 7), 
                np.repeat([random.randint(20,20)], 12)],  axis=0)
frequencies, edges = np.histogram(values, 20)
# options で グラフの幅を指定
hv.Histogram(frequencies, edges).options(width=600)

WARNING:root:Histogram: Histogram edges should be supplied as a tuple along with the values, passing the edges will be deprecated in holoviews 2.0.

"bokeh ヒストグラム"

Plotly で描画する

これは、現在はまだ動作しない旨の警告が出力されました。

import numpy as np
import holoviews as hv
import random
hv.extension('plotly')
# ヒストグラムの値 区間決定後の値 を np.repeat、np.concatenate を使って再度集計
values = np.concatenate([np.repeat([1], 84), 
                np.repeat([2], 18), 
                np.repeat([3], 12), 
                np.repeat([4], 4), 
                np.repeat([5], 12), 
                np.repeat([random.randint(6,9)], 5), 
                np.repeat([random.randint(10,19)], 7), 
                np.repeat([random.randint(20,20)], 12)],  axis=0)
frequencies, edges = np.histogram(values, 20)
hv.Histogram(frequencies, edges)

The plotly backend is experimental, and is not supported at this time. If you would like to volunteer to help maintain this backend by adding documentation, responding to user issues, keeping the backend up to date as other code changes, or by adding support for other elements, please email holoviews@gmail.com

WARNING:root:Histogram: Histogram edges should be supplied as a tuple along with the values, passing the edges will be deprecated in holoviews 2.0.





:Histogram   [x]   (Frequency)

ploty の API を直接使用する

以下、のコードでヒストグラムが描画できました。

import numpy as np

import plotly.plotly as py
import plotly.graph_objs as go
import random
import plotly.offline as offline
offline.init_notebook_mode()
# ヒストグラムの値 区間決定後の値 を np.repeat、np.concatenate を使って再度集計
values = tuple(np.concatenate([np.repeat([1], 84), 
                np.repeat([2], 18), 
                np.repeat([3], 12), 
                np.repeat([4], 4), 
                np.repeat([5], 12), 
                np.repeat([random.randint(6,9)], 5), 
                np.repeat([random.randint(10,19)], 7), 
                np.repeat([random.randint(20,20)], 12)],  axis=0))

data = go.Histogram(x=values, 
                    xbins=dict(start=0, end=20, size=1)) # 区間の指定。sizeが区間幅

# レイアウトの指定
layout = go.Layout(
    xaxis = dict(title="value", dtick=10), 
    yaxis = dict(title="count"),
    bargap = 0.1)

fig = dict(data=[data], layout=layout)
offline.iplot(fig)

"plotly ヒストグラム"


まとめ

区間決定後のデータを用いて、ヒストグラムを Bokeh と Plotly で描いてみました。
実施した後、思ったのですが、区間決定後のデータは普通に棒グラフで描くのでは?と思いました。
グラフ描画ライブラリの、ヒストグラムメソッドは、「ヒストグラムでないデータをヒストグラムにする」のが役割で、
既にヒストグラム化済みのデータセットを描画するためのものではないということがわかりました。

numpy の 変な使い方は学習できましたが、一般的なやり方ではなさそうに思いました。 以上です。

コメント