国土数値情報のGISデータをsfで処理するときのメモ。
単純に読み込むだけならこう:
tmp_zip <- tempfile(fileext = ".zip") tmp_zipdir <- tempfile() curl::curl_download('http://nlftp.mlit.go.jp/ksj/gml/data/P12/P12-14/P12-14_05_GML.zip', destfile = tmp_zip) unzip(tmp_zip, exdir = tmp_zipdir) layers <- sf::st_layers(tmp_zipdir) d <- sf::read_sf(tmp_zipdir, layer = layers$name[1])
なんですが、Windowsだとこれは以下のように文字化けして見えます。実際には文字化けではなくて、Shift_JISの文字列にUTF-8という文字コードの指定が誤ってついているだけで、中に入っているデータ(バイト列)は正しいです。
d #> Simple feature collection with 621 features and 7 fields #> geometry type: MULTIPOINT #> dimension: XY #> bbox: xmin: 139.7046 ymin: 38.95984 xmax: 140.8945 ymax: 40.46308 #> epsg (SRID): NA #> proj4string: +proj=longlat +ellps=GRS80 +no_defs #> # A tibble: 621 x 8 #> P12_001 P12_002 P12_003 #> <int> <chr> <chr> #> 1 10001 "\u008fH\u0093c\u008a<U+0193>\u0095\u0082<U+0702>\u0082\xe8" 05 #> 2 10002 "\u008fH\u0093c\u008es\u0091\xe5\u0090X\u008eR\u008c\xf6\u0089\u0080" 05 #> 3 10003 "\u008fH\u0093c\u008es\u0089\u0516\u060a<U+03CC>\xf5\u0094_\u0089\u0080" 05 #> 4 10004 "\u008fH\u0093c\u008es\u0095l\u0093c\u0090X\u0097ё\u008d\u008d\u0087\u008c\xf6\u0089\u0080" 05 #> 5 10005 "\u008e<U+00A9>\u0091R\u0089<U+020A>w\u008aw\u008fK\u008a\xd9" 05 #> 6 10006 "\u008fH\u0093c\u008es\u0095<U+00B6>\u0089<U+00BB>\u0089\xef\u008a\xd9" 05 #> 7 10007 "\u008fH\u0093c\u008c<U+00A7>\u008e\u0099\u0093<U+00B6>\u0089\xef\u008a\xd9" 05 #> 8 10008 "\u008c\xfc\u0095l\u0089^\u0093<U+00AE>\u008c\xf6\u0089\u0080\u0096<U+C2C5>\u008dL\u008f\xea" 05 #> 9 10009 "\u008fH\u0093c\u008c<U+00A7>\u0097<U+00A7>\u0091\u008d\u008d\u0087\u0083v\u0081[\u0083\u008b" 05 #> 10 10010 "\u008e\xed\u0091\xf2\u0083\u008a\u0083\u0093\u0083S\u0089\u0080" 05 #> # ... with 611 more rows, and 5 more variables: P12_004 <chr>, P12_005 <chr>, P12_006 <chr>, P12_007 <int>, geometry <S3: #> # sfc_MULTIPOINT>
これを一気に変換するには、dplyr;;mutate_if()
とかを使います。しかし…
dplyr::mutate_if(d, is.character, iconv, from = "CP932") #> # A tibble: 621 x 8 #> P12_001 P12_002 P12_003 P12_004 P12_005 P12_006 P12_007 geometry #> <int> <chr> <chr> <chr> <chr> <chr> <int> <S3: sfc_MULTIPOINT> #> 1 10001 秋田竿燈まつり 05 05201 年中行事 秋田市旭北 1 <S3: sfc_MULTIPOINT> #> 2 10002 秋田市大森山公園 05 05201 ‐ 秋田市浜田 4 <S3: sfc_MULTIPOINT> #> 3 10003 秋田市花木観光農園 05 05201 ‐ 秋田市雄和向野字桧谷地1 6 <S3: sfc_MULTIPOINT> #> 4 10004 秋田市浜田森林総合公園 05 05201 ‐ 秋田市浜田 1 <S3: sfc_MULTIPOINT> #> 5 10005 自然科学学習館 05 05201 ‐ 秋田市東通仲町4-1 6 <S3: sfc_MULTIPOINT> #> 6 10006 秋田市文化会館 05 05201 ‐ 秋田市山王7-3-1 6 <S3: sfc_MULTIPOINT> #> 7 10007 秋田県児童会館 05 05201 ‐ 秋田市山王中島町1-2 6 <S3: sfc_MULTIPOINT> #> 8 10008 向浜運動公園野球広場 05 05201 ‐ 秋田市新屋町字砂奴寄4-6 4 <S3: sfc_MULTIPOINT> #> 9 10009 秋田県立総合プール 05 05201 ‐ 秋田市新屋町字砂奴寄4-6 4 <S3: sfc_MULTIPOINT> #> 10 10010 種沢リンゴ園 05 05201 ‐ 秋田市雄和種沢熊野堂272 1 <S3: sfc_MULTIPOINT> #> # ... with 611 more rows
なんと、sf
オブジェクトではなくなってしまいます。
これはなぜかというと、sf
用のmutate()
のメソッドが読み込まれていないからです。以下のようにいちどsf
パッケージ自体を読み込むとmutate.sf()
が使われるようになり、sf
オブジェクトが返ってきます。
library(sf) #> Linking to GEOS 3.6.1, GDAL 2.2.0, proj.4 4.9.3 dplyr::mutate_if(d, is.character, iconv, from = "CP932") #> Simple feature collection with 621 features and 7 fields #> geometry type: MULTIPOINT #> dimension: XY #> bbox: xmin: 139.7046 ymin: 38.95984 xmax: 140.8945 ymax: 40.46308 #> epsg (SRID): NA #> proj4string: +proj=longlat +ellps=GRS80 +no_defs #> # A tibble: 621 x 8 #> P12_001 P12_002 P12_003 P12_004 P12_005 P12_006 P12_007 geometry #> <int> <chr> <chr> <chr> <chr> <chr> <int> <simple_feature> #> 1 10001 秋田竿燈まつり 05 05201 年中行事 秋田市旭北 1 <MULTIPOINT (...> #> 2 10002 秋田市大森山公園 05 05201 ‐ 秋田市浜田 4 <MULTIPOINT (...> #> 3 10003 秋田市花木観光農園 05 05201 ‐ 秋田市雄和向野字桧谷地1 6 <MULTIPOINT (...> #> 4 10004 秋田市浜田森林総合公園 05 05201 ‐ 秋田市浜田 1 <MULTIPOINT (...> #> 5 10005 自然科学学習館 05 05201 ‐ 秋田市東通仲町4-1 6 <MULTIPOINT (...> #> 6 10006 秋田市文化会館 05 05201 ‐ 秋田市山王7-3-1 6 <MULTIPOINT (...> #> 7 10007 秋田県児童会館 05 05201 ‐ 秋田市山王中島町1-2 6 <MULTIPOINT (...> #> 8 10008 向浜運動公園野球広場 05 05201 ‐ 秋田市新屋町字砂奴寄4-6 4 <MULTIPOINT (...> #> 9 10009 秋田県立総合プール 05 05201 ‐ 秋田市新屋町字砂奴寄4-6 4 <MULTIPOINT (...> #> 10 10010 種沢リンゴ園 05 05201 ‐ 秋田市雄和種沢熊野堂272 1 <MULTIPOINT (...> #> # ... with 611 more rows
パッケージでは@importFrom
しておく必要があります。
追記(2017/08/29):
パッケージの名前空間に@importFrom
するだけでは不十分で、ユーザから見える場所、つまりグローバル環境に@export
しておかないとだめでした。これはdplyr::mutate()
のメソッドディスパッチが起こるのはkokudosuuchiの中ではなくdplyrの中だからです。具体的にはこんな感じ:
#' @importFrom sf mutate.sf #' @export sf::mutate.sf
さらに追記(2017/08/29):
これは、データがShift_JISだとわかっているなら、読み込むときに文字コードを指定すれば済む話ではあります。
sf::read_sf(tmp_zipdir, layer = layers$name[1], options = "ENCODING=CP932")