Cesium.js を Python から使うパッケージを作った
3D 地図を表示する JavaScript ライブラリである Cesium.js を Python から簡単に使いたい。Cesium.js についてはこちらを。
上に記載した方法は、可視化したい内容に応じて JavaScript のテンプレートを作成し、Python からデータを埋め込むというものだった。が、都度 テンプレートを作るのはさっと可視化したい場合にはめんどくさい。
ということでこれを Python のみ / JavaScript なしで利用できるパッケージを書いた。
使い方
サンプルデータは前と同じく こちらのエントリのものを利用する。作成した DataFrame は変数 df に入っているとする。
インストール
pip で。
$ pip install cesiumpy
地図の表示
以降の操作は Jupyter Notebook 上で行う。装飾のない地図を表示したいだけなら Viewer インスタンスを作成すればよい。地図は Jupyter のセルに埋め込まれて表示される。
import cesiumpy cesiumpy.__version__ # '0.1.1' cesiumpy.Viewer()

グラフの描画
Cesium.js では以下のような図形 ( Entity ) が描画できる。cesiumpy を使うとこれらを Python のみで作成 / 描画できる。
PointLabelBoxEllipseCylinderPolygonRectangleEllipsoidWallCorridorPolylinePolylineVolumeBillboard
ここではそのうちいくつかを例として記載する。ドキュメントには全ての Entity の画像と作り方を簡単に記載している。
Cylinder
上の例と同じく、Cylinder で 3D 棒グラフを描く。Entity を描画するには、まず当該のインスタンスを作成し、Viewer.entities.add メソッドに渡せばよい。
v = cesiumpy.Viewer() for i, row in df.iterrows(): l = row['Recreation Visitors (2014)[5]'] cyl = cesiumpy.Cylinder(position=[row['lon'], row['lat'], l / 2.], length=l, topRadius=10e4, bottomRadius=10e4, material='aqua') v.entities.add(cyl) v

Point
Point クラスを使うと バブルチャートが描ける。
また、右上に並んだアイコンで投影法や地面の画像 ( Imagery ) が変更できる。ここでは Open Street Map を表示している。Imagery は スクリプトからも変更できる。
v = cesiumpy.Viewer() for i, row in df.iterrows(): l = row['Recreation Visitors (2014)[5]'] p = cesiumpy.Point(position=[row['lon'], row['lat'], 0], pixelSize=np.sqrt(l / 10000), color='blue') v.entities.add(p) v

Billboard ( Pin )
Leaflet のように ピン を表示する場合は Billboard と Pin を使う。ピンの色やラベルを変更することもできる。
v = cesiumpy.Viewer() pin = cesiumpy.Pin() for i, row in df.iterrows(): l = row['Recreation Visitors (2014)[5]'] b = cesiumpy.Billboard(position=[row['lon'], row['lat'], 0], image=pin, scale=0.4) v.entities.add(b) v

scipy.spatial の利用
また、cesiumpy は scipy.spatial に含まれる以下のような図を地図上に重ねて描くことができる。
- ボロノイ図 (
scipy.spatial.Voronoi) - 凸包 (
scipy.spatial.ConvexHull)
まずはデータを合衆国本土のみにフィルタする。
filtered = df[(-130 < df['lon']) & (df['lon'] < -60) & (20 < df['lat']) & (df['lat'] < 50)] filtered.shape # (47, 10)
フィルタしたデータから、各レコードの座標 (経度, 緯度) からなる tuple の list を作成する。
pos = filtered[['lon', 'lat']].values pos = [tuple(p) for p in pos] pos # [(-68.129999999999995, 44.210000000000001), # (-109.34, 38.409999999999997), # ... # (-119.3, 37.5), # (-113.03, 37.18)]
まず scipy で書くとこのような処理になる。詳細は以下のドキュメントに記載されているが、プロットの見た目を変更したり、各領域の座標を再利用できる形に変換するのは少し手間だ。
- scipy.spatial.Voronoi — SciPy v0.16.1 Reference Guide
- Spatial data structures and algorithms (scipy.spatial) — SciPy v0.16.1 Reference Guide
from scipy.spatial import Voronoi, voronoi_plot_2d vor = Voronoi(pos) vor # <scipy.spatial.qhull.Voronoi at 0x107dbab50> voronoi_plot_2d(vor)

一方、cesiumpy でやるとこんな感じ。cesiumpy.spatial.Voronoi.get_polygons() は、各座標を 対応するボロノイ領域を含む Polygon のリストに変換する。これに適当に色付けして地図上に表示すればよい。
ボロノイ領域は元の座標と同じ順序になっているため、元座標に応じて色分けすることもできる。
colors = [cesiumpy.color.BLUE, cesiumpy.color.RED, cesiumpy.color.YELLOW, cesiumpy.color.ORANGE,
cesiumpy.color.PURPLE, cesiumpy.color.GREEN, cesiumpy.color.WHITE, cesiumpy.color.AQUA,
cesiumpy.color.NAVY, cesiumpy.color.PINK, cesiumpy.color.MAGENTA]
v = cesiumpy.Viewer()
polygons = cesiumpy.spatial.Voronoi(pos).get_polygons()
colors = np.random.choice(colors, len(polygons))
for p, c in zip(polygons, colors):
p.material = c.set_alpha(0.1)
p.outline = True
v.entities.add(p)
v

まとめ
cesiumpy を使うと Cesium.js を利用した可視化が JavaScript なしで書ける。
Entityを利用したグラフの描画、可視化- ボロノイ図や凸包の描画
また、上には含めなかったが下のような処理もできる。

インタラクティブ・データビジュアライゼーション ―D3.jsによるデータの可視化
- 作者: Scott Murray,長尾高弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2014/02/19
- メディア: 大型本
- この商品を含むブログ (3件) を見る