1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Automating GIS Processes 2024 写経 Lesson 5(Interactive maps 後半)

Posted at

前半 の続きです。

Add a layer of points

Folium also supports to add entire layers, for instance, as geopandas.GeoDataFrames. Folium implements Leaflet’s ``geoJSON layers <https://leafletjs.com/reference.html#geojson>__ in its folium.features.GeoJson class. We can initialise such a class (and layer) with a geo-data frame, and add it to a map. In the example below, we use the addresses.gpkg data set we create in lesson 3.

Foliumは、例えば、geopandas.GeoDataFrameなど、レイヤー全体の追加もサポートします。
Foliumは、そのfolium.features.GeoJsonクラスの中で、LeafletgeoJSONレイヤーを実装します。
GeoDataFrameのデータセットを使って、クラス(とレイヤー)を初期化し、それを地図に追加します。例えば以下のように。
なお、入力データとして、Lesson3で作成した、addresses.gpkgを使います。(作成するのが面倒な場合は、こちらにあります。)

まずはファイルを読み込みます。

import geopandas
addresses = geopandas.read_file(DATA_DIRECTORY / "addresses.gpkg")
addresses.head()

image.png

データは読み取れましたが、以下のワーニングがでてますね。

/usr/local/lib/python3.12/dist-packages/pyogrio/geopandas.py:275: UserWarning: More than one layer found in 'addresses.gpkg': 'addresses' (default), 'addresses_with_population_data'. Specify layer parameter to avoid this warning.
  result = read_func(

このaddresses.gpkgはレイヤーが複数あり、この処理では、デフォルトの'addresses'を読み取ったようです。
なので、geopandas.read_file()メソッドに、layer="addresses"を追加します。

import geopandas
addresses = geopandas.read_file(DATA_DIRECTORY / "addresses.gpkg", layer="addresses")
addresses.head()

image.png

読み込んだデータをプロットしてみましょう。

addresses.plot()

image.png

うん、よくわからないですね。では、読み込んだデータをポイントマーカーとして、地図に重畳してみましょう。

interactive_map = folium.Map(
    location=(60.2, 25.0),
    zoom_start=12
)

addresses_layer = folium.features.GeoJson(
    addresses,
    name="Public transport stops"
)
addresses_layer.add_to(interactive_map)

interactive_map

image.png

We can also add a pop-up window to our map which would show the addresses at the point of interest upon clicking:

また、ポップアップウィンドウも地図に追加できます。これにより、クリックしたポイントに、その場所の情報が表示できます。

interactive_map = folium.Map(
    location=(60.2, 25.0),
    zoom_start=12
)

popup = folium.GeoJsonPopup(
    fields=["address"],
    aliases=["Address"],
    localize=True,
    labels=True,
    style="background-color: yellow;",
)

addresses_layer = folium.features.GeoJson(
    addresses,
    name="Public transport stops",
    popup=popup
)
addresses_layer.add_to(interactive_map)

interactive_map

image.png

ポイントマーカーをどれかクリックしてみました。popupで指定した内容が表示されています。
image.png

Add a polygon layer

In the following section we are going to revisit another data set with which we have worked before: the Helsinki Region population grid we got to know in lesson 2, and which you used during exercise 3. We can load the layer directly from HSY’s open data WFS endpoint:

以下のセクションで、私たちは以前取り扱った別のデータセットを使います。ヘルシンキの人口グリッドで、Lesson2Excercise3で使ったものです。Helsinki Region InfoshareのWFS endpointから、直接レイヤーをロードできます。

# To ignore the SSL certificate issue
import ssl
ssl._create_default_https_context = ssl._create_unverified_context

population_grid = (
    geopandas.read_file(
        "https://kartta.hsy.fi/geoserver/wfs"
        "?service=wfs"
        "&version=2.0.0"
        "&request=GetFeature"
        "&typeName=asuminen_ja_maankaytto:Vaestotietoruudukko_2020"
        "&srsName=EPSG:4326"
        "&bbox=24.6,60.1,25.2,60.4,EPSG:4326"
    )
    .set_crs("EPSG:4326")
)
population_grid.head()

image.png

Let’s first clean the data frame: drop all columns we don’t need, and rename the remaining ones to English.

最初に、データフレームをきれいにしましょう。使わない列を無くし、残った列の名前を英語にしましょう。

population_grid = population_grid[["index", "asukkaita", "geometry"]]
population_grid = population_grid.rename(columns={
    "asukkaita": "population"
})

population_grid.head()

image.png

Index column for choropleth maps
We will use the folium.Choropleth to display the population grid. Choropleth maps are more than just polygon geometries, which could be displayed as a folium.features.GeoJson layer, like we used for the address points above. Rather, this class takes care of categorizing data, adding a legend, and handling a few more small tasks to quickly create beautiful thematic maps.

The class expects an input dataset that has an explicit, str-type, index column, as it treats the geospatial input and the thematic input as separate datasets that need to be joined (see below for how we specify both geo_data and data).

A good approach to create such a column is to copy the data frame’s index into a new column, for instance, id.

コロプレスマップ(階級区分図)のインデックス列について
私たちは、人口グリッドを表示するために、folium.Choroplethを使います。コロプレスマップは単なるポリゴンの集まり以上のもので、上記のポイントのレイヤーの表示で使ったように、folium.features.GeoJsonのレイヤーとして表示されます。むしろ、きれいで意味のある地図を作るために、このクラスは、データを分類し、凡例を追加し、他にもいくつかのことができます。

このクラスは、地理空間データと主題となるデータ(これらは内部で結合する必要がある)を別々に扱います。そのため、データは明示的に文字列型のインデックス列を含むことを期待しています。(geo_data(地理空間データ)とdata(主題となるデータ)を明示する方法については、以下のコードを見てください)

インデックス列を作るための良いアプローチは、データフレームのインデックスを新しい列(例:id列)にコピーすることです。

ということで、インデックスをid列にコピーします。

population_grid["id"] = population_grid.index.astype(str)
population_grid.head()

image.png

なお、population_grid.indexは、pandas.core.indexes.range.RangeIndexという特殊な型です。なので、astype(str)で、pandas.Indexにしています。
image.png

Now we can create the polygon choropleth layer, and add it to a map object. Due to the slightly complex architecture of Folium, we have to supply a number of parameters:

  • geo_data and data, the geospatial and thematic input data sets, respectively. Can be the same geopandas.GeoDataFrame.
  • columns: a tuple of the names of relevant columns in data: a unique index column, and the column containing thematic data
  • key_on: which column in geo_data to use for joining data (this is basically identical to columns, except it’s only the first value)

では、ポリゴンのコロプレスマップ(階級区分図)のレイヤーを作ります。そして、そのレイヤーを地図に追加します。Foliumのアーキテクチャーはちょっとだけ複雑なので、いくつかのパラメータを用意する必要があります。

  • geo_data:地理空間データ、geopandas.GeoDataFrame型でも良い。
  • data:主題となるデータ、DataFrameSeries。今回はgeo_dataと同じでよい。(なぜなら地理空間データと主題となるデータが同じDataFrameに含まれているから。
  • columnsdataの列のうち、関連を持たせる列の名前をタプルで指定、同じ列名は入れない
  • key_ongeo_dataの列のうち、dataと結合するために使う列を指定(基本的にcolumnsと同じだが、列は一つだけ指定する)
interactive_map = folium.Map(
    location=(60.17, 24.94),
    zoom_start=12
)

population_grid_layer = folium.Choropleth(
    geo_data=population_grid,
    data=population_grid,
    columns=("id", "population"),
    key_on="feature.id"
)
population_grid_layer.add_to(interactive_map)

interactive_map

image.png

さて、folium.Choropleth()メソッドの引数key_onに指定している"feature.id"とは何者でしょうか。

最初に触れたとおり、Foliumは、geoJSONとしてデータを処理します。言い換えると、引数geo_dataで指定した地理空間データは、geoJSONとして処理されます。

image.png

で、今回は、geoJSONのfeature(地物)毎のidを、population_grididと結合したいので、key_on="feature.id"となります。

To make the map slightly nicer, let’s still request more categories (bins), change the colour range (using fill_color), set the line thickness to zero, and add a layer name to the legend:

この地図を少しだけよくするために、binsで分類を追加(9分類)、fill_colorでカラーレンジを変更、枠線の幅を0に、そして、レイヤーの名前を凡例に追加します。

interactive_map = folium.Map(
    location=(60.17, 24.94),
    zoom_start=12
)

population_grid_layer = folium.Choropleth(
    geo_data=population_grid,
    data=population_grid,
    columns=("id", "population"),
    key_on="feature.id",

    bins=9,
    fill_color="YlOrRd",
    line_weight=0,
    legend_name="Population, 2020",

    highlight=True
)
population_grid_layer.add_to(interactive_map)

interactive_map

image.png

色味が変わりました。またポリゴンの枠線が消えてすっきりとしました。

ちょっと拡大してみましょう。
image.png

YlOrRdですので、黄色からオレンジ色、そして赤色となり、それが9分類で、凡例も入っていることが確認できます。

https://matplotlib.org/stable/users/explain/colors/colormaps.html
image.png

Add a tooltip to a choropleth map

In such an interactive map, it would be nice to display the value of each grid cell polygon when hovering the mouse over it. Folium does not support this out-of-the-box, but with a simple trick, we can extend its functionality: We add a transparent polygon layer using a ‘basic‘ folium.features.GeoJson, and configure it to display tooltips.

インタラクティブマップでは、マウスホバーしたグリッドセルの値を表示するほうが良いでしょう。Foliumの標準機能(out-of-the-box)では、これはサポートされていません。
しかし、簡単な仕掛けで実現できます。「基本」のfolium.features.GeoJsonを使って、透明のポリゴンレイヤーを追加し、それをツールチップとして表示するように設定します。

We can keep the map we created above, and simply add another layer to it.

上記で作成した地図はそのままに、単純に別のレイヤーを追加しましょう。

# folium GeoJson layers expect a styling function,
# that receives each of the map’s feature and returns
# an individual style. It can, however, also return a
# static style:
def style_function(feature):
    return {
        "color": "transparent",
        "fillColor": "transparent"
    }


# More complex tooltips can be created using the
# `folium.features.GeoJsonTooltip` class. Below, we use
# its most basic features: `fields` specifies which columns
# should be displayed, `aliases` how they should be labelled.
tooltip = folium.features.GeoJsonTooltip(
    fields=("population",),
    aliases=("Population:",)
)


tooltip_layer = folium.features.GeoJson(
    population_grid,
    style_function=style_function,
    tooltip=tooltip
)
tooltip_layer.add_to(interactive_map)

interactive_map

folium.features.GeoJsonでツールチップのレイヤーを生成する際に、引数style_functionに、地物の色を透明にする関数style_function()を指定することで、透明のレイヤーを実現しています。また、引数tooltipに、生成したfolium.features.GeoJsonTooltipを指定することで、ツールチップとして文言が表示されるようにしています。

image.png

では、最も赤色なポリゴンにマウスを持っていきましょう。

image.png

良さそうですね。ツールチップとして、設定したpopulationが表示されています。

tooltip = folium.features.GeoJsonTooltip(
    fields=("population",),
    aliases=("Population:",)
)

Python packages for interactive (web) maps
Folium is just one of many packages that provide an easy way to create interactive maps using data stored in (geo-)pandas data frames. Other interesting libraries include:

  • GeoViews
  • Mapbox GL for Jupyter
  • Bokeh
  • Plotly Express
  • and many more.

Some of these packages are covered in the course Cartographic visualizations in GIS.

インタラクティブな(Web)地図用のPythonのパッケージ
Foliumは、pandasやGeoPandasのデータを使ってインタラクティブな地図を作る簡単な方法を提供する、数あるパッケージのうちの一つです。ほかにも面白いライブラリとしては以下があります。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?