45
Help us understand the problem. What are the problem?

More than 3 years have passed since last update.

posted at

updated at

政府統計の総合窓口(e-Stat)のAPIを使ってみよう [R編]

はじめに

Qiita Rアドベント政府統計ポータル(e-Stat)と R でサンタさんの12月の出費動向を調べてみたという良記事がありました。
とても参考になるのですが、ポータルからマウスで項目をクリックしていくのが大変です。特に最後の方のフェーズではページが強制的にフルスクリーンになってしまい、上記アドベントの操作を確認できなくなります。

そこでAPIを使ってみます。

その前に、e-Stat API を少し触ってみましょう。

公式説明PDFをパクる

恐れおおくも総務省統計局統計センター様謹製PDF の最後の事例をパクります。

RCurl でjson形式のデータを引っ張ってきます。次世代統計システムから取得した自分のアカウントが必要です。以下のコードで yourAPPID の部分を取得したID に変更してください。

さらに加えて、統計表IDや分類表IDが必要なんですが、後述します。

> library(RCurl)
> yourAPPID <- "yourAPPID"
> url <- paste("http://api.e-stat.go.jp/rest/1.0/app/json/getStatsData?appId=",
+               yourAPPID,
+               "&statsDataId=0003013276", "&cdArea=09003,22004",
+               "&cdCat01=010920070",
+               "&cdTimeFrom=2012000101&cdTimeTo=2013000303",sep = "")
> x <- getURI(url)

あまり使ったことなかったので、この機会にjsonlite をインスコしてjsonを解釈しますた。

> library(jsonlite)
> x2 <- fromJSON(x)

構造を確認してみましょう(一部、端折ります)。

> str(x2)
List of 1
 $ GET_STATS_DATA:List of 3
  ..$ RESULT          :List of 3
  ..$ PARAMETER       :List of 6
  ..$ STATISTICAL_DATA:List of 3
  .. ..$ TABLE_INF:List of 9
  .. .. ..$ @id            : chr "0003013276"
  .. .. ..$ STAT_NAME      :List of 2
  .. .. .. ..$ @code: chr "00200561"
  .. .. .. ..$ $    : chr "家計調査"
  .. .. ..$ STATISTICS_NAME: chr "家計調査 家計収支編 二人以上の世帯"
  .. .. ..$ TITLE          :List of 2
  .. .. .. ..$ @no: chr "010"
  .. .. .. ..$ $  : chr "品目分類 品目分類(平成22年改定)(総数:金額)"
  .. ..$ CLASS_INF:List of 1
  .. .. ..$ CLASS_OBJ:'data.frame': 5 obs. of  3 variables:
  .. .. .. ..$ @id  : chr [1:5] "tab" "cat01" "cat02" "area" ...
  .. .. .. ..$ @name: chr [1:5] "表章項目" "品目分類(22年改定)" "世帯区分" "地域区分" ...
  .. .. .. ..$ CLASS:List of 5
  .. .. .. .. ..$ :List of 3
  .. .. .. .. ..$ :List of 4
  .. .. .. .. .. ..$ @code : chr "010920070"
  .. .. .. .. .. ..$ @name : chr "ぎょうざ"
  .. .. .. .. .. ..$ @level: chr "4"
  .. .. .. .. .. ..$ @unit : chr "円"
  .. .. .. .. ..$ :'data.frame':    4 obs. of  3 variables:
  .. .. .. .. .. ..$ @code : chr [1:4] "03" "04" "01" "02"
  .. .. .. .. .. ..$ @name : chr [1:4] "二人以上の世帯" "二人以上の世帯のうち勤労者世帯" "二人以上の世帯(農林漁家世帯を除く)" "二人以上の世帯のうち勤労者世帯(農林漁家世帯を除く)"
  .. .. .. .. ..$ :'data.frame':    2 obs. of  3 variables:
  .. .. .. .. .. ..$ @code : chr [1:2] "09003" "22004"
  .. .. .. .. .. ..$ @name : chr [1:2] "09201 宇都宮市" "22130 浜松市"
  .. .. .. .. .. ..$ @level: chr [1:2] "1" "1"
  .. .. .. .. ..$ :'data.frame':    15 obs. of  3 variables:
  .. .. .. .. .. ..$ @code : chr [1:15] "2013000303" "2013000202" "2013000101" "2012001212" ...
  .. .. .. .. .. ..$ @name : chr [1:15] "2013年3月" "2013年2月" "2013年1月" "2012年12月" ...
  .. ..$ DATA_INF :List of 2
  .. .. ..$ NOTE :'data.frame': 3 obs. of  2 variables:
  .. .. ..$ VALUE:'data.frame': 30 obs. of  7 variables:
  .. .. .. ..$ @tab  : chr [1:30] "01" "01" "01" "01" ...
  .. .. .. ..$ @cat01: chr [1:30] "010920070" "010920070" "010920070" "010920070" ...
  .. .. .. ..$ @cat02: chr [1:30] "03" "03" "03" "03" ...
  .. .. .. ..$ @area : chr [1:30] "09003" "09003" "09003" "09003" ...
  .. .. .. ..$ @time : chr [1:30] "2013000303" "2013000202" "2013000101" "2012001212" ...
  .. .. .. ..$ @unit : chr [1:30] "円" "円" "円" "円" ...
  .. .. .. ..$ $     : chr [1:30] "358" "310" "294" "464" ...

