2013年7月15日

東京の地価公示データを眺める

国土交通省はいくつかの数値情報を提供してくれていますが、 その中のひとつに「地価公示データ」があります。

全国のデータは2007年からの提供ですが、都道府県のデータは1983年から提供されていますので、 東京都の30年の地価のそれぞれを表現してみます。 なお、東京都全域だと広すぎるので、島嶼部は除きます。

作成したものは下記のページに置いてみました。

実装方法としては、こちらの記事のデータセットを変更したものになります。 GDAL のセットアップや d3.js を使った GeoJSON の描画については下記の記事やそのリンク先を参照してください。

データを取得する

まずはデータをダウンロードします。 データ形式は GML と Shape ファイルの2種類ですが、どちらも同じ ZIP に同梱されています。

国土数値情報 地価公示データ のダウンロード手順は分かりにくいかもしれませんが、「東京」のチェックを入れてダウンロードページへ進み、利用規約などを確認してから各年度の ZIP アーカイブをダウンロードします。

$ ls downloads/
L01-00_13_GML.zip  L01-08_13_GML.zip  L01-85_13_GML.zip  L01-93_13_GML.zip
L01-01_13_GML.zip  L01-09_13_GML.zip  L01-86_13_GML.zip  L01-94_13_GML.zip
L01-02_13_GML.zip  L01-10_13_GML.zip  L01-87_13_GML.zip  L01-95_13_GML.zip
L01-03_13_GML.zip  L01-11_13_GML.zip  L01-88_13_GML.zip  L01-96_13_GML.zip
L01-04_13_GML.zip  L01-12_13_GML.zip  L01-89_13_GML.zip  L01-97_13_GML.zip
L01-05_13_GML.zip  L01-13_13_GML.zip  L01-90_13_GML.zip  L01-98_13_GML.zip
L01-06_13_GML.zip  L01-83_13_GML.zip  L01-91_13_GML.zip  L01-99_13_GML.zip
L01-07_13_GML.zip  L01-84_13_GML.zip  L01-92_13_GML.zip

次に、これらを raw ディレクトリに展開します。

