GeoPandasには普通のJoinとは違ってSpatial Joinなる地理空間結合があります。
GISデータを扱うときにそういったGeometryに関する結合は役に立つのですが、ドキュメントは英語だし、言い回しが似ていて挙動がどうもわかりにくいのが少々問題です(僕の英語力の問題か…)。
ということで今回はGeoPandasの地理空間結合の挙動を見ていきたいと思います。
-
データサイエンティストとして3年間で3社経験した僕の転職体験談まとめ
こんにちわ、サトシです。33歳です。 今回は、データサイエンティストの3年間に3社で働いた僕が、データサイエンティストとしての転職活動についてまとめて書きたいと思います。 これまでSE→博士研究員→ポ ...
Binary Predicates
まずは、Binary Predicatesなるものを紹介したいと思います。
こちら日本語訳がわからないので、そのままBinary Predicatesという事にします。
ざっくりどんなものかと言うと、複数のGISオブジェクト(point, linestring, polygonなど)の接触などトポロジカルな位置の関係性によって、TrueかFalseを返すものです。
こちらにShapelyのドキュメントがあるので、興味があれば見てみてください。
https://shapely.readthedocs.io/en/latest/manual.html#binary-predicates
とはいえ、ドキュメントをみてもわかりにくいので実際に実験してみます。
とりあえず、このようなオブジェクトを作ってみます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
a = LineString([(0, 0), (5, 5)]) b = LineString([(2, 2), (10, 2)]) c = Point(2.5, 2.5) d = Point(1, 1) e = Polygon([(0,0),(2,0),(2,2),(0,2)]) s = gpd.GeoSeries([ LineString([(0, 0), (5, 5)]), LineString([(2, 2), (10, 2)]), Point(2.5, 2.5), Point(1, 1), Polygon([(0,0),(2,0),(2,2),(0,2)]) ]) |
このGeoSeries : sとa~eの位置的な関係性から結果のTrue, Flaseを確認しますが、今回はBinary Predicatesの一部でintersects, touches, containsのみやってみます。
1 2 3 4 |
a.intersects(b) ===== True →交差していればOK |
1 2 3 4 |
e.touches(c) ===== False →共通の点があり、内部が交差していなければOK |
1 2 3 4 |
e.touches(a) ===== False →共通の点があるが、内部が交差してるのでNG |
1 2 3 4 |
e.touches(b) ===== True →共通の点があり、内部が交差していないのでOK |
1 2 3 4 |
e.contains(a) ===== False →containsは全部入ってないとNG |
1 2 3 4 |
e.contains(d) ===== True →全部入っているからOK |
地理空間結合 Spatial Join
Binary Predicatesがどんなものかやったので、やっとGeoDataFrameで地理空間結合(Spatial Join)をやってみたいと思います。
ドキュメントはこちらです。
https://geopandas.org/docs/user_guide/mergingdata.html
一般的な結合では、keyによってinner, left, right, crossなどの結合をしますが、地理空間結合ではkeyではなく2つのGeoDataFrameのGeometryの位置関係でJoinを行います。
そのときの位置関係にBinary Predicatesを指定する必要があるので、先ほどBinary Predicatesを紹介したのです。
というわけで、Intersectsによる地理空間結合をやってみます。
使うデータはGeoPandasに入っている国境データと都市データです。
1 2 |
world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres')) cities = gpd.read_file(gpd.datasets.get_path('naturalearth_cities')) |
1 2 |
ax = world.plot() cities.plot(ax=ax, color='red', markersize=2) |
1 2 |
countries = world[['geometry', 'name']].rename(columns={'name':'country'}) countries |
IntersectsによるSpatial Join
ではBinary PredicatesにIntersectsを指定した場合のSpatial Joinをやってみます。
Spatial Joinの頭文字をとって、"sjoin"でSpatial Joinができます。
まずは、inner join。
1 2 3 4 |
#spatial join #howはinner, left, rightをとりうる cities_with_country = cities.sjoin(countries, how="inner", predicate='intersects') cities_with_country |
Left join。
1 2 3 |
#leftの場合 cities_with_country = cities.sjoin(countries, how="left", predicate='intersects') cities_with_country |
Right join。
1 2 3 |
#rightの場合 同じ国の都市が複数あるので行が増えている cities_with_country = cities.sjoin(countries, how="right", predicate='intersects') cities_with_country |
-
データサイエンティスト経験3年の僕がフリーランスとして独立するまでの体験談
こんにちわ、サトシです。 今回は、企業でデータサイエンティストとして働いていた僕が、フリーランスとしてどのような手順で独立していったかについて書いていきたいと思います。 僕はSIer SE→博士過程→ ...
まとめ
今回はGeoPandasの地理空間結合(Spatial Join)とBinary Predicatesについて書きました。
Binary Predicatesは今回はintersects, touches, containsのみでしたが、他にもたくさん種類があるのでドキュメントをよく読んで適切なものを選ぶ必要があります。
また、GeoDataFrameのSpatial Joinをするときも、InnerやLeftなどは一般的なJoinと似た感じですが、結合keyがgeometryになるということで、もし使うことになったらこちらもちゃんとドキュメントを確認して結合方法を再確認したいですね。
がんばって英語を読みましょう!
PythonによるGISデータ分析の勉強法
PythonでGISデータの分析手法を学びたい方はUdemyのコースがおすすめです。日本語の書籍は全然ないです。。。