2018年4月23日月曜日

統計LODのSPARQLクエリ研究 (2017.12.28)

自治体なんでもランキング with 統計LOD に必要な情報を、一挙に入手するクエリは以下の通り。
統計LOD の SPARQL Endpoint はこちら。クエリをコピペして一度お試しあれ。
なお、アプリ上では、統計指標(述語 g00200502-dimension:indicator に対する 目的語)については、ドロップダウンリストで選択したものをセットするが、ここでは便宜的に「g00200502-code:indicator-A1101」(人口総数)にしている。
【都道府県】
PREFIX g00200502-dimension:<http://data.e-stat.go.jp/lod/ontology/g00200502/dimension/>
PREFIX g00200502-code:<http://data.e-stat.go.jp/lod/ontology/g00200502/code/>
PREFIX cd-dimension:<http://data.e-stat.go.jp/lod/ontology/crossDomain/dimension/>
PREFIX sdmx-measure:<http://purl.org/linked-data/sdmx/2009/measure#>
PREFIX sdmx-dimension:<http://purl.org/linked-data/sdmx/2009/dimension#>
PREFIX sacs:<http://data.e-stat.go.jp/lod/terms/sacs#>
PREFIX ic:<http://imi.go.jp/ns/core/rdf#>
select  ?pref  ?year  ?observation
where {
?s  g00200502-dimension:indicator  g00200502-code:indicator-A1101 ;
    cd-dimension:timePeriod  ?year ;
    sdmx-measure:obsValue  ?observation ;
    sdmx-dimension:refArea  ?areacode .
?areacode  sacs:administrativeClass  sacs:Prefecture ;
           ic:表記  ?pref .
} ORDER BY DESC(?year) DESC(?observation)
【政令指定都市】
PREFIX g00200502-dimension:<http://data.e-stat.go.jp/lod/ontology/g00200502/dimension/>
PREFIX g00200502-code:<http://data.e-stat.go.jp/lod/ontology/g00200502/code/>
PREFIX cd-dimension:<http://data.e-stat.go.jp/lod/ontology/crossDomain/dimension/>
PREFIX sdmx-measure:<http://purl.org/linked-data/sdmx/2009/measure#>
PREFIX sdmx-dimension:<http://purl.org/linked-data/sdmx/2009/dimension#>
PREFIX sacs:<http://data.e-stat.go.jp/lod/terms/sacs#>
PREFIX ic:<http://imi.go.jp/ns/core/rdf#>
select  ?pref  ?city  ?year  ?observation
where {
?s  g00200502-dimension:indicator  g00200502-code:indicator-A1101 ;
    cd-dimension:timePeriod  ?year ;
    sdmx-measure:obsValue  ?observation ;
    sdmx-dimension:refArea  ?areacode .
?areacode  sacs:administrativeClass  sacs:DesignatedCity ;
           ic:表記  ?city ;
           sacs:prefectureLabel ?pref .
} ORDER BY DESC(?year) DESC(?observation)
【全ての市町村及び東京特別区】
PREFIX g00200502-dimension:<http://data.e-stat.go.jp/lod/ontology/g00200502/dimension/>
PREFIX g00200502-code:<http://data.e-stat.go.jp/lod/ontology/g00200502/code/>
PREFIX cd-dimension:<http://data.e-stat.go.jp/lod/ontology/crossDomain/dimension/>
PREFIX sdmx-measure:<http://purl.org/linked-data/sdmx/2009/measure#>
PREFIX sdmx-dimension:<http://purl.org/linked-data/sdmx/2009/dimension#>
PREFIX sacs:<http://data.e-stat.go.jp/lod/terms/sacs#>
PREFIX ic:<http://imi.go.jp/ns/core/rdf#>
select  ?pref  ?city  ?year  ?observation
where {
?s  g00200502-dimension:indicator  g00200502-code:indicator-A1101 ;
    cd-dimension:timePeriod  ?year ;
    sdmx-measure:obsValue  ?observation ;
    sdmx-dimension:refArea  ?areacode .
    { ?areacode  sacs:administrativeClass  sacs:DesignatedCity .} UNION
    { ?areacode  sacs:administrativeClass  sacs:CoreCity .} UNION
    { ?areacode  sacs:administrativeClass  sacs:City .} UNION
    { ?areacode  sacs:administrativeClass  sacs:SpecialCity .} UNION
    { ?areacode  sacs:administrativeClass  sacs:SpecialWard .} UNION
    { ?areacode  sacs:administrativeClass  sacs:Town .} UNION
    { ?areacode  sacs:administrativeClass  sacs:Village .}
    ?areacode  ic:表記  ?city ;
               sacs:prefectureLabel ?pref .
} ORDER BY DESC(?year) DESC(?observation)
全市区町村分を取得するクエリは、複数の自治体種別をUNIONで繋げているのがスマートでないが、これは統計LODの自治体情報のオントロジー構造の問題によるものであり、現状ではこうする他に手がない。次の「おまけコラム」で、その問題点について詳しく述べたので、改善していただけるとありがたい。

