国勢調査の調査区データに年齢階層別人口データを統合する
地図で見る統計(統計GIS)でダウンロードしたGISのデータに、年齢階層別人口のデータを統合して、GIS上で色分け表示できるようにする。
GISのデータのうち、いわゆるデータベースのデータは、dBASE方式の.dbfファイルとなっている。このファイル、2003までのExcelでは読み書きできたんだけれど、2007以降は読み込みのみになってしまったらしく、書き込みができない。
そこでRを使う。
まず、Rでdbfファイルの読み書きができるよう、foreignパッケージを読み込んでおく
>library(foreign)
まず、GISデータを読み込む。ここでは例として津市のデータを読み込む
次に、年齢階層別人口データを読み込むのだが、中のデータで、0は"-"が、秘匿値は"X"が入っている。この場合、Rで読み込むと、データ全体を数値として認識してくれないため、あらかじめエディタなどで、"-"や"X"を0に変換しておく。このファイルの中身はカンマ区切りテキストなのだが、2行目に人口の集計項目名が来る。
KEY_CODE,HYOSYO,CITYNAME,NAME,HTKSYORI,HTKSAKI,GASSAN,T000573001,T000573002,...
,,,,,,,総数、年齢「不詳」含む,総数0~4歳,...
24201,1,津市,,,,,285746,11755,...
242010010,2,津市,白塚町,,,,8951,340,...
普通にread.tableを使うと
>pop.data <- read.table("tblT000573C24201.txt",sep=",",header=T)
>str(pop.data)
'data.frame': 469 obs. of 67 variables:
$ KEY_CODE : num NA 2.42e+04 2.42e+08 2.42e+10 2.42e+10 ...
$ HYOSYO : int NA 1 2 3 3 3 3 2 3 3 ...
$ CITYNAME : Factor w/ 2 levels "","津市": 1 2 2 2 2 2 2 2 2 2 ...
$ NAME : Factor w/ 328 levels "","あのつ台",..: 1 1 275 275 275 275 275 113 113 113 ...
$ HTKSYORI : Factor w/ 3 levels "","合算地域あり",..: 1 1 1 1 1 1 1 1 1 1 ...
$ HTKSAKI : int NA NA NA NA NA NA NA NA NA NA ...
$ GASSAN : int NA NA NA NA NA NA NA NA NA NA ...
$ T000573001: Factor w/ 399 levels "-","1001","1002",..: 399 183 374 352 174 225 328 386 182 309 ...
$ T000573002: Factor w/ 116 levels "-","1","10","104",..: 116 9 58 43 112 54 44 62 3 42 ...
こうなってしまい、人口データが数値(numeric)ではなくFactorとして読まれてしまうので、GISで数値で図が書けない。
そこで、タイトルとデータをscanで別々に読み込む。
まずはタイトルを読み込む。scan関数で1行目だけ読み込む。
pop.title <- scan("tblT000573C24201.txt",sep=",",nlines=1,what="raw")
次に3行スキップして4行目以降をデータとしてを読み込む。scan関数で読み込んだ結果はベクトルになるので、行列に変換する
pop.data <- scan("tblT000573C24201.txt",sep=",",skip=3,what="raw")
pop.data <- matrix(pop.data,ncol=length(pop.title),byrow=T)
この時点ではpop.dataは町丁名があることから文字列データとなっている。数値データのみを残すために、2列目から7列目までをタイトル、データとも削除する
pop.title <- pop.title[-2:-7]
pop.data <- pop.data[,-2:-7]
as.numericでデータを数値に変換する。このとき、データはベクトルに戻ってしまうので、再度、行列に変換する。
pop.data <- matrix(as.numeric(pop.data),ncol=length(pop.title))
行列の列要素に名前をつけて、データフレームに変換する
colnames(pop.data) <- pop.title
pop <- data.frame(pop.data)
そして、GISの図形データと人口データを統合する。このとき字などの関係から、人口データには出てこない町丁名が図形データにはあることから、共通要素がない場合は図形データを残すようにして上書き保存する。
db2 <- merge(db,pop,by="KEY_CODE",all.x=T)
drite.dbf(db2,"h22ka24201.dbf")
これで、GISでシェープファイルを開き、テーブルを見ると、右の方に年齢階層別人口のデータが追加されるようになる。
GISのテーブル結合機能でもこの処理はできるのだけれど、稀にテーブルのタイトルが認識できないことがあることと、例えば県全体の絵を描くときなど、複数のファイルに対して処理する必要がある場合は、Rで処理した方が早い。このときは、ファイル名のリストをテキストファイルで別途作っておき、R上でforループで回す。例えば、30個のファイルに対して処理する場合は、こう書く
setwd("データの入っているディレクトリのフルパス")
gislist <- scan("GISファイル名(DBFファイル)のリスト",what="raw")
poplist <- scan("人口データファイル名(txtファイル)のリスト",what="raw")for(i in 1:30){
db <- read.dbf(gislist[i])
pop.title <- scan(poplist[i],sep=",",nlines=1,what="raw")
pop.title2 <- scan(poplist[i],sep=",",skip=1,nlines=1,
what="raw")
pop.title[8:67]<-pop.title2[8:67]
pop.data <- scan(poplist[i],sep=",",skip=3,what="raw")
pop.data <- matrix(pop.data,ncol=length(pop.title),byrow=T)
pop.title <- pop.title[-2:-7]
pop.data <- pop.data[,-2:-7]
pop.data <- matrix(as.numeric(pop.data),
ncol=length(pop.title))
colnames(pop.data) <- pop.title
pop <- data.frame(pop.data)
db2 <- merge(db,pop,by="KEY_CODE",all.x=T)
write.dbf(db2,gislist[i])
}