Shapefileで沖縄を移動

Shapefileで特定の地域を動かすということを考える.

地図の作成にはshapefileが有用であり,Rでもrmapなどのpackageを使うことがある.またESRI(https://www.esrij.com/products/japan-shp/)が提供するデータをshapefile packageでRにimportし,R上で地図を描くことも可能である.

日本の地図を描くことを考えよう.日本は細長い島国であり,そのままの地理情報を使うと全体に合わせてwindowを作る必要があるため,各地域が小さくなり見づらくなる.天気予報で沖縄が日本海に移動しているように,特定の地域を移動することで,より見やすい地図を描くことができるわけである.

今回はこの天気予報でよく見かける地図をR上で作成することを考える.

必要なもの:
1.Shapefile:上のESRIのページからダウンロード
2.R本体(Rstudioがおススメ)
3.必要なRのパッケージ:maptoolsshapefile

まずは必要なデータをR上にimportするところから始める.そのためには,Shapefileが格納されているフォルダーを指定する必要がある.ここでは,WD_shapefileをShapefileへのpathとする(もしもDesktop上にあるのであれば,”C:/Users/user/Desktop/”).setwd関数でデータの保存先をworking directoryに指定する.必要なデータをreadShapePoly関数で読み込んだ後は,単純にplot関数で日本地図が描かれる.

# load required packages
library(maptools)
library(shapefiles)

# set working directory and import datasets
setwd(WD_shapefile)
jpn1 <- readShapePoly("JPN_adm1.shp")

par(mar=c(0,0,0,0)) # set margin to zero
plot(jpn1)

mar=c(0,0,0,0)で上下左右の余白を0に設定しても,shapefileのデータをそのまま用いると,上のようなfigureとなり白い部分が多い. では,沖縄を日本海に移動しよう.

沖縄の移動のためには,まず,shapefileの中で沖縄が格納されている場所を特定する必要がある. ID_1には,アルファベット順に番号をふったID(1が愛知,2が秋田)が入っているので,沖縄の番号がわかればID_1==32というように直接指定してもよい. わからない場合は,NAME_1に都道府県名があるので,これで沖縄の場所を探して,該当するID_1を引っ張って来ることになる. 引っ張ってきたIDをNとし,沖縄のpolygonデータをPrefに格納,length(Pref)でpolygonデータの数をLとして保存する. ここで,polygonデータの数は,各都道府県がいくつのpolygonデータで構成されているかに該当する.

例えば長野や岐阜は領域が1つのpolygonデータによって記述できるので1になる. 一方で,沖縄や鹿児島のように島を複数持つ県では,polygonデータを分けておかないといけない(一つのデータとして持っていると,plotする際に合体させられてしまう)ので,このLが大きい値になる(実際,L=114,つまり沖縄は114のpolygonデータにより構成されている).

各polygonデータは経度と緯度の2つのベクトルを持ち,これに数字を足すことによって地図上で場所を移動できる. 下のプログラムでは,coords[,1]でx座標にあたる緯度に5を足し,Coords[,2]でy座標にあたり経度に17を足して,日本海に沖縄を移動させている.

N    <- jpn1$ID_1[(jpn1$NAME_1 == "Okinawa")]
Pref <- jpn1@polygons[[N]]@Polygons
L    <- length(Pref)
for (i in 1:L){
  Pref_i  <- Pref[[i]]
  Coord_i <- Pref_i@coords
  jpn1@polygons[[N]]@Polygons[[i]]@coords[,1] <- Coord_i[,1] + 5
  jpn1@polygons[[N]]@Polygons[[i]]@coords[,2] <- Coord_i[,2] + 17
}

今度は都道府県で色分けしてみる.Rにはrainbow()という関数が備わっており,虹色を指定した数で分割してくれる.ここでは47都道府県ということでrainbow(47)で色を指定した.さらにsegments関数を使って,地図の一角にラインを追加している.

Col <- rainbow(47)
par(mar=c(0,0,0,0))
plot(jpn1, xlim=c(128, 146), ylim=c(30, 46), col=Col)
segments(128.5,40.8,137.0,40.8,col="gray70")
segments(137.0,45.0,137.0,40.8,col="gray70")

沖縄が移動できていることが確認できる.ただ,移動はできたもののエリアが小さく色の判別が難しい.例えば人口密度で各都道府県を塗分けたいと思った場合,上のようなfigureでは意図したものが伝わらないだろう.

そこで次に沖縄を拡大することを考える. 基本的な考え方は移動する場合と同じで,沖縄を構成するpolygonデータの緯度・経度に数字を四則演算を使って変換する.

さらに上のプログラムでは,愛知から順番にアルファベット順で色をふっていったが,ここではこの順番を変更し,北から南にグラデーションをつけることを考える. そのためには,まず北海道から順番に色の配列を作り,それをアルファベット順に並べかえる必要がある.

setwd(WD_shapefile)
jpn1 <- readShapePoly("JPN_adm1.shp")
N    <- jpn1$ID_1[(jpn1$NAME_1 == "Okinawa")]
Pref <- jpn1@polygons[[N]]@Polygons
L    <- length(Pref)
for (i in 1:L){
  Pref_i  <- Pref[[i]]
  Coord_i <- Pref_i@coords
  # move
  jpn1@polygons[[N]]@Polygons[[i]]@coords[,1] <- Coord_i[,1] + 5
  jpn1@polygons[[N]]@Polygons[[i]]@coords[,2] <- Coord_i[,2] + 17
  # expand
  jpn1@polygons[[N]]@Polygons[[i]]@coords[,1] <- Coord_i[,1] * 3.5 - 128*2.46
  jpn1@polygons[[N]]@Polygons[[i]]@coords[,2] <- Coord_i[,2] * 3.5 - 49
}
# prepare color
PrefName <- c("Aichi", "Akita", "Aomori", "Chiba", "Ehime", "Fukui", "Fukuoka", "Fukushima", "Gifu", "Gumma",
              "Hiroshima", "Hokkaido", "Hyogo", "Ibaraki", "Ishikawa", "Iwate", "Kagawa", "Kagoshima", 
              "Kanagawa", "Kochi", "Kumamoto", "Kyoto", "Mie", "Miyagi", "Miyazaki", "Nagano", "Nagasaki", 
              "Nara", "Niigata", "Oita", "Okayama", "Okinawa", "Osaka", "Saga", "Saitama", "Shiga", "Shimane", 
              "Shizuoka", "Tochigi", "Tokushima", "Tokyo", "Tottori", "Toyama", "Wakayama", "Yamagata", 
              "Yamaguchi", "Yamanashi")
Order_EN  <- 1:47
Order_JIS <- c(22, 4, 2, 12, 37, 20, 40, 7, 23, 10, 34, 1, 28, 8, 19, 3, 36, 46, 14, 39, 43, 26, 24, 5, 45, 16,
               42, 29, 17, 44, 33, 47, 27, 41, 11, 25, 32, 21, 9, 38, 13, 31, 18, 30, 6, 35, 15)
PrefOrder <- data.frame(PrefName = PrefName, Order_EN = Order_EN, Order_JIS = Order_JIS)
PrefOrder     <- PrefOrder[order(PrefOrder$Order_JIS),]
PrefOrder$Col <- rainbow(47)
PrefOrder     <- PrefOrder[order(PrefOrder$Order_EN),]
# plot by ordered-color
par(mar=c(0,0,0,0))
plot(jpn1, xlim=c(128, 146), ylim=c(30, 46), col=PrefOrder$Col)
segments(128.5,40.8,137.0,40.8,col="gray70")
segments(137.0,45.0,137.0,40.8,col="gray70")

残念ながらRには都道府県名を並び替える仕組みがないため,自分で用意することになる.上の例ではPrefNameとして都道府県名の列を作り,Order_ENでアルファベット順,Order_JISとして北から南への順番をふって,data.frameの形で保存してある. 毎回このようなプログラムを書くのは手間なので,対応表をcsvファイルなどで作っておいて,外から読み込む形のほうが望ましいかもしれない.

また,xlim=c(128,146)で地図を表示するエリアを切ったが,沖縄の島の一部が日本海上に点在している状況になってしまっている. 沖縄本島のみを地図に残す形でこれは対応可能だが,polygonデータを合体させる必要などがあるため,これは別の記事で.

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です