国土地理院の公開データを基に、GeoPandas の dissolve と simplify を用いて、都道府県の境界情報を含む shapefile を作成した (prefecture.xxx). まず、前回使用した市区町村の境界情報データ (town.xxx) と組み合わせて、位置情報の取り扱いを見てみる.

市区町村境界情報を読み込み所属未定地を削除し、各市区町村の幾何中心を求める. 東京都中央区が含まれる県を探してみる.

import geopandas as gpd
path = 'town.shp'
town = gpd.read_file(path, encoding = 'sjis')

path = 'prefecture.shp'
pref = gpd.read_file(path, encoding = 'sjis')
town = town[town['市区町村'] != '所属未定地']
town['centroid'] = town.geometry.centroid
ref = town[town['市区町村'] == '中央区'].centroid.values[0]   
pref[pref.geometry.contains(ref)]

期待通り、東京都が表示された.

    id 都道府県                                           geometry
26  26  東京都  (POLYGON ((153.9840799995924 24.29761444135346...

ニューヨークの座標を作成し、それを含む県を探してみる.

from shapely.geometry import Point
ny = Point(40.743719, -74.002853)
pref[pref.geometry.contains(ny)]

期待通り、どの都道府県も表示されない.

Empty GeoDataFrame
Columns: [id, 都道府県, geometry]
Index: []

contains() の他に、intersects()、within() も使用可能. 近接点を求めることも可能. 次に、中央区の幾何中心に最も近い市区町村の幾何中心を探してみる. 千代田区の幾何中心が最も近い.

from shapely.ops import nearest_points
X = town[town['市区町村'] != '中央区'].centroid.unary_union 
town[town.centroid == nearest_points(ref, X)[1]] 
      id 都道府県  市区町村     town                                           geometry                                     centroid
989  989  東京都  千代田区  東京都千代田区  POLYGON ((139.7728658372886 35.70370213544527,...  POINT (139.7549088445381 35.68766566327401)

千代田区の次に近い所を探すと、江東区となった.

X = town[(town['市区町村'] != '中央区') & (town['市区町村'] != '千代田区')].centroid.unary_union  
town[town.centroid == nearest_points(ref, X)[1]]
        id 都道府県 市区町村    town                                           geometry                                     centroid
1020  1020  東京都  江東区  東京都江東区  (POLYGON ((139.8337401947542 35.70289566660176...  POINT (139.8151834789071 35.65975371541843)

GeoViews を用いて県境を表示する. バックエンドに Bokeh を使用しているのでインタラクティブな地図が表示される.

import geoviews as gv
gv.extension('bokeh')
fig = gv.Shape.from_shapefile('prefecture.shp')
gv.save(fig, 'pref.html', size=200)



これに都道府県別のデータを重ねて、choropleth map を作成してみる. 総務省統計局作成の平成29年10月1日現在に於けるエクセル形式の都道府県別人口データを使用する. データを読み込んだ後に都道府県別外国人数とその割合を計算している.

import pandas as pd
path = '05k29-2.xls'
cols = [2, 4, 5, 6, 7, 8, 9, 10, 11]
names = ['prefecture', 'total', 'male', 'female', 'ratio',
        'total_jpn', 'male_jpn', 'female_jpn', 'ratio_jpn']
stat = pd.read_excel(path, skiprows=10, names=names, usecols=cols, skipfooter=3)
stat['prefecture'].fillna('全国', inplace=True)
stat['prefecture'] = stat['prefecture'].str.replace(u"\u3000", '')
stat['total_frn'] = stat.apply(lambda row: (row['total']-row['total_jpn']), axis=1)
stat['ratio_frn'] = stat.apply(lambda row: (row['total_frn']/row['total']*100.), axis=1)

先ほど読み込んだ県境データと組み合わせて、都道府県別外国人数を表示する.

gdf = gpd.GeoDataFrame(pd.merge(pref, stat, left_on='都道府県', right_on='prefecture'))
options = {'title': '(千人)'}
fig = gv.Polygons(gdf, vdims=['prefecture', 'total_frn']).opts(
    tools=['hover'], width=500, height=400, color_index='total_frn',
    colorbar=True, toolbar='above', xaxis=None, yaxis=None).opts(title="外国人人口", colorbar_opts=options)
gv.save(fig, 'foreigners.html')

都道府県別外国人比率を表示する. 関東・中部・関西にかけて外国人比率が高いことが分かる.

options = {'title': '%'}
fig = gv.Polygons(gdf, vdims=['prefecture', 'ratio_frn']).opts(
    tools=['hover'], width=500, height=400, color_index='ratio_frn',
    colorbar=True, toolbar='above', xaxis=None, yaxis=None).opts(title="外国人比率", colorbar_opts=options)
gv.save(fig, 'ratio_foreigners.html')



以上、地図情報と統計データを組み合わせて簡単に図が作成できることを確認した.