読者です 読者をやめる 読者になる 読者になる

Rから国土数値情報ダウンロードサービス Web APIを使うパッケージをつくりました

R GIS 国土数値情報 kokudosuuchi

(この記事はFOSS4G Advent Calendar 2015 9日目の記事です)

RからGRASSを使います、と宣言していたんですが、GIS初心者すぎて挫折しました。。

即席でつくったパッケージの紹介でお茶を濁します。すみません…

国土数値情報ダウンロードサービスとは

国土に関する基礎的なGISデータセットをダウンロードできるサービスです。データの形式はJPGISという独自形式や、ESRI Shapefileなどがあります。

国土数値情報ダウンロードサービス

とてもありがたいサービスなんですが、いかんせんUIがイケてなくて欲しい情報探しづらいのが難点です。そこで、APIです。

国土数値情報ダウンロードサービスWeb APIとは

2014年12月からは、国土数値情報ダウンロードサービスの情報をXML形式で取得できるAPIが試験的に提供されています。

Web API(試行版)

今のところ、利用できるのは、国土数値情報の概要情報を取得するAPIと、国土数値情報のZIPファイルダウンロードURLを取得するAPIです。検索できる形式も今はJPGISに限られています。

これをRから使うパッケージをつくりました。

国土数値情報ダウンロードサービスの利用規約

で、パッケージの紹介をするわけですが、その前に。国土数値情報ダウンロードサービスのAPIや、APIから取得したURLでダウンロードできるデータを利用する際は以下の利用規約を確認してからお願いします。

kokudosuuchiパッケージ

つくりました。

インストール

Githubからインストールします。

devtools::install_github("yutannihilation/kokudosuuchi")

使い方

kokudosuuchiパッケージを読み込みます。

library(kokudosuuchi)
#> このサービスは、「国土交通省 国土数値情報(カテゴリ名)」をもとに加工者が作成
#> 以下の国土数値情報ダウンロードサービスの利用約款をご確認の上ご利用ください:
#> 
#> http://nlftp.mlit.go.jp/ksj/other/yakkan.html

まずは国土数値情報の概要情報を取得するAPIの方を使ってみます。getKSJSummary()という関数を使います。(パラメータもいくつか指定できますが、今のところはすべて指定できるものが1種類しかないのでデフォルトのままで問題ありません)

すると、APIへの問い合わせ結果を以下のようにtbl_dfにして返してくれます。

library(dplyr)

d <- getKSJSummary()
d
#> Source: local data frame [100 x 5]
#> 
#>    identifier                title           field1       field2 areaType
#>         (chr)                (chr)            (chr)        (chr)    (chr)
#> 1         A03   三大都市圏計画区域         政策区域     大都市圏        2
#> 2         A09             都市地域 国土(水・土地)     土地利用        3
#> 3         A10         自然公園地域             地域     保護保全        3
#> ...

ここで、identifierは各データを表す識別子です。次のAPIで使います。field1,field2はカテゴリです。areaTypeは、「1:全国のみ」「2:三大都市圏で分類」「3:全国・都道府県で分類」「4:メッシュで分類」の4種類があります。この種類によって次のAPIで指定するパラメータが違います。

次に、国土数値情報のZIPファイルダウンロードURLを取得するAPIの方を使ってみます。getKSJURL()という関数を使います。こちらのAPIには、いくつかのパラメータが指定できます。(詳しくは仕様書を参照)

たとえば、大阪府の河川に関するデータが欲しいとします。まず、河川のデータのidentifierを探します。

filter(d, stringr::str_detect(title, "河川"))
#> Source: local data frame [1 x 5]
#> 
#>   identifier title           field1 field2 areaType
#>        (chr) (chr)            (chr)  (chr)    (chr)
#> 1        W05  河川 国土(水・土地)   水域        3

ここでareaTypeが3なので、指定するパラメータはprefCodeです。都道府県コードは毎回探すのがめんどくさいので、これもパッケージに入れておきました。

data("KSJprefCodes")

filter(KSJprefCodes, prefName == "大阪府")
Source: local data frame [1 x 2]

  prefCode prefName
     (dbl)    (chr)
1       27   大阪府

27ですね。

では、指定するパラメータがわかったところでさっそくAPIに投げてみます。

getKSJURL("W05", prefCode = 27)
#> Source: local data frame [1 x 9]
#> 
#>   identifier title            field  year areaType areaCode datum                                                        zipFileUrl
#>        (chr) (chr)            (chr) (chr)    (chr)    (chr) (chr)                                                             (chr)
#> 1        W05  河川 国土(水・土地)  2009        3       27     1 http://nlftp.mlit.go.jp/ksj/gml/data/W05/W05-09/W05-09_27_GML.zip
#>   zipFileSize
#>         (chr)
#> 1      1.56MB

ありました。このURLからZipをダウンロードすれば、河川のデータが手に入ります。

河川をプロット

せっかくなので、このデータを使ってみます。APIで検索できるのはJPGIS 2.1のファイルのみ、と書かれていますが同じZIPにShapefileも入っていることもあります。河川データとかはそれなので、さくっとRで読み込むことができます。

データ読み込み

まずは先ほどのURLからデータをダウンロードしてきます。