また、統計調査というものの性質上致し方ないことであるが、統計の種類により調査年が異なるのも利活用を難しくする一つの要因だ。最新年の情報のみ欲しい場合でも、一旦、すべての調査年の値を入手し、必要な年の値のみ抽出する必要がある。

最大のネックは、クエリが長くて処理が重すぎること。特に、全市区町村分を取得するクエリは、下手すると何分も待たされ、途中で寝てしまう。サーバに負荷をかけすぎて、他の利用者に迷惑をかけることにもなってしまう。
そこで、考えたのが以下のクエリ。(これは都道府県バージョン)
【一段目】都道府県のうち、北海道の調査年を取得
PREFIX g00200502-dimension:<http://data.e-stat.go.jp/lod/ontology/g00200502/dimension/>
PREFIX g00200502-code:<http://data.e-stat.go.jp/lod/ontology/g00200502/code/>
PREFIX sdmx-dimension:<http://purl.org/linked-data/sdmx/2009/dimension#>
PREFIX sac:<http://data.e-stat.go.jp/lod/sac/>
PREFIX cd-dimension:<http://data.e-stat.go.jp/lod/ontology/crossDomain/dimension/>
select ?year
where {
?s  g00200502-dimension:indicator  g00200502-code:indicator-A1101 ;
    sdmx-dimension:refArea  sac:C01000-19700401 ;
    cd-dimension:timePeriod  ?year .
} ORDER BY DESC(?year)
【二段目】都道府県の名称と統計調査の観測値を取得
PREFIX g00200502-dimension:<http://data.e-stat.go.jp/lod/ontology/g00200502/dimension/>
PREFIX g00200502-code:<http://data.e-stat.go.jp/lod/ontology/g00200502/code/>
PREFIX cd-dimension:<http://data.e-stat.go.jp/lod/ontology/crossDomain/dimension/>
PREFIX xsd:<http://www.w3.org/2001/XMLSchema#>
PREFIX sdmx-measure:<http://purl.org/linked-data/sdmx/2009/measure#>
PREFIX sdmx-dimension:<http://purl.org/linked-data/sdmx/2009/dimension#>
PREFIX sacs:<http://data.e-stat.go.jp/lod/terms/sacs#>
PREFIX ic:<http://imi.go.jp/ns/core/rdf#>
select  ?pref  ?observation
where {
?s  g00200502-dimension:indicator  g00200502-code:indicator-A1101 ;
    cd-dimension:timePeriod    "(一段目で取得した調査年をセット)"^^xsd:gYear ;
    sdmx-measure:obsValue  ?observation ;
    sdmx-dimension:refArea  ?areacode .
?areacode  sacs:administrativeClass  sacs:Prefecture ;
           ic:表記  ?pref .
} ORDER BY DESC(?observation)

上記のようにすると、二段階になり、一見遅くなるように思うが、全ての調査年を走査する必要がなくなるため、負荷が軽減され、結果として高速化される。しかしながら、これでもまだ重く、特に「全市区町村分」は途中で固まることもあり実用的ではない。
どの部分がボトルネックとなっているか調べた結果、『標準自治体コードをもとに、自治体名(市区町村、都道府県)を取得する部分』がかなり重いことが分かった。データセットを跨ぐと重くなるのだろうか。

(都道府県)
?areacode  ic:表記  ?pref .

(市区町村)
?areacode  ic:表記  ?city ;
             sacs:prefectureLabel ?pref .

上記の問題を解消するため、クエリをもう一段階分割し、三段構成とすることとした。
そのクエリは以下のとおり。(これは全市区町村バージョン)
【一段目】全自治体の標準自治体コードと、市区町村名称及び都道府県名称を取得
PREFIX sacs:<http://data.e-stat.go.jp/lod/terms/sacs#>
PREFIX ic:<http://imi.go.jp/ns/core/rdf#>
select ?areacode ?pref ?city
where {
?areacode  a  sacs:StandardAreaCode ;
           ic:表記  ?city ;
           sacs:prefectureLabel  ?pref .
} ORDER BY ?areacode

