Rで複数のシェープファイルを結合する
地図で可視化する際の行政界のシェープは、統計局のものをよく利用させてもらっています。↓以下参考。
e-Stat(統計局)で公開されているShapeファイルを、Rで表示する - Rプログラミングの小ネタ
統計局で公開されているシェープは比較的小さい単位に分かれています。例えば、福岡市だと、区単位(東区、博多区、中央区、南区、西区、城南区、早良区)の7つのシェープに分かれています。
こういうのをまとめて1つにしたい時ってありますよね。
QGISのようなGUIのあるGISソフトでやる方法もありますが、数が多くなるとしんどい。ということで、Rのスクリプトでシェープの結合をする方法を紹介します。
ざっくり言うと、readShapePolyで読み込んで、spRbindで結合させるだけなんですけどね。
でも、そう簡単にはいかない時があるんですよね。というのも、ポリゴンのIDがかぶっているとspRbindでエラーが出てしまう。例えば、東区のシェープの中のあるポリゴンに「1」というIDが付いていて、博多区のシェープの中のあるポリゴンにも「1」というIDが付いていると、この2つを結合させようとする際にエラーになってしまいます。
なので、東区のポリゴンはのIDは、"1.1", "1.2", "1.3", ...、博多区のポリゴンのIDは"2.1", "2.2", "2.3", ... みたいにリネームしたあとに、結合させましょうというのが、↓このスクリプトのポイントでございます。
↓あとは、おまけみたいなもんです。
ちゃんとくっついているかplotしてみます。ifelseでごちゃごちゃ書いているのは、区ごとに色分けするためです。
ややこしいのが海の部分で、ここを同じ色で塗りたいのですが、区によってMOJIの属性(通常は町丁目名が入っている)に「博多湾」と入っていたり、「博多港」と入っていたり、「水面」と入っていたり、NULLが入っていたりする。博多湾とか博多港は分かるけど、「水面」ってなんだよ。
あと、地図に文字をプロットするようなときには、文字が大きいと重なっちゃうし、小さいとつぶれてしまうことがよくあるので、PDFに出力するとベクタとして書き出せるので吉です。
↓こんな感じで表示されます。
↓PDFファイル自体も置いておきますね。
福岡市の行政界地図(PDFファイル)
e-Stat(統計局)で公開されているShapeファイルを、Rで表示する - Rプログラミングの小ネタ
統計局で公開されているシェープは比較的小さい単位に分かれています。例えば、福岡市だと、区単位(東区、博多区、中央区、南区、西区、城南区、早良区)の7つのシェープに分かれています。
こういうのをまとめて1つにしたい時ってありますよね。
QGISのようなGUIのあるGISソフトでやる方法もありますが、数が多くなるとしんどい。ということで、Rのスクリプトでシェープの結合をする方法を紹介します。
ざっくり言うと、readShapePolyで読み込んで、spRbindで結合させるだけなんですけどね。
でも、そう簡単にはいかない時があるんですよね。というのも、ポリゴンのIDがかぶっているとspRbindでエラーが出てしまう。例えば、東区のシェープの中のあるポリゴンに「1」というIDが付いていて、博多区のシェープの中のあるポリゴンにも「1」というIDが付いていると、この2つを結合させようとする際にエラーになってしまいます。
なので、東区のポリゴンはのIDは、"1.1", "1.2", "1.3", ...、博多区のポリゴンのIDは"2.1", "2.2", "2.3", ... みたいにリネームしたあとに、結合させましょうというのが、↓このスクリプトのポイントでございます。
library(maptools) # シェープのファイル名を取得 shape_files <- list.files(path="shape_folder", pattern=".*\\.shp", full.names=T) # 緯度経度、世界測地系 pj <- CRS("+proj=longlat +datum=WGS84") # ポリゴンのIDが重複しないように前処理したあと、 # リストに格納しておく shape_list <- list() # 空のリストを用意 for ( i in 1:length(shape_files) ) { # シェープの読み込み shp <-readShapePoly(shape_files[i], proj4string=pj) # id文字列のベクトルを作る ids <- paste(i, 1:length(shp@polygons), sep=".") # polygonsのIDを変更する for ( j in 1:length(shp@polygons) ) { shp@polygons[[j]]@ID <- ids[j] } # dataの行名もそれに対応して変更する row.names(shp@data) <- ids # リストに追加する shape_list <- c(shape_list, shp) } # リストに格納してある、シェープを結合する merged <- shape_list[[1]] for ( i in 2:length(shape_list) ) { merged <- spRbind(merged, shape_list[[i]]) } # シェープの書き出し writePolyShape(merged, "merge.shp")
↓あとは、おまけみたいなもんです。
ちゃんとくっついているかplotしてみます。ifelseでごちゃごちゃ書いているのは、区ごとに色分けするためです。
ややこしいのが海の部分で、ここを同じ色で塗りたいのですが、区によってMOJIの属性(通常は町丁目名が入っている)に「博多湾」と入っていたり、「博多港」と入っていたり、「水面」と入っていたり、NULLが入っていたりする。博多湾とか博多港は分かるけど、「水面」ってなんだよ。
あと、地図に文字をプロットするようなときには、文字が大きいと重なっちゃうし、小さいとつぶれてしまうことがよくあるので、PDFに出力するとベクタとして書き出せるので吉です。
library(RColorBrewer) cols <- brewer.pal(8, "Pastel2") merged$col <- ifelse ( merged$MOJI=="博多湾" | merged$MOJI=="博多港" | merged$MOJI=="水面" | is.na(merged$MOJI) , cols[1], ifelse ( merged$CSS_NAME=="東区" , cols[2], ifelse ( merged$CSS_NAME=="博多区", cols[3], ifelse ( merged$CSS_NAME=="中央区", cols[4], ifelse ( merged$CSS_NAME=="南区" , cols[5], ifelse ( merged$CSS_NAME=="西区" , cols[6], ifelse ( merged$CSS_NAME=="城南区", cols[7], ifelse ( merged$CSS_NAME=="早良区", cols[8], "NG" )))))))) pdf("out.pdf", family="Japan1GothicBBB", width=11.69, height=16.54) plot(merged, col=merged$col, lwd=0.1) text(merged$X_CODE, merged$Y_CODE, merged$MOJI, cex=0.1) dev.off()
↓こんな感じで表示されます。
![]() |
福岡市の行政界地図 |
↓PDFファイル自体も置いておきますね。
福岡市の行政界地図(PDFファイル)
コメント
コメントを投稿