W05file <- tempfile(fileext = "zip")
download.file("http://nlftp.mlit.go.jp/ksj/gml/data/W05/W05-09/W05-09_27_GML.zip", destfile = W05file)
#> trying URL 'http://nlftp.mlit.go.jp/ksj/gml/data/W05/W05-09/W05-09_27_GML.zip'
#> Content type 'application/zip' length 1633167 bytes (1.6 MB)
#> downloaded 1.6 MB
#> 

W05dir <- tempdir()
unzip(W05file, exdir = W05dir)

これをrgdalパッケージで読み込みます。レイヤーは二つありますが、今回はW05-09_27-g_Streamの方を使います。

library(rgdal)
ogrListLayers(W05dir)
#> [1] "W05-09_27-g_RiverNode" "W05-09_27-g_Stream"   
#> attr(,"driver")
#> [1] "ESRI Shapefile"
#> attr(,"nlayers")
#> [1] 2

river <- readOGR(W05dir, "W05-09_27-g_Stream")
#> OGR data source with driver: ESRI Shapefile 
#> Source: "C:\Users\user1\AppData\Local\Temp\RtmpmqbOOY", layer: "W05-09_27-g_Stream"
#> with 2125 features
#> It has 10 fields

追記(2016//11/3):

readOGR()にはencoding引数があったので、以下のように指定すれば、このあとの自分でEncoding()を設定する手順は必要はありませんでした。すみません。

river <- readOGR(W05dir, "W05-09_27-g_Stream", encoding = "UTF-8")

データを覗いてみる

データをちょっと覗いてみます。

knitr::kable(head(river@data))
W05_001 W05_002 W05_003 W05_004 W05_005 W05_006 W05_007 W05_008 W05_009 W05_010
0 860603 8606030000 4 繧ォ繧、隹キ 4 1 #gb03_2700942 #gb03_2701226 #gb03_2700942 #gb03_2701226
1 860604 8606040044 2 蟆サ辟。蟾㤼㹤 3 1 #gb03_2700011 #gb03_2702076 #gb03_2700008 #gb03_2700032
2 860604 8606040044 2 蟆サ辟。蟾㤼㹤 3 1 #gb03_2700011 #gb03_2702076 #gb03_2700032 #gb03_2702076
3 270001 2700010002 4 隘ソ蟾㤼㹤 3 1 #gb03_2701757 #gb03_2701450 #gb03_2701757 #gb03_2701756
4 860604 8606040001 1 豺蟾㤼㹤 1 1 #gb03_2701546 #gb03_2700000 #gb03_2701073 #gb03_2700000
5 860604 8606040001 1 豺蟾㤼㹤 1 1 #gb03_2701546 #gb03_2700000 #gb03_2701405 #gb03_2701073

ここで、カラム名W05_001とかよく分からない文字列になっています。これがどういう意味かを調べるには、今のところAPIでは完結しなくて、各データの詳細ページを見る必要があります。たとえば、河川データであれば以下です。

国土数値情報 河川データの詳細

順番的に、W05_003区間種別のようです。一級河川とか二級河川とか、そういう区分で見たければここでデータを分割するのがよさそうです。

それはそうと、Windowsで見るとW05_004が文字化けしてるっぽく見えるので修正しておきます。これは文字化けしてるように見えるだけで、変換したりしなくてもEncoding()を設定すれば終わりです。

l <- levels(river@data$W05_004)
Encoding(l) <- "UTF-8"
levels(river@data$W05_004) <- l

knitr::kable(head(river@data))
W05_001 W05_002 W05_003 W05_004 W05_005 W05_006 W05_007 W05_008 W05_009 W05_010
0 860603 8606030000 4 カイ谷 4 1 #gb03_2700942 #gb03_2701226 #gb03_2700942 #gb03_2701226
1 860604 8606040044 2 尻無川 3 1 #gb03_2700011 #gb03_2702076 #gb03_2700008 #gb03_2700032
2 860604 8606040044 2 尻無川 3 1 #gb03_2700011 #gb03_2702076 #gb03_2700032 #gb03_2702076
3 270001 2700010002 4 西川 3 1 #gb03_2701757 #gb03_2701450 #gb03_2701757 #gb03_2701756
4 860604 8606040001 1 淀川 1 1 #gb03_2701546 #gb03_2700000 #gb03_2701073 #gb03_2700000
5 860604 8606040001 1 淀川 1 1 #gb03_2701546 #gb03_2700000 #gb03_2701405 #gb03_2701073

川の名前が出てきました。

ggplot2で河川をプロット

詳細は割愛しますが、ggplot2で地図を描くには以下の記事が参考になります。下の公式wikiの情報はやや古いです。

やることは、broom::tidy()riverをdata.frameに変換して、元のriver@dataとマージするだけです。

library(broom)
library(ggplot2)

r <- tidy(river)

river@data %>%
  add_rownames("id") %>%
  inner_join(r, by = "id") %>%
  {
    ggplot(., aes(long, lat, group = group, colour = W05_003)) +
      geom_line() +
      coord_quickmap() +
      facet_wrap(~W05_003)
  }

f:id:yutannihilation:20151209020457p:plain

あんまり意味はないですが、等級別の河川のプロットが描けました。

まとめ

Rから国土数値情報ダウンロードサービス Web APIを使うパッケージをつくりました。使ってみて変なところがあれば、GithubのIssuesTwitterあたりでお知らせいただけるとうれしいです。

では、明日からも引き続きFOSS4G Advent Calendarの記事をお楽しみください。次はuriさんです。