ggplot2 パッケージでの地図出力でポイントとラベルの重なりを防ぐ方法

概要
ggplot2 パッケージで sf オブジェクトを地図として出力するとき、ポイントとそのラベルが重ならないよう出力したければ、ggrepel パッケージを使えばよい。

はじめに

ggplot2 パッケージを使って sf オブジェクトから地図を出力する際、ポイントで表される地物とそのラベルの両方を出力したいことがある。このとき何も考えないと、ポイントと点が重なってしまう。

例えば、以下の地図では横浜市の市役所・区役所のポイント(赤色)がそのラベルと重なってしまっている。

2014年時点の横浜市の市役所・区役所の位置。位置を示す赤いポイントとラベルが重なってしまっている。
2014年時点の横浜市の市役所・区役所の位置。位置を示す赤いポイントとラベルが重なってしまっている。

重ならないようにするには、ggrepel パッケージを使えば良い。

2014年時点の横浜市の市役所・区役所の位置。位置を示す赤いポイントとラベルが重ならずに済んでいる。
2014年時点の横浜市の市役所・区役所の位置。位置を示す赤いポイントとラベルが重ならずに済んでいる。

ggrepel パッケージは、sf オブジェクトの出力時以外でも、ggplot2 での重なりを防ぐために使うことができる。例えば、「ggplot2 パッケージによる可視化の際のラベルの重なりを防ぐ」には、散布図でのラベルの重なりを防いだ例が載っている。

今回使用するシェープファイル

今回は、国土交通省の国土数値情報から手に入る以下の2つのシェープファイルを用いる。

これらをダウンロードして展開しておく。これらのファイルは神奈川県の全自治体の情報が入っている。後ほど、R上で横浜市の部分だけ抽出することになる。

ポイントとラベルが重ならないように地図を出力するコード

R で、ポイントとラベルが重ならないように地図を出力するコードは以下の通り。

# 必要なパッケージの読み込み
library("tidyverse")
library("sf")

# 神奈川県の行政区域データ(ポリゴン)のシェープファイル読みこみ
yokohama_basemap <- read_sf("./N03-140401_14_GML/N03-14_14_140401.shp") %>%
  filter(N03_003 == "横浜市") # 横浜市のデータのみ残す
# 神奈川県の市区町村役場データ(ポイント)のシェープファイル読みこみ
yokohama_gov <- read_sf("./P34-14_14_GML/P34-14_14.shp", options = c("ENCODING=CP932")) %>%
  filter(str_starts(P34_004, "横浜市")) # 横浜市のデータのみ残す

# ggplot2 パッケージによる地図の出力
ggplot() + 
  # 横浜市の行政区(ポリゴン)の出力
  geom_sf(data = yokohama_basemap) +
  # 横浜市の市役所・区役所(ポイント)の出力
  geom_sf(data = yokohama_gov, 
          colour = "red",
          size = 1.5) + 
  # 横浜市の市役所・区役所の名称のラベルの出力
  ggrepel::geom_text_repel(
    data = yokohama_gov,
    aes(label = P34_003, geometry = geometry),
    stat = "sf_coordinates", 
    # ラベルの文字の大きさの設定
    size = 3,
    # ラベルからの引き出し線の設定
    min.segment.length = 0, 
    segment.color = "gray50") +
  theme_minimal()

上記のコードでは、まず必要なパッケージ [3] を読みこんだ上で、ダウンロードしてきたシェープファイルを読みこんでいる。行政区域データの方は filter(N03_003 == "横浜市") で横浜市だけを抽出している。N03_003 列に市町村名が入っているので、これで横浜市だけ抽出できるのだ。また、市区町村役場データの方は filter(str_starts(P34_004, "横浜市")) で横浜市だけを抽出している。P34_004 列に役所の住所が「横浜市中区港町1-1」 [4] のように入っているので、冒頭が「横浜市」であるところを抽出しているのだ。

その後、コードの13行目(ggplot() +)以降で、地図を出力している。

  1. 15行目(geom_sf(data = yokohama_basemap))で横浜市の行政区のポリゴンを出力。
  2. 17行目(geom_sf(data = yokohama_gov,)から19行目までで、市役所・区役所の存在する地点に、赤いポイントを出力。
  3. 21行目(ggrepel::geom_text_repel()から29行目で、市役所・区役所の名称のラベルを出力。ここでggrepelパッケージの機能を使い、重ならないようにしている。
    • geometry = geometryというのは、図中に出力する位置は、yokohama_govの中の geometry 列の情報を使ってくださいという意味。
    • stat = "sf_coordinates" は、sf オブジェクトの経度・緯度の情報を良いあんばいに取り出す方法を使います、という意味。geom_sf()関数ではデフォルトで stat = "sf_coordinates" となっているのでわざわざ書く必要がないのだが、ggrepel::geom_text_repel()関数ではデフォルトでないので明示が必要。
  4. 最後の theme_minimal() で図のスタイルをシンプルなものにする。

参考:ポイントとラベルが重なった地図を出力するコード

最後に、参考までに、この記事の冒頭で挙げた地図、すなわちポイントとラベルが重なってしまっている地図を出力するコードを挙げておく。

# 必要なパッケージの読み込み
library("tidyverse")
library("sf")

# 神奈川県の市区町村(ポリゴン)のシェイプファイル読みこみ
yokohama_basemap <- read_sf("./N03-140401_14_GML/N03-14_14_140401.shp") %>%
  filter(N03_003 == "横浜市") # 横浜市のデータのみ残す
# 神奈川県の市区町村役場等(ポイント)のシェイプファイル読みこみ
yokohama_gov <- read_sf("./P34-14_14_GML/P34-14_14.shp", options = c("ENCODING=CP932")) %>%
  filter(str_starts(P34_004, "横浜市")) # 横浜市のデータのみ残す

# ggplot2 パッケージによる地図の出力
ggplot() + 
  # 横浜市の行政区(ポリゴン)の出力
  geom_sf(data = yokohama_basemap) +
  # 横浜市の市役所・区役所(ポイント)の出力
  geom_sf(data = yokohama_gov, colour = "red",
          size = 1.5) + 
  # 横浜市の市役所・区役所の名称のラベルの出力
  geom_sf_text(data = yokohama_gov,
               aes(label = P34_003), size = 3) +
  theme_minimal()
脚注
  1. ダウンロード対象となるファイルは、N03-140401_14_GML.zip []
  2. ダウンロード対象となるファイルは、P34-14_14_GML.zip []
  3. tidyversesf の2つ。なお、地図を描く際は、ggplot2 パッケージを使っているが、このパッケージは idyverse を読みこむ際にいっしょに読みこまれる。 []
  4. この住所は2014年時点の横浜市役所の住所である。その後移転し、2022年現在は「横浜市中区本町6丁目50番地の10」にある。 []