データ分析実践
上級問題チェック

問題 40 /40

次のDataFrameは、品川区の公共施設のオープンデータである。 df ▶︎
GeoPandasとFoliumを使って、次のように先頭の5つの施設のマーカーをプロットする場合、正しい記述はどれか。 map ▶︎
*マーカーにマウスオーバーすると「品川区役所」等の施設名を表示。

選択 1

geometry = gpd.points_from_xy(df['経度'], df['緯度']) gdf = gpd.GeoDataFrame( df, geometry=geometry, crs=6668) x_map = gdf.centroid.x.mean() y_map = gdf.centroid.y.mean() map = folium.Map( location=[y_map, x_map], zoom_start=14) folium.Choropleth( gdf.loc[:4, :] ).add_to(map)

選択 2

gdf = gpd.GeoDataFrame(df, crs=6668) x_map = gdf.centroid.x.mean() y_map = gdf.centroid.y.mean() map = folium.Map( location=[y_map, x_map], zoom_start=14) folium.Choropleth( gdf.loc[:4, :], tooltip='施設名', ).add_to(map)

選択 3

center = df.loc[:, ['緯度', '経度']].mean() map = folium.Map( location=center, zoom_start=14) for i, row in df.loc[:4, :].iterrows(): folium.Marker( location=[row['緯度'], row['経度']], tooltip=row['施設名'], ).add_to(map)

選択 4

center = df.loc[:, ['緯度', '経度']].mean() map = folium.Map( location=center, zoom_start=14) folium.Marker( location=[df.loc[:4, '緯度'], df.loc[:4, '経度']], tooltip=row['施設名'], ).add_to(map)

解説

選択肢3が正解です。 Foliumは地図を表示したりマーカーをプロットすることができます。 import folium lat = 35.71 lon = 139.81 # 東京スカイツリーの緯度・経度です。 map = folium.Map( location=[lat, lon], zoom_start=16) # location引数に中心の座標を渡し、zoom_start引数で表示倍率を指定し、地図のオブジェクトを生成しています。 folium.Marker( location=[lat, lon], tooltip='東京スカイツリー', ).add_to(map) # location引数でマーカーをプロットし、tooltip引数でマウスオーバーした際に表示される情報を指定しています。 map ▶︎
実際のデータ分析では、オープンデータなどを使って一度に複数のマーカーをプロットすることがあります。 問題文の公共施設のCSVデータは、次のサイトからダウンロードできます。 https://catalog.data.metro.tokyo.lg.jp/dataset/t131091d0000000003 ダウンロードした「kokyoshisetsu.csv」を、Pandasのread_csv関数で読み込みます。 df = pd.read_csv( 'kokyoshisetsu.csv', encoding='shift-jis', usecols=['施設名', '緯度' ,'経度']) df ▶︎
【選択肢1】 ------------------------------- geometry = gpd.points_from_xy(df['経度'], df['緯度']) # 問題文のDataFrameはGeometry型のデータがありません。そのため、最初にGeoPandasのpoints_from_xy関数で、Pointオブジェクトを生成しています。 geometory ▶︎ <GeometryArray> [ <POINT (139.73 35.609)>, <POINT (139.74 35.617)>, <POINT (139.741 35.611)>, <POINT (139.717 35.628)>...] gdf = gpd.GeoDataFrame( df, geometry=geometry, crs=6668) # geometry列に先のPointオブジェクトを指定してGeoDataFrameを生成しています。GeoDataFrameはCRSを指定しない場合、内部的にはデフォルトのEPSG:4326が適用されますが、後のcentroidメソッドやChoropleth関数は明示的にCRSが設定されていないとエラーになるため、日本の地理座標系であるEPSG:6668をセットしています。 gdf ▶︎
x_map = gdf.centroid.x.mean() y_map = gdf.centroid.y.mean() # GeoPandasのcentroidメソッドで経度と緯度の中心を算出しています。 x_map ▶︎ 139.7261744591029 y_map ▶︎ 35.611328087071236 map = folium.Map( location=[y_map, x_map], zoom_start=14) # FoliumでMapオブジェクトを生成しています。 folium.Choropleth( gdf.loc[:4, :] ).add_to(map) # FoliumのChoropleth関数で、公共施設(先頭5つ)のマーカーをプロットしています。 ------------------------------- この記述で地図が表示されマーカーもプロットされますが、マウスオーバーしても施設名の情報が表示されないため誤りです。 【選択肢2】 ------------------------------- gdf = gpd.GeoDataFrame(df, crs=6668) x_map = gdf.centroid.x.mean() y_map = gdf.centroid.y.mean() map = folium.Map( location=[y_map, x_map], zoom_start=14) folium.Choropleth( gdf.loc[:4, :], tooltip='施設名', ).add_to(map) ------------------------------- 誤った記述です。 一行目でGeoDataFrameを生成する際、geometryの引数をつけていないため、Geometry型のデータがないGeoDataFrameになります。そのため、後のcentroid関数やChoropleth関数がエラーになります。 また、Choropleth関数にtooltipという引数はないため、施設名の情報は表示できません。 【選択肢3】 ------------------------------- center = df.loc[:, ['緯度', '経度']].mean() # 緯度と経度の平均値がSeriesで返ります。これにより公共施設の中心地が割り出せます。選択肢1のようにGedPandasのcentroidメソッドを使わなくても、DataFrameの緯度と経度で中心地を割り出せます。 center ▶︎ 緯度 35.611328 経度 139.726174 map = folium.Map( location=center, zoom_start=14) # Mapオブジェクトを生成しています。 for i, row in df.loc[:4, :].iterrows(): # pandasのiterrowsメソッドは、行ごとのイテラブルオブジェクトを返します。最初の行であれば、インデックスの「0」と「{'施設名': '品川区役所', '緯度': 35.608837, '経度': 139.73024}」の辞書が返ります。この辞書を、次のfolium.Markerの引数に渡します。 folium.Marker( location=[row['緯度'], row['経度']], tooltip=row['施設名'], ).add_to(map) # folium.Maker関数は選択肢1のChoropleth関数と違い、Geometry型のデータがなくても、緯度と経度の数値情報があればマーカーをプロットできます。また、tooltip引数に施設名を指定して、マウスオーバーした際に名前が表示されるようにしています。これで問題文の地図を表示できます。 ------------------------------- map ▶︎
なお、このmapをHTML形式で保存することで、Webブラウザでインタラクティブな地図を表示することもできます。 map.save('sample.html') 【選択肢4】 ------------------------------- center = df.loc[:, ['緯度', '経度']].mean() map = folium.Map( location=center, zoom_start=14) folium.Marker( location=[df.loc[:4, '緯度'], df.loc[:4, '経度']], tooltip=row['施設名'], ).add_to(map) ------------------------------- 誤った記述です。 mapオブジェクトは生成できますが、folium.Marker関数がエラーになります。選択肢3はfor文でDataFrameを一行ずつ処理していましたが、ここではlocation引数にdf.loc[:4, '緯度']のようにSeriesを渡しているため、TypeErrorになります。 df.loc[:4, '緯度'] ▶︎ 0 35.608837 1 35.616681 2 35.611373 3 35.627776 4 35.616945 (公式書籍 p.315-318、321)