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

溢れ出る加齢臭

カレー臭に加え加齢臭が溢れ出る年齢になりました。

国勢調査の調査区データに年齢階層別人口データを統合する

地図で見る統計(統計GIS)でダウンロードしたGISのデータに、年齢階層別人口のデータを統合して、GIS上で色分け表示できるようにする。

GISのデータのうち、いわゆるデータベースのデータは、dBASE方式の.dbfファイルとなっている。このファイル、2003までのExcelでは読み書きできたんだけれど、2007以降は読み込みのみになってしまったらしく、書き込みができない。

そこでRを使う。

まず、Rでdbfファイルの読み書きができるよう、foreignパッケージを読み込んでおく

>library(foreign)

まず、GISデータを読み込む。ここでは例として津市のデータを読み込む

db <- read.dbf("h22ka24201.dbf")

次に、年齢階層別人口データを読み込むのだが、中のデータで、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])
}