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
のみで作成 / 描画できる。
Point
Label
Box
Ellipse
Cylinder
Polygon
Rectangle
Ellipsoid
Wall
Corridor
Polyline
PolylineVolume
Billboard
ここではそのうちいくつかを例として記載する。ドキュメントには全ての 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件) を見る