ホームページを開くと、上記【一段目】のクエリを自動的にエンドポイントへ送信し、全ての自治体の標準自治体コードと、対応する市区町村名、その上位自治体である都道府県名を取得し、クライアントPCのメモリにオブジェクトとして格納しておく。
このクエリはやや重いが、取得したオブジェクトは、ページを閉じたり、別のページに遷移するまではメモリに保持されるため、一度の取得で何度も使いまわしが可能だ。
メモリへの格納後、次に「札幌市」の調査年を取得、最後に観測値を取得する。
【二段目】市区町村のうち、札幌市の調査年の取得
PREFIX g00200502-dimension:<http://data.e-stat.go.jp/lod/ontology/g00200502/dimension/>
PREFIX g00200502-code:<http://data.e-stat.go.jp/lod/ontology/g00200502/code/>
PREFIX sdmx-dimension:<http://purl.org/linked-data/sdmx/2009/dimension#>
PREFIX sac:<http://data.e-stat.go.jp/lod/sac/>
PREFIX cd-dimension:<http://data.e-stat.go.jp/lod/ontology/crossDomain/dimension/>
select ?year
where {
?s  g00200502-dimension:indicator  g00200502-code:indicator-A1101 ;
    sdmx-dimension:refArea  sac:C01100-19731201 ;
    cd-dimension:timePeriod  ?year .
} ORDER BY DESC(?year)
【三段目】全市区町村の統計調査の観測値を取得
PREFIX g00200502-dimension:<http://data.e-stat.go.jp/lod/ontology/g00200502/dimension/>
PREFIX g00200502-code:<http://data.e-stat.go.jp/lod/ontology/g00200502/code/>
PREFIX cd-dimension:<http://data.e-stat.go.jp/lod/ontology/crossDomain/dimension/>
PREFIX xsd:<http://www.w3.org/2001/XMLSchema#>
PREFIX sdmx-measure:<http://purl.org/linked-data/sdmx/2009/measure#>
PREFIX sdmx-dimension:<http://purl.org/linked-data/sdmx/2009/dimension#>
PREFIX sacs:<http://data.e-stat.go.jp/lod/terms/sacs#>
select ?areacode ?observation
where {
?s  g00200502-dimension:indicator  g00200502-code:indicator-A1101 ;
    cd-dimension:timePeriod   "(二段目で取得した調査年をセット)"^^xsd:gYear ;
    sdmx-measure:obsValue  ?observation ;
    sdmx-dimension:refArea  ?areacode .
    { ?areacode  sacs:administrativeClass  sacs:DesignatedCity .} UNION
    { ?areacode  sacs:administrativeClass  sacs:CoreCity .} UNION
    { ?areacode  sacs:administrativeClass  sacs:City .} UNION
    { ?areacode  sacs:administrativeClass  sacs:SpecialCity .} UNION
    { ?areacode  sacs:administrativeClass  sacs:SpecialWard .} UNION
    { ?areacode  sacs:administrativeClass  sacs:Town .} UNION
    { ?areacode  sacs:administrativeClass  sacs:Village .}
} ORDER BY DESC(?observation)

上記クエリの結果がコールバックされたら、三段目で取得した「?areacode」と、一段目で取得済みの、メモリに格納してある標準自治体コード等の情報を Javascript でマッチングさせ、ブラウザ上に表示させる。
ブラウザ内でのマッチング作業に少し時間がかかるが、SPARQLサーバー上で行うよりもずっと高速だ。
Fusekiサーバー内でどのような処理が行われているか詳しいことは分からないが、重いクエリ一発で処理を行うより、軽いクエリを複数回組み合わせたほうが、結果として素早く処理が完了できるようだ。統計LODを利用したアプリケーション開発を考えておられる方には、このように細かくクエリを分割する手法をお勧めしたい。

余談だが、今回の統計LODリニューアル後のデータは、共通語彙基盤の語彙が多く使われており、その使いどころも、IPAの解説に近い形に手直しをされた。これは素晴らしい取組だと思う。その一方で、使われている共通語彙の名前空間URIが未だに「旧」であるところがイケてない(こちら参照)。速やかに新URIに修正していただきたいところだ。

0 件のコメント:

コメントを投稿