とりあずデータを取り出すには GET_STATS_DATA$STATISTICAL_DATA$DATA_INF$VALUEだけ抜けば良いことが分かりました。
抜きます。

> df <- x2$GET_STATS_DATA$STATISTICAL_DATA$DATA_INF$VALUE

列は増えていますが、最初に言及したPDFと多分同じですね。

> colnames(df)
[1] "@tab"   "@cat01" "@cat02" "@area"  "@time"  "@unit"  "$"     
> colnames(df)[7] <- "@yen"
> head(df)
  @tab    @cat01 @cat02 @area      @time @unit @yen
1   01 010920070     03 09003 2013000303    円  358
2   01 010920070     03 09003 2013000202    円  310
3   01 010920070     03 09003 2013000101    円  294
4   01 010920070     03 09003 2012001212    円  464
5   01 010920070     03 09003 2012001111    円  377
6   01 010920070     03 09003 2012001010    円  324

データのクラスIDを確認する方法

ちなみに政府統計APIを利用するには、各種カテゴリのクラス・コードIDを知る必要があります。
上で抽出したJSONフォーマットでも CLASS_INF$CLASS_OBJ$CLASS に保存されています。

> # 以下にIDが確認できます
> x2$GET_STATS_DATA$STATISTICAL_DATA$CLASS_INF$CLASS_OBJ[1:2]
    @id                @name
1   tab             表章項目
2 cat01 品目分類(22年改定)
3 cat02             世帯区分
4  area             地域区分
5  time       時間軸(月次)
> # ついでなので、もっと詳しくみてみましょうか
> codes <- x2$GET_STATS_DATA$STATISTICAL_DATA$CLASS_INF$CLASS_OBJ$CLASS
> length(codes)
[1] 5
> codes
[[1]]
[[1]]$`@code`
[1] "01"
[[1]]$`@name`
[1] "金額"
[[1]]$`@level`
[1] ""

[[2]]
[[2]]$`@code`
[1] "010920070"
[[2]]$`@name`
[1] "ぎょうざ"
[[2]]$`@level`
[1] "4"
[[2]]$`@unit`
[1] "円"

[[3]]
  @code                                                @name @level
1    03                                       二人以上の世帯      1
2    04                       二人以上の世帯のうち勤労者世帯      1
3    01                 二人以上の世帯(農林漁家世帯を除く)      1
4    02 二人以上の世帯のうち勤労者世帯(農林漁家世帯を除く)      1

