データ分析実践
上級問題チェック
問題 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)



