前回のブログでは、次世代統計利用システムで都道府県・市区町村コード情報が 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 で複数の期限付きの政令指定都市のコードを持つ場合があるということのためのようだ。

image

それで、期限付きの政令指定都市コードのうち現在の政令指定都市コードを選択してやらないといけないということで、ここでは、少し処理を簡単にするため、廃止年月日のない政令指定都市コードを選択することにした。

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ページは、統計メモ帳の以下にアドレスに公開しておきます。

http://ecitizen.jp/sac

もう少し手間をかければ、e-stat の「標準地域コードを探す」というページに近いものが作れると思っている。しかし、レスポンスや次世代統計利用システムのサーバー側の負荷を考えると、SPARQL を直接使うのはどうかなと思っていて、自分のサーバーで、データのキャッシュ等をして負荷の軽減をすべきだと思っている。それで、次はサーバー側での SPARQL の処理を試してみようと思っている。C#には、dotNetRDF というオープンスースの RDF 関連のライブラリーもあるので、そのライブラリーも試してみたいと思っている。