[[4]]
  @code          @name @level
1 09003 09201 宇都宮市      1
2 22004   22130 浜松市      1

[[5]]
        @code      @name @level
1  2013000303  2013年3月      1
2  2013000202  2013年2月      1
3  2013000101  2013年1月      1
4  2012001212 2012年12月      1
5  2012001111 2012年11月      1

政府統計の統計表IDを確認する方法

さて、APIを利用して統計表を抜くには、そのIDが必要なので、取り出します。とても時間がかかります。ここはXMLなので XML パッケージを使います。

> library(XML)
> url <- paste("http://statdb.nstac.go.jp/rest/1.0/app/getStatsList?appId=", yourAPPID, sep = "")
> estat <- xmlParse(url)

Rでやるのが辛いなら、端末で抜きましょう。

$ wget http://statdb.nstac.go.jp/rest/1.0/app/getStatsList?appId=yourAPPID --output-document=estat.xml

いちど抜いたら保存しておきましょう。

「家計調査 家計収支編 二人以上の世帯」を抜く

Qiita Rアドベント記事に政府統計ポータル(e-Stat)と R でサンタさんの12月の出費動向を調べてみたではマウス操作でデータをCSVファイルとして抽出しています。
これをAPIでやってみましょう。

そのためには統計表 ID やリストIDが必要です。上で統計表ID一覧を取得済みですから、ここを検索します。

> library(XML)
> # url <- paste("http://statdb.nstac.go.jp/rest/1.0/app/getStatsList?appId=", yourAPPID, sep = "")
> # estat <- xmlParse(url)
> # あるいは保存したファイルから  estat <- xmlParse("estat.xml")
> #
> #  ちなみにこの操作は、オブジェクトをコピーするのではなく、もとのデータへの参照になっています
> est1 <- getNodeSet(estat, "//GET_STATS_LIST//DATALIST_INF//STATISTICS_NAME")
>
> # リスト名を取り出します(これも時間がかかります)
> tmp <- xmlSApply(est1, function(x) xmlSApply(x, xmlValue))
>
> #ちなみにtmpオブジェクトも保存しておくといいでしょう
> # save(tmp, file = "estatIdNames.rda")
> # 検索して、該当するリストの添え字を取ります
> num <- grep("家計調査 家計収支編 二人以上の世帯", tmp)
> nodes <- getNodeSet(estat, "//GET_STATS_LIST//DATALIST_INF//LIST_INF")
> nodes[num]
[[1]]
<LIST_INF id="0002070001">
  <STAT_NAME code="00200561">家計調査</STAT_NAME>
  <GOV_ORG code="00200">総務省</GOV_ORG>
  <STATISTICS_NAME>家計調査 家計収支編 二人以上の世帯</STATISTICS_NAME>
  <TITLE no="001">用途分類 用途分類(総数)</TITLE>
  <CYCLE>月次</CYCLE>
  <SURVEY_DATE>0</SURVEY_DATE>
  <OPEN_DATE>2014-12-26</OPEN_DATE>
  <SMALL_AREA>0</SMALL_AREA>
</LIST_INF> 

[[2]]
<LIST_INF id="0002070002">
  <STAT_NAME code="00200561">家計調査</STAT_NAME>
  <GOV_ORG code="00200">総務省</GOV_ORG>
  <STATISTICS_NAME>家計調査 家計収支編 二人以上の世帯</STATISTICS_NAME>
  <TITLE no="001">用途分類 用途分類(総数)</TITLE>
  <CYCLE>四半期</CYCLE>
  <SURVEY_DATE>0</SURVEY_DATE>
  <OPEN_DATE>2014-11-14</OPEN_DATE>
  <SMALL_AREA>0</SMALL_AREA>
</LIST_INF> 

以下、あと少し続くけど略

まあ、さらに検索しても良いのですが、疲れたので、目視で以下を確認しました。