$ mkdir raw
$ cd raw/
$ for f in ../downloads/*.zip; do unzip $f; done

それぞれの ZIP アーカイブには次の5種類のデータが含まれています。 展開すると、それが30年分ある計算になります。

  • KS-META-L01-{YEAR}_13-g.xml: メタデータ
  • L01-{YEAR}_13-g.xml: GML 形式のデータ
  • L01-{YEAR}_13-g_LandPrice.dbf: Shape ファイルのデータベース
  • L01-{YEAR}_13-g_LandPrice.shp: Shape ファイルのメインファイル
  • L01-{YEAR}_13-g_LandPrice.shx: Shape ファイルの形状ファイル

なお、2012年からはファイル名が変更されており -g* の部分が取り除かれています。 文字エンコーディングも UTF-8 から Shift_JIS に変わっていますので、まとめて処理する場合は注意が必要です。

データを確認する

ogrinfo を使って Shape ファイルの情報を見ておきましょう。 3D Point の地物を表現しており、2606 の形状点が存在することが分かります。

$ ogrinfo -al L01-13_13.shp | head -n 8
INFO: Open of `L01-13_13.shp'
      using driver `ESRI Shapefile' successful.

Layer name: L01-13_13
Geometry: 3D Point
Feature Count: 2606
Extent: (139.098222, 27.094612) - (142.203304, 35.828359)
Layer SRS WKT:

属性情報は L01_001 から L01_031 までの31種類があります。 これらの意味は SHAPEファイルの属性について という別のエクセルで提供されています。 「土地関連」シートに地価公示の31属性の説明があります。

公示価格は L01_006 なので、これと住居表示の L01_019 を表示してみます。 ogrinfo-sql オプションを受け付けますので、SQL でフィールドを選択します。 (ターミナルの設定が UTF-8 の場合は iconvnkf などで変換しましょう。)

$ ogrinfo -sql "SELECT L01_006,L01_019 FROM 'L01-13_13'" L01-13_13.shp |
    iconv -f shift_jis -t utf-8 | head -n 40

これで住所と地価を確認できました。

次に、行政区域コード (L01_017) で制限をかけます。 東京都 (都道府県コードは13) の場合、 13101 から23区が始まり、13201 から市が始まり、13301 から村が始まります。 離島は 13320 より大きいものになります。 したがって、島嶼部を除くためには行政区域コードが 13320 より小さいものを指定します。 コード体系の詳細は Wikipedia の 全国地方公共団体コード を参照してください。

$ ogrinfo -sql "SELECT L01_006,L01_019 FROM 'L01-13_13' WHERE L01_017 < '13320'" L01-13_13.shp |
    iconv -f shift_jis -t utf-8 | head -n 40

データを変換する

ogr2ogr を使って Shape ファイルを GeoJSON に変換します。 基本形は以下の通りです。

$ ogr2ogr \
    -f GeoJSON \                 # 変換形式
    -where "L01_017 < '13320'" \ # フィルタ条件
    tokyo-landprice-2013.geojson \  # 出力ファイル名
    L01-13_13.shp                # 入力ファイル名

もっと細かく制御したい場合は SQL を書きます。 ここではフィールドを選択しフィールド名も変更しておきたいので、 以下の SQL を適用させます。 この Shape ファイルには属性がすべて String で保存されていますので、整数値のものは INTEGER にキャストします。

SELECT L01_017 AS city_code,
       L01_018 AS city_name,
       L01_019 AS address,
       L01_027 AS station,
       CAST(L01_028 AS INTEGER) AS distance_from_station,
       CAST(L01_006 AS INTEGER) AS price
FROM '{LAYER_NAME}'
WHERE L01_017 < '13320'

LAYER_NAME はファイルごとに異なります。 ここで扱っている Shape ファイルでは、拡張子を取り除いたものがレイヤー名称になります。 SQL は -sql オプションで与えますので、シェルで実行するコマンドは以下のようになります。

$ FIELDS="L01_017 AS city_code, L01_018 AS city_name, L01_019 AS address"
$ FIELDS=$FIELDS", L01_027 AS station, CAST(L01_028 AS INTEGER) AS distance_from_station"
$ FIELDS=$FIELDS", CAST(L01_006 AS INTEGER) AS price"
$ fpath=L01-13_13.shp
$ fname=`basename $fpath`
$ ogr2ogr -f GeoJSON \
    -sql "SELECT $FIELDS FROM '${fname%.shp}' WHERE L01_017 < '13320'" \
    tokyo-landprice-2013.json $fpath

データファイルは 1983 年からありますので、順次繰り返し実施します。 ひとつのファイルは 400kb から 950kb 程度の大きさになります。 市町村合併により市町村の数が変わることでファイルサイズも変わってきます。

$ for fpath in L01-{8,9}*.shp
do
    fname=`basename $fpath`
    ogr2ogr -f GeoJSON \
        -sql "SELECT $FIELDS FROM '${fname%.shp}' WHERE L01_017 < '13320'" \
        tokyo-landprice-19${fname:4:2}.geojson $fpath
done
$ for fpath in L01-{0,1}*.shp
do
    fname=`basename $fpath`
    ogr2ogr -f GeoJSON \
        -sql "SELECT $FIELDS FROM '${fname%.shp}' WHERE L01_017 < '13320'" \
        tokyo-landprice-20${fname:4:2}.geojson $fpath
done

2012年からはファイルの文字エンコーディングが違うようなので、 iconv で UTF-8 に統一しておきます。

$ for y in 2012 2013
do
    mv tokyo-landprice-$y.geojson $y.geojson
    iconv -f shift_jis -t utf-8 $y.geojson > tokyo-landprice-$y.geojson
    rm $y.geojson
done

これで Shape ファイルから GeoJSON ファイルへの変換ができました。 出来上がったファイルは geojson ディレクトリに移動しておきましょう。

$ mkdir ../geojson
$ mv *.geojson ../geojson/

データを表示する

d3.js を使うことで Web ブラウザでも GIS データを表示できます。

まずは HTML を作成し、d3.js のコードを読み込む環境を整えます。 Yeoman を使う場合は下記のように進めます。

$ yo webapp
$ bower install d3 --save
$ grunt server

これでテストサーバが立ち上がってブラウザのページも開きます。 d3.js は AMD 非対応なので、require.config で shim の設定を忘れないようにしましょう。(Yeoman 1.0beta から 1.0rc の間で、Bower のファイル名やディレクトリ名が変更されています。)

require.config({
    paths: {
        jquery: '../bower_components/jquery/jquery',
        bootstrap: 'vendor/bootstrap',
        d3: '../bower_components/d3/d3'
    },
    shim: {
        bootstrap: {
            deps: ['jquery'],
            exports: 'jquery'
        },
        d3: {
            exports: 'd3'
        }
    }
});

次に、描画用の関数を定義します。詳しくは D3.jsとTopoJSONで地図を作る を読んでください。

var width = 1150,
    height = 500;

function render(year) {

    $('#main').empty();
    $('td span').text('');
    d3.select('#address').text('地図上をクリックしてください');

    var g = d3.select('#main').append('svg')
                  .attr('width', width)
                  .attr('height', height)
                  .append('g');

    d3.json('tokyo-landprice-' + year + '.geojson', function(err, collection) {
        if (err) {
            $('#main').text('ファイルを読み込めませんでした。');
            return;
        }
        var projection = d3.geo.mercator()
                           .scale(60000)
                           .center(d3.geo.centroid(collection))
                           .translate([width / 2, height / 2]);
        var path = d3.geo.path().projection(projection);
        g.selectAll('path')
            .data(collection.features)
            .enter()
            .append('path')
            .attr('d', path)
            .style('fill', function(d) {
                // 地価に沿って色を変えるような処理を書いてください。
            })
            .on('click', function() {
                // クリック時の処理を書いてください。
            })
            ;
    });
}

あとは、描画用関数を呼び出す処理を記述します。

render(2013); // render the latest year by default

GeoJSON ファイルを index.html と同じディレクトリに配置すると多数のポイントを表示できるはずです。 (index.html には "id=main" となる要素が必要です。)

$ cp -p geojson/*.geojson app/

最後に、index.html に表示用の領域を用意し、地点をクリックしたときの処理を追加します。上記のコード例のコメント部分を埋めると、下図のようになります。

終わりに

東京都の地価公示データを地図形式で表示してみました。 静的な表示なのでズームイン/ズームアウトはできませんが、全体の傾向を見るにはひとまず十分だと思います。

そもそもの動機としては、引っ越し先をどこにしようかという思いでした。 中央線沿線の駅近くは高い、八王子と町田も意外と高い、という二点が個人的な発見でした。 23区と言っても、荒川を渡るかどうかで大きく違うようです。 感覚的には理解しているつもりでも、地図としてまとめて見ると分かりやすいですね。

また、30年分のデータを眺めてみると、1991年の地価高騰が目につきます。 23区の広域に渡って真っ赤になりますので、地価が100万円を超えていたことが分かります。 デジタルデータで土地バブルを振り返ることができ、いわゆるデータジャーナリズムの一端を垣間みることができました。スライダー機能を実装すると分かりやすいかもしれません。

Shape ファイルから GeoJSON に変換して d3.js で表示、という流れはとてもお手軽だと思います。 次は LeafletTopoJSON も使ってみたいですね。

コメントを投稿