前回のブログでは、次世代統計利用システムで都道府県・市区町村コード情報が LOD(Linked Open Data)で提供されるようになったので、実際に使ってみてその使い方をメモした。今回は、その LOD を使って、実際に自治体コード表(地方公共団体コード表)を作ってみた。(公開している場所 http://ecitizen.jp/sac)
自治体コード表をLODを使って作ってみて感じたことは、LODはプログラマーにとっては確かに便利だと思う。でも、現在の政府統計窓口では、市町村コード表や廃置分合等情報がダウンロードできるようになっている。それを使ってプログラムする場合とLODを使ってプログラムをする場合の差はあまりないと思う。結局は、LODを使ってもデータの内容を把握しないとプログラムはつくれない。オープンデータの5つ星がいわれているが、自分の経験からいえば、星が0と1の間はものすごく大きいが、星1つと星5つの差はそれと比べるとかなり小さく、星5つというよりは星1.5だというのが正直な感想である。
以下は具体的にどうしたかをメモしておく。まず、自治体コード表を作るため、前回作成した埼玉県の市町村一覧を選択するクエリーを変更して、SELECT に「ふりがな表記」と「自治体コードの6桁目であるチェックディジットコード」を追加し、FILTERに「特別区」及び「政令指定都市の区」を追加して表示されるようにした。変更後のクエリーは以下のとおりである。
SELECT ?s ?name ?kana ?cd WHERE { GRAPH ?g { ?s ?p ?o . ?s rdf:type sacs:CurrentStandardAreaCode. {{ ?o dcterms:isPartOf sac:C11000-19700401. }UNION{ ?o dcterms:isPartOf ?district. ?district dcterms:isPartOf sac:C11000-19700401. }} ?o sacs:administrativeClass ?ad. ?o rdfs:label ?name. ?o rdfs:label ?kana. ?o sacs:checkDigit ?cd. } FILTER( lang(?name) = "ja")
FILTER( lang(?kana) = "ja-hrkt") FILTER(?ad = sacs:DesignatedCity || ?ad = sacs:CoreCity || ?ad = sacs:SpecialCity || ?ad = sacs:SpecialWard || ?ad = sacs:Ward || ?ad = sacs:City || ?ad = sacs:Town || ?ad = sacs:Village) }
そのクエリーをベースにして、JavaScript を使ってWebブラウザーで自治体コードが表示されるようにしてみた。期限付きの都道府県コードは、CXX000-19700401で調べた範囲ではすべての都道府県が大丈夫のようだ。沖縄県の場合は1970年4月1日現在では琉球政府の時代で日本復帰は1972年5月15日であるが、C47000-19700401 となっていた。なお、沖縄県にある市町村の方の期限付き標準地域コードは1972年5月15日以降の分しかない。
このクエリーを処理する JavaScript のルーティンを書くことはそれほど難しいことはない。注意する点は、ブラウザーでの処理には、クロスドメインの制限があるということである。そのため、使うプロトコルは JSONP になるので、データとして jsonp/callback を送信する必要がある。また、その値がコールバックルーティンの名前なので、jQuery の場合であれば jsonpCallback にその名前を設定してやる必要がある。
なお、ソートは本来はクエリー側ですべきで、ORDER BY ?s をクエリーの最後につけてやればコード順のソートが出来るはずなのだが、理由はよくわからないが動作させられなかったので、JavaScript 側の方でソートをしている。
function makeTable(sacQuery){ $.ajax({
url: http://statdb.nstac.go.jp/lod/sparql?,
data: {
query: sacQuery,
output: "json",
jsonp: "sacsac"
},
jsonpCallback: 'sacsac',
dataType: "jsonp"
})
.done(function (data) {
var mn = data.results.bindings;
mn.sort(function (a, b) {
if (a.s.value < b.s.value)
return -1
else
return 1;
});
var html = "<table class=\"sactable\">";
html += "<tr><th>団体コード</th><th>団体名</th><th>ふりがな</th></tr>";
for (var n = 0; n < mn.length; n++) {
html += "<tr><td>" + mn[n].s.value.substring(mn[n].s.value.length - 5) + mn[n].cd.value + "</td><td>" +
mn[n].name.value + "</td><td>" + mn[n].kana.value + "</td></tr>";
}
html += "</table>";
return html;
});
}
これで動作させてみると、下の図のように政令指定都市の区が二重になった。なぜか調べると、政令指定都市の区は dcterms:isPartOf で複数の期限付きの政令指定都市のコードを持つ場合があるということのためのようだ。
それで、期限付きの政令指定都市コードのうち現在の政令指定都市コードを選択してやらないといけないということで、ここでは、少し処理を簡単にするため、廃止年月日のない政令指定都市コードを選択することにした。
SPARQL 1.1 だと、dcterms:valid 値がないレコードを取得するののは NOT EXISTS を使えば簡単に記述できるが、NOT EXISTS は動作しなかった。それで、以下のように SPARQL 1.0 で記述してみると動作した。
SELECT ?s ?name ?kana ?cd WHERE { GRAPH ?g { ?s ?p ?o . ?s rdf:type sacs:CurrentStandardAreaCode. {{ ?o dcterms:isPartOf sac:C11000-19700401. }UNION{ ?o dcterms:isPartOf ?district. ?district dcterms:isPartOf sac:C11000-19700401. OPTIONAL {?district dcterms:valid ?valid.} }} ?o sacs:administrativeClass ?ad. ?o rdfs:label ?name.
?o rdfs:label ?kana. ?o sacs:checkDigit ?cd.
}
FILTER( lang(?name) = "ja")
FILTER( lang(?kana) = "ja-hrkt") FILTER(?ad = sacs:DesignatedCity || ?ad = sacs:CoreCity || ?ad = sacs:SpecialCity || ?ad = sacs:SpecialWard || ?ad = sacs:Ward || ?ad = sacs:City || ?ad = sacs:Town || ?ad = sacs:Village)
FILTER (!BOUND(?valid))
}
次世代統計利用システムの都道府県・市区町村コード情報は、SPARQL 1.0 で動作しているように思われる。これから使うシステムなので、NOT EXISTS や MINUS が使える SPARQL 1.1 で動作させて欲しいと思う。
今回作った Webページは、統計メモ帳の以下にアドレスに公開しておきます。
もう少し手間をかければ、e-stat の「標準地域コードを探す」というページに近いものが作れると思っている。しかし、レスポンスや次世代統計利用システムのサーバー側の負荷を考えると、SPARQL を直接使うのはどうかなと思っていて、自分のサーバーで、データのキャッシュ等をして負荷の軽減をすべきだと思っている。それで、次はサーバー側での SPARQL の処理を試してみようと思っている。C#には、dotNetRDF というオープンスースの RDF 関連のライブラリーもあるので、そのライブラリーも試してみたいと思っている。