[[22]]
<LIST_INF id="0003015188">
  <STAT_NAME code="00200561">家計調査</STAT_NAME>
  <GOV_ORG code="00200">総務省</GOV_ORG>
  <STATISTICS_NAME>家計調査 家計収支編 二人以上の世帯</STATISTICS_NAME>
  <TITLE no="010">品目分類 品目分類(平成22年改定)(総数:金額)</TITLE>
  <CYCLE>四半期</CYCLE>
  <SURVEY_DATE>0</SURVEY_DATE>
  <OPEN_DATE>2014-11-14</OPEN_DATE>
  <SMALL_AREA>0</SMALL_AREA>
</LIST_INF>

これをすっこ抜きます。ここから再び json をい使いましょう(XML で取得する方法を後述します)。これまた時間かかります。これまた時間かかります。

> url <- paste("http://api.e-stat.go.jp/rest/1.0/app/json/getStatsData?appId=",
+             yourAPPID,
+             "&statsDataId=0003015188",  sep = "")
> x <- getURI(url)

構造を確認します。

> x2 <- fromJSON(x)
> x2$GET_STATS_DATA$STATISTICAL_DATA$CLASS_INF$CLASS_OBJ[1:2]
    @id                @name
1   tab             表章項目
2 cat01 品目分類(22年改定)
3 cat02             世帯区分
4  area             地域区分
5  time     時間軸(四半期)

ゲーム関係のIDを探します。

> num <- grep("ゲーム|がん具",x2$GET_STATS_DATA$STATISTICAL_DATA$CLASS_INF$CLASS_OBJ$CLASS[[2]][,2])
> x2$GET_STATS_DATA$STATISTICAL_DATA$CLASS_INF$CLASS_OBJ$CLASS[[2]][num,]
        @code                @name @level @unit
521 090203010       テレビゲーム機      3    円
522 090203150       ゲームソフト等      3    円
523 090203020           他のがん具      3    円
559 090442000 入場・観覧・ゲーム代      4    円
567 090442060   他の入場・ゲーム代      5    円
# > grep("ゲーム|がん具",x2[[1]][3]$STATISTICAL_DATA$CLASS_INF$CLASS_OBJ$CLASS, value = TRUE, perl = TRUE)
# [1] "list(`@code` = c(\"090203010\", \"090203150\", \"090203020\"), `@name` = c(\"テレビゲーム機\", \"ゲームソフト等\", \"他のがん具\"), `@level` = c(\"3\", \"3\, \"3\"), `@unit` = c(\"円\", \"円\, \"円\"))"

これらのIDをカテゴリ01 (cdCat01) に指定して、もう一回検索してみましょうか。

> url <- paste("http://api.e-stat.go.jp/rest/1.0/app/json/getStatsData?appId=",
+             yourAPPID,
+             "&statsDataId=0003015188",
+             "&cdCat01=090203010,090203150,090203020",  sep = "")
> x <- getURI(url)
> 
> x2 <- fromJSON(x)
> df <- x2$GET_STATS_DATA$STATISTICAL_DATA$DATA_INF$VALUE
> head(df)
    @tab    @cat01 @cat02 @area      @time @unit    $
1      01 090203010     03 00000 2014000709    円  191
2      01 090203010     03 00000 2014000406    円  144
3      01 090203010     03 00000 2014000103    円  206

多分、これで良いんでしょうか。

XML として抽出するなら

ちなみに XML を使う場合は、http://api.e-stat.go.jp/rest/1.0/app/json/getStatsData? から json の部分を削ります。

