e-Stat by R
The current release is OpenBSD 6.8, released October 18, 2020. This day marks the OpenBSD project's 25th anniversary.
configure
前回OpenBSDでRを作った時、/usr/ports/math/R/Makefile中に、突然(そのMakefie内では)未定義な変数が表れていて面喰らった。で、逃げてしまったんだけど、今回は正攻法で調べてみる。 まずは、configureが何をやってるか、dry-run してみる。
ob# make -n configure | tr ';' '\n' lock=R-3.6.3 export _LOCKS_HELD=" R-3.6.3" /usr/bin/perl /usr/ports/infrastructure/bin/portlock /usr/ports/pobj/locks/$ lock.lock math/R, locked=true trap 'if $locked then rm -f /usr/ports/pobj/locks/$lock.lock locked=false fi' 0 trap 'exit 1' 1 2 3 13 15 cd /usr/ports/math/R && PKGPATH=math/R make _internal-configure
これを見ると、ロック処理して2重実行を禁止してるのな。次は -p を付けてターゲットルールと変数をダンプしてみる。だらだら出てくるやつから、一度ログに落としてじっくり閲覧。
ob# make -p configure >LOG ob# emacs LOG
目がチカチカするので、grep MODTK_ LOG して、眼をいたわる。
CONFIGURE_ARGS = --disable-java --disable-openmp --enable-BLAS-shlib --enable-R-shlib --with-tcl-config=${MODTCL_CONFIG} --with-tk-config=${MODTK_CONFIG} --prefix='${PREFIX}' --sysconfdir='${SYSCONFDIR}' --mandir='${PREFIX}/man' --infodir='${PREFIX}/info' --localstatedir='${LOCALSTATEDIR}' --disable-silent-rules --disable-gtk-doc MODTCL_VERSION = ${MODTK_VERSION} MODTK_BIN = ${LOCALBASE}/bin/wish${MODTK_VERSION} MODTK_BUILD_DEPENDS = ${_MODTK_SPEC}:x11/tk/${MODTK_VERSION} ${MODTCL_BUILD_DEPENDS} MODTK_CONFIG = ${MODTK_LIBDIR}/tkConfig.sh MODTK_INCDIR = ${LOCALBASE}/include/tk${MODTK_VERSION} MODTK_LIB = tk85 MODTK_LIBDIR = ${MODTCL_TCLDIR}/tk${MODTK_VERSION} MODTK_LIB_DEPENDS = ${_MODTK_SPEC}:x11/tk/${MODTK_VERSION} ${MODTCL_LIB_DEPENDS} MODTK_RUN_DEPENDS = ${_MODTK_SPEC}:x11/tk/${MODTK_VERSION} ${MODTCL_RUN_DEPENDS} MODTK_VERSION = 8.5 MODTK_WANTLIB = ${MODTK_LIB} ${MODTCL_WANTLIB} :
makeの変数代入は大きく分けて2種類あるとな。:= は、即実行。= の方は、必要になった時に実行ってやつだ。そんなの今回初めて知ったぞ。で、複雑な事をやって、最終的に決定されるとな。裏では、bsd.port.mkが鎮座してるとな。
ob# grep _internal-configure: LOG | tr ' ' '\n' _internal-configure: /usr/ports/pobj/R-3.6.3/.dep-STEM-ge-8,lt-9-lang-gcc-8,-f95 /usr/ports/pobj/R-3.6.3/.dep-archivers-gtar /usr/ports/pobj/R-3.6.3/.dep-archivers-unzip /usr/ports/pobj/R-3.6.3/.dep-archivers-zip : /usr/ports/pobj/R-3.6.3/.dep-STEM-ge-8,lt-9-lang-gcc-8,-libs /usr/ports/pobj/R-3.6.3/.buildwantlibs /usr/ports/pobj/R-3.6.3/build-amd64/.configure_done
ob# make -dA configure >CONFLOG
そして、これが最強のログになる。見るのを拒否してるぐらい分量が有るぞ。grepで絞ろうにも、keywordを思い付かない。トホホ。まあ、このログが困った時の最後の砦って事で、今回のサーチは終了と言う事にしておく。
県別魅力度ランキング
年も終わりに近づくと、その年のまとめって事で、〇〇ランキングってのが、ぞろ出て来る。 そんな事で、 都道府県魅力度ランキング2020 なんてのが発表された。民間な機関がまとめたそうなんだけど、どこから資金が出ているのだろう? こういう事を常に考えてしまうオイラーが居る。要するにバイアスがかかっていないかって事だ。
上記によると、万年最下位なバラキが、とうとう順位を上げた。タレントに露出度アップ作戦が功を奏したようだ。オイラーはてっきり、天然自然なスィーツである、干し芋が高感度に寄与してたと思っていたけど、違ったみたい。是非Rを使って因子分析を行ってほしい所だ。
当然、最下位に沈んだ県がある訳で、栃木らしい。餃子だけじゃ食べて行けない訳ね。カクテルも光輝いてはいないようだし。まて、栃木には那須塩原も有るし日光だってあるぞ。 でも、日光結構、一度行けば満足。シンガポールのマーライオンみたいに、がっかりの筆頭かな。ああ、筆が滑ってしまった。栃木の県知事並びに県民の皆様に、伏してお詫び致します。
e-Stat
上の魅力度は私的機関の調査なので、今度は公的機関の資料に当たってみる。総務省統計局ね。 この局が電子統計を公開してる。 少し、資料集めしておく。
Rに特化した資料も集めておくかな。
政府統計e-Stat APIをプログラミング言語「R(アール)」で使ってみた
プログラミングによるビッグデータの分析(R) おお、総務書のICTスキル教材とやらが出てきたぞ。R言語は、政府公認のアプリに認定されてるって事でいいかな。
総務省 ICTスキル総合習得プログラム こちらが、上記の親ページか。なかなか楽しそう。
e-StatのAPI 奥村先生の所
ユーザー登録
e-Stat へ行く。右上の新規登録をクリックして、メアドを入力。暫くすると本登録の案内がメールで送られて来る。リンクをクリックして本登録。
IDはメアドを入れる。パスワードはご自由に。これで本登録終了。今度はログインボタンを押してログイン。パスワードを忘れた人は、IDを入力して、パスワード要求して下さいですって。 それって、とっても危険な事だよね。メアドを知ってる人は、簡単に乗っ取る事出来ちゃうよ。 それでいいのか >総務省。こういう苦言は、お問い合わせにメールすればいいのかな。
ああ、単にメアドを知ってたって、メアドのパスワードを知らないとだめか。ソーシャルハッキングとか、むにゃむにゃむにゃ。そんな人、どんだけーー居るの?
次はRからデータを引っ張り出す時に必要な、アプリケーションIDを要求する。マイページをクリック。API機能(アプリケーションID発行)をクリック。
3個のIDを取得出来る。けど、普通に使うなら一つあれば十分だろう。 名称は、「Rの勉強」、URLは、「https://localhost」 にした。これで、発行ボタンを押すと、40Byteの長ったらしいhex文字が出てきた。 後は、これを使うだけ。
なお、URLは、httpを指定しちゃうと、強度不足って怒られて、アプリケーションIDの発行を拒否されるんで注意。いつの間にか、httpsがデフォになったんですねぇ。
e-Stat by R
いよいよRからe-Statを叩く。懇切丁寧に使い方を解説されてる、 Rからe-Stat APIを使う をトレースする事にします。
library(httr) response <- GET( url = "https://api.e-stat.go.jp/rest/2.1/app/json/getStatsList", query = list( appId = '40Byte-appID' , searchWord = "犯罪統計 AND 刑法犯" ) ) response
url + query な所にアクセスして、そのレスポンスを取得するんだな。検索ワードは AND で 絞り込みとな。
library(listviewer) res_content <- content(response) jsonedit(res_content)
コンテンツはbody部になろんだな。してその結果はjsonとな。jsonのビューアーは、firefox上に展開された。ブラウザーが得意とする分野だ。
ちょいと寄り道
サーバーからのレスポンスを眺めてみる。
> str(response) List of 10 $ url : chr "https://api.e-stat.go.jp/rest/2.1/app/json/getStatsList?appId=40hex....&searchWord=%E7....%8A%AF" $ status_code: int 200 $ headers :List of 12 ..$ server : chr "nginx" ..$ date : chr "Sun, 18 Oct 2020 22:25:07 GMT" ..$ content-type : chr "application/json; charset=utf-8" :
headerにnginxなんてのが見えるな。政府もOSSを採用してんのかな。バックエンドのDBはMySQLだったりして。
リクエストにしっかりとappIDが埋め込まれていて、どこの誰が使ったか、確認出来るとな。 この方法、超昔にやった事があるぞ。懐かしい方法だわい。昔やったのはCGIですよ。最初はperlだったけどrubyに鞍替えしたな。確か20世紀の最後の頃だったような。
裸のresponseを見ると
$times redirect namelookup connect pretransfer starttransfer 0.000000 0.117418 0.138843 0.193385 29.406071 total 29.406309 $content [1] 7b 22 47 45 54 5f 53 54 41 54 53 5f 4c 49 53 54 22 3a 7b 22 52 45 53 55 : [4057] 34 45 31 22 7d 7d 5d 7d 7d 7d
こんな応答時間まで取得してた。それから生ボディーも見られた。 次は、生ボディーをRに解釈してもらう。
> str(res_content) List of 1 $ GET_STATS_LIST:List of 3 ..$ RESULT :List of 3 .. ..$ STATUS : int 0 ..$ PARAMETER :List of 3 .. ..$ LANG : chr "J" .. ..$ SEARCH_WORD: chr "犯罪統計 AND 刑法犯" .. ..$ DATA_FORMAT: chr "J" .. ..$ TABLE_INF :List of 4 .. .. ..$ :List of 15 .. .. .. ..$ @id : chr "0003191320" .. .. .. ..$ STAT_NAME :List of 2 .. .. .. .. ..$ @code: chr "00130001" .. .. .. .. ..$ $ : chr "犯罪統計" .. .. .. ..$ GOV_ORG :List of 2 .. .. .. .. ..$ @code: chr "00130" .. .. .. .. ..$ $ : chr "警察庁" .. .. .. ..$ STATISTICS_NAME : chr "犯罪統計" .. .. .. ..$ TITLE : chr "第1表 刑法犯 罪種別 認知・検挙件数・検挙人員" .. .. .. ..$ CYCLE : chr "年次" .. .. .. ..$ SURVEY_DATE : chr "201601-201612" .. .. .. ..$ OPEN_DATE : chr "2017-12-11" .. .. .. ..$ SMALL_AREA : int 0 .. .. .. ..$ MAIN_CATEGORY :List of 2 .. .. .. .. ..$ @code: chr "14" .. .. .. .. ..$ $ : chr "司法・安全・環境" .. .. .. ..$ SUB_CATEGORY :List of 2 .. .. .. .. ..$ @code: chr "02" .. .. .. .. ..$ $ : chr "犯罪" .. .. .. ..$ OVERALL_TOTAL_NUMBER: int 2310 .. .. .. ..$ UPDATED_DATE : chr "2017-12-11" .. .. .. ..$ STATISTICS_NAME_SPEC:List of 1 .. .. .. .. ..$ TABULATION_CATEGORY: chr "犯罪統計" :
本当の生データは
$GET_STATS_LIST $GET_STATS_LIST$RESULT $GET_STATS_LIST$RESULT$STATUS [1] 0 $GET_STATS_LIST$RESULT$ERROR_MSG [1] "正常に終了しました。" $GET_STATS_LIST$DATALIST_INF$TABLE_INF[[4]] $GET_STATS_LIST$DATALIST_INF$TABLE_INF[[4]]$`@id` [1] "0003195002" $GET_STATS_LIST$DATALIST_INF$TABLE_INF[[4]]$STAT_NAME $GET_STATS_LIST$DATALIST_INF$TABLE_INF[[4]]$STAT_NAME$`@code` [1] "00130001" $GET_STATS_LIST$DATALIST_INF$TABLE_INF[[4]]$STAT_NAME$`$` [1] "犯罪統計" $GET_STATS_LIST$DATALIST_INF$TABLE_INF[[4]]$GOV_ORG $GET_STATS_LIST$DATALIST_INF$TABLE_INF[[4]]$GOV_ORG$`@code` [1] "00130" $GET_STATS_LIST$DATALIST_INF$TABLE_INF[[4]]$GOV_ORG$`$` [1] "警察庁"
こんな具合になっていた。こうしてみると裸のデータでも、何とかなりそうな雰囲気だな。
rlist
指南書では、かっこよく rlist ってパッケージで、綺麗にデータを見せてくれている。 Rでリストを扱うrlistパッケージのチュートリアル こんな素晴らしい案内も公開されている。
さすが、listって名前が付いているぐらいだから、lispの主要関数をそっくりRに移植しましたって趣で、オイラーは大好きですよ、こういうの。
ああ、オイラーの所でこのrlistパッケージを入れようとしたら、基底にXMLが必要って言われてエラーになった。エラー内容から、システムに欠けている、何とかパッケージを入れて、事無きを得た。ほんとにリナ系のパッケージングには腹が立つ。たかがヘッダーぐらい、けちけちしないで、ライブラリィー本体と一緒に入れろよ。disk容量の節約なんてのは、理由にならんからね。プンプン。
リナをdisるには、オイラーが常日頃愛用してる、OpenBSDではどうか確認しておかねばならない。そうしないと、何処かの国の野党みたいに、反対するのが使命ってなるからね。取り合えず、問題になったrlistだけを入れてみた。
> install.packages('rlist') --- Please select a CRAN mirror for use in this session --- also installing the dependencies 'yaml', 'jsonlite', 'XML', 'data.table' : * installing *source* package 'XML' ... checking for pkg-config... /usr/bin/pkg-config checking for xml2-config... /usr/local/bin/xml2-config USE_XML2 = yes SED_EXTENDED_ARG: -E Minor 9, Patch 10 for 2.9.10 Located parser file -I/usr/local/include/libxml2 -I/usr/local/include/parser.h Checking for 1.8: -I/usr/local/include/libxml2 -I/usr/local/include Using libxml2.*
リナの時は、確かこの辺りで引っかかったはず。OpenBSDでは、難なくクリアしたぞ。使ってて、超気持ちイイィー(って、往年の北島風の雄たけび)
この際だから、リナの apt-cache 相当を調べておく。
ob$ locate xml2-config /usr/local/bin/xml2-config /usr/local/lib/cmake/libxml2/libxml2-config.cmake /usr/local/man/man1/xml2-config.1 ob$ pkg_info -E /usr/local/bin/xml2-config /usr/local/bin/xml2-config: libxml-2.9.10p0 libxml-2.9.10p0 XML parsing library
そして、そんなの入れた記憶が無いんで、それを必要とする(身に覚えがあるであろう)パッケージを炙り出してみる。
ob$ pkg_info -R libxml Information for inst:libxml-2.9.10p0 Required by: emacs-26.3p1-no_x11 libglade2-2.6.4p17v0 librsvg-2.48.4 py-gtk2-2.24.0p7 qemu-4.2.0p0 shared-mime-info-1.15 tshark-3.2.7
ははは、オイラーの大好物が出て来た。emacsでもXMLをハンドリング出来るのか。あれは太っちょの括弧もどきだから、スマートなカッコ・コッカと親類ではあるからね。
ob$ pkg_info -Q libxml debug-libxml++-2.40.1p2 debug-libxml++3-3.2.0 hs-libxml-sax-0.7.5p8 libxml++-2.40.1p2 libxml++3-3.2.0 libxml-2.9.10p0 (installed) libxmlbird-1.2.0p0 p5-Libxml-0.08p2 p5-XML-LibXML-2.0204v0 p5-XML-RSS-LibXML-0.3105 py-libxml-2.9.10p0
似たような名前も検索できるとな。残念ながら上記の -Q を除いて検索対象はインストール済みのportsだけを対象にしてる。apt-file 相当は、自分で汗を流してpkg/PLISTあたりを検索するしかないだろう。上手いコマンドを知っていたら、教えてください。
> install.packages('estatapi') --- Please select a CRAN mirror for use in this session --- also installing the dependencies 'sys', 'askpass', 'assertthat', 'digest', 'utf8 ', 'curl', 'mime', 'openssl', 'R6', 'cli', 'clipr', 'crayon', 'hms', 'lifecycle' , 'BH', 'cpp11', 'ellipsis', 'generics', 'glue', 'tidyselect', 'vctrs', 'fansi', 'pillar', 'pkgconfig', 'httr', 'purrr', 'readr', 'dplyr', 'tibble', 'rlang'
余勢を駆ってestatapiも入れてみようとした。なんだか色々な物の盛り合わせセットになってる。11.3Mのサイズが有るBHをダウンロードし始めたので、インストールを中止した。折角公開してくれた皆さんの努力を踏みにじるようで、申し訳ない。またいつか。
ああ、またいつかの理由は、e-StatのAPIを見てたら、新しい版の3.0が提供されてた。この版では、CSVが取れるらしい。なら、現状の環境でもすんなり行くのではないかと思ったのさ。
色々なライブラリィーを入れれば、それは便利だろうけど、脆弱性に繋がるからね。何たってオイラーはTeoさんの弟子ですから。まあ、茨の道が待ってるかも知れないけど。
> library(rlist) > library(pipeR) > res_content$GET_STATS_LIST$DATALIST_INF$TABLE_INF %>>% + list.mapv(`@id`) [1] "0003191320" "0003191340" "0003194968" "0003195002"
@idで評価すると、idを取り出せるとな。
> res_content$GET_STATS_LIST$DATALIST_INF$TABLE_INF %>>% + list.select( + id = `@id`, + table_name = TITLE_SPEC$TABLE_NAME + ) %>>% + list.stack() id 1 0003191320 2 0003191340 3 0003194968 4 0003195002 table_name 1 第1表 刑法犯 罪種別 認知・検挙件数・検挙人員 2 第1表 刑法犯 罪種別 認知・検挙件数・検挙人員 対前年比較 3 第3表 刑法犯総数 都道府県別 認知・検挙件数・検挙人員 対前年比較 4 第3表 刑法犯総数 都道府県別 認知・検挙件数・検挙人員
名前も取り出しに追加しておいて、list.stackで、フレームにも出来るとな。
get data
APIで公的統計データを取得 なんて言うのが載ってた、統計局の勉強資料に、ちょいと鞍替えする。
例で、全国消費実態調査/ 平成26年全国消費実態調査/ のデータをDLしようとしたんだけど、 該当データは無いと言われた。
e-Statへ行って、統計データを探す。データ種別は、ファイルとデータベースが有るけど、勿論データベースからの検索。
検索ワードは、政府統計(初期状態)とデータセットが有るんで、データセットを選び、平成26年全国消費実態調査 総世帯 購入地域 で、検索。19件出て来た。
エラーした時の案内に、フロー編第151表 のが載ってたので、それを頼りに、APIのクエリィーを出してみた。
"\"RESULT\"\n\"STATUS\",\"1\"\n\"ERROR_MSG\", \"正常に終了しましたが、該当データはありませんでした。\"\n\"DATE\",\"2020-10-18T15:33:13.957+09:00\"\n\ "RESULT_INF\"\n\"TOTAL_NUMBER\",\"0\"\n \"TABLE_INF\",\"0003130397\"\n\"STAT_NAME\",\"00200564\",\"全国消費実態調査\" ...
このURLを見ると、statsDataIdが、スクリプト中で指定されてる。けど、補助のidは無い。きっと補助のidが間違ってて、エラーになってるんだろうね。取り合えずそれを削除した。
そんな時は、 estatapiパッケージで簡単にe-Statのデータ取得 を参考に、 統計分野 を見れば良いのかな。なんか、図書の10進分類みたいな番号が割り当てられている。すると、個別のデータを示すIdってのは、ISBN番号になるのか。慣れれば便利なんだろうね。図書館の司書に相当する、データ・ソムリエみたいになれるのかな?
library("httr") library("listviewer") library("rlist") library("pipeR") library("stringr") library("dplyr") # 全国消費実態調査/ 平成26年全国消費実態調査/ # 全国品目及び購入先・購入地域に関する結果総世帯に関する結果 response2 <- GET( url = "https://api.e-stat.go.jp/rest/3.0/app/getSimpleStatsData", query = list( appId = '40byte-appId' , statsDataId = "0003130397" ) ) con2 <- content(response2) result <- read.csv(text = sub('"VALUE"\n', "", con2), row.names = c() ) write.csv(result, "/tmp/zzz.csv", row.names=FALSE)
read.csvの所でエラーになったので、row.namesを何も無しに設定した。仕様が変わったの?
> response2$times redirect namelookup connect pretransfer starttransfer 0.000000 0.039533 0.060795 0.126765 4.090438 total 4.435121
とんでもなく時間がかかる時が有るけど、混雑してるのかな?
sakae@pen:/tmp$ wc zzz.csv 513836 549811 12501388 zzz.csv sakae@pen:/tmp$ nkf -g zzz.csv UTF-8
出来上がったcsvファイル。
"2014000000","2014年" "円","56" "003","金額" "02610","紙おむつ(大人用)" "00020","現金" "07005","総世帯" "00620","70歳以上" "00000","全国"
何となく、2014年の全国70歳以上の総世帯が現金で紙おむつ代を56円払いましたって風に読むのかな。
DBで拾い出したものをEXCEL風の表形式でDL出来るんでやってみた。
sakae@pen:/tmp$ wc FEH_00200564_201019061408.csv 155 242 393220 FEH_00200564_201019061408.csv sakae@pen:/tmp$ nkf -g FEH_00200564_201019061408.csv Shift_JIS
nkf -w してutfに変換して見ると
"統計名:","平成26年全国消費実態調査 全国 品目及び購入先・購入地域に関する結果 総世帯" "表番号:","151" "表題:","[総世帯]フロー編第151表 年間収入階級・世帯主の年齢階級,購入形態, 品目別1世帯当たり1か月間の支出" "実施年月:","2014年","-" "市区町村時点(年月日):","-" "***","数字が得られないもの" "-","該当数字がない" : "テレビゲーム機【円】","ゲームソフト等【円】","他の玩 具【円】","切り花【円】","音楽・映像用未使用メディア【円】","音楽・映像収録済メ ディア【円】","ペットフード【円】","他の愛玩動物・同用品【円】","園芸用植物【円 】","園芸用品【円】","電池【円】"
sakae@pen:/tmp$ grep テレビゲーム機 aa.csv | tr ',' '\n' | wc 459 471 13857
随分と細かい家計簿(相当)だなあ。特定なデータを抜き出す方法は、 政府統計の総合窓口(e-Stat)のAPIを使ってみよう {R編} が参考になる。