> url <- paste ("http://api.e-stat.go.jp/rest/1.0/app/getStatsData?appId=", yourAPPID, 
+              "&statsDataId=0003015188",
+              sep = "")
> library (XML)
> estatX <- xmlParse(url)
> estatTable <- getNodeSet(estatX, "//GET_STATS_DATA//STATISTICAL_DATA//CLASS_INF//CLASS_OBJ")
> # xmlRoot () xmlChildren () で辿っていってもいいです
> # estatTableの二つ目のリストは 品目分類 `cat01` ですが、何でしょうか?
> estatTable [[2]]
<CLASS_OBJ id="cat01" name="品目分類(22年改定)">
  <CLASS code="000100000" name="世帯数分布(抽出率調整)" level="1" unit="一万分比"/>
  <CLASS code="000200000" name="集計世帯数" level="1" unit="世帯"/>
  <CLASS code="000300000" name="世帯人員" level="1" unit="人"/>
  <CLASS code="000400000" name="18歳未満人員" level="2" unit="人"/>
  <CLASS code="000500000" name="65歳以上人員" level="2" unit="人"/>
  <CLASS code="000600000" name="65歳以上無職者人員" level="3" unit="人"/>
  <CLASS code="000700000" name="有業人員" level="1" unit="人"/>
  <CLASS code="000800000" name="世帯主の年齢" level="1" unit="歳"/>
  <CLASS code="000900000" name="持家率" level="1" unit="%"/>
  <CLASS code="001000000" name="家賃・地代を支払っている世帯の割合" level="1" unit="%"/>
  <CLASS code="001100000" name="消費支出" level="1" unit="円"/>
  <CLASS code="010000000" name="食料" level="1" unit="円"/>
  <CLASS code="010100000" name="穀類" level="2" unit="円"/>
  <CLASS code="010110001" name="米" level="3" unit="円"/>
中略
> # 長いので簡略化します
> xmlAttrs(estatTable[[2]],"id")
                    id                   name 
               "cat01" "品目分類(22年改定)" 
> # "cat01" は品目なので、ゲームと玩具のIDを確認します
> estatClass <- getNodeSet(estatX, "//GET_STATS_DATA//STATISTICAL_DATA//CLASS_INF//CLASS_OBJ//CLASS")
> 
> tmp1 <- sapply(estatClass,xmlGetAttr, "name")
> 
> num <- grep("ゲーム|がん具", tmp1)
> 
> # 検索時にゲームなどの品目を利用したい時はこのIDを使います
> # tmp2 <- sapply(estatClass,xmlGetAttr, "code")
> (games <- data.frame(code = tmp1[num], name = tmp1 [num]))
       code                 name
1 090203010       テレビゲーム機
2 090203150       ゲームソフト等
3 090203020           他のがん具
4 090442000 入場・観覧・ゲーム代
5 090442060   他の入場・ゲーム代

> ## IDが確認できたので、これを使って検索しなおしてみましょう
> url2 <- paste ("http://api.e-stat.go.jp/rest/1.0/app/getStatsData?appId=", yourAPPID, 
+              "&statsDataId=0003015188",
+              "&cdCat01=090203010,090203150,090203020",
+              sep = "")
>
> estatX2 <- xmlParse(url2)
> estatData2 <- getNodeSet(estatX2, "//GET_STATS_DATA//STATISTICAL_DATA//DATA_INF//VALUE")
> df <- do.call ("rbind",  lapply (estatData2, xmlAttrs))
> value <-  lapply(estatData2,xmlValue)
> df <- cbind(df,value)
> df <- as.data.frame(df)
> head(df)
  tab     cat01 cat02  area       time unit value
1  01 090203010    03 00000 2014000709   円   191
2  01 090203010    03 00000 2014000406   円   144
3  01 090203010    03 00000 2014000103   円   206
4  01 090203010    03 00000 2013001012   円   526
5  01 090203010    03 00000 2013000709   円   172
6  01 090203010    03 00000 2013000406   円   164

補足

Rでe-Statを利用する方法としてとRで統計API というサイトがあります。以上の操作はベタなので、みなさん、このRで統計API で公開されている関数を利用しましょうね。

また、政府統計の総合窓口(e-Stat)ーAPI機能テストフォームなんかも使いましょう。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
45
Help us understand the problem. What are the problem?