世界の測量

Sibling of "Relevant, Timely, and Accurate, " but much lighter and shorter ※自らの所属する組織の見解を示すものでない

MapReduce的ベクトルタイル作成(地価公示)Pt. 1

UNIXのsortを使って、TileStacheよりも原理的に早く、ベクトルタイルを作成する。狙うは、国土数値情報(地価公示)。小分けにして記録していく。これはその1回目。

原理

mapの出力でありsortの対象のデータは、古き良き「行指向」データである。形式は次の通り。

[z,x,y,payload].join("¥t"), "¥n"

reduceの結果として作成するデータはGeoJSONを想定するので、payloadは、GeoJSONのfeatureに対応するデータとする。タイル作成の処理コマンドは次のようにしていく。

$ ruby map.rb | sort | ruby reduce.rb

データ入手

国土数値情報 地価公示データの詳細からデータを入手する。平成25年度全国データを選択。3.54MB。展開すると、L01-13.shpが入手できる。

map.rb

map.rbを次のように作成した

require 'find'
require 'json'
require 'rubygems'
require 'geo_ruby'
require 'geo_ruby/shp'
include GeoRuby::Shp4r

module Math
  def self.sec(x)
    1.0 / cos(x)
  end
end

def process(r, z)
  n = 2 ** z
  lon_deg = r.geometry.x
  lat_rad = r.geometry.y * 2 * Math::PI / 360
  x = n * ((lon_deg + 180) / 360)
  y = n *
    (1 - (Math::log(Math::tan(lat_rad) + Math::sec(lat_rad)) / Math::PI)) / 2
  prop = {}
  r.data.attributes.each {|k, v|
    prop[k] = case v
    when 'true'
      true
    when 'false'
      false
    else
      s = v.encode('UTF-8', 'CP932')
      /^\d*$/.match(s) ? s.to_i : s
    end
  }
  f = {:type => 'Feature', :geometry => {:type => 'Point', 
    :coordinates => [r.geometry.x, r.geometry.y]}, 
    :properties => prop}
  print [z, x.to_i, y.to_i, JSON.dump(f)].join("\t"), "\n"
end

ShpFile.open('L01-13.shp') {|shp|
  shp.each {|r|
    18.upto(18) {|z| process(r, z)}
  }
}

実行例

$ ruby map.rb
18      221474  112784  {"type":"Feature","geometry":{"type":"Point","coordinates":[124.149335,24.346996],"properties":{"L01_001":5,"L01_002":2,"L01_003":5,"L01_004":2,"L01_005":"西暦 2013","L01_006":62800,"L01_007":1,"L01_008":false,"L01_009":false,"L01_010":false,"L01_011":false,"L01_012":false,"L01_013":false,"L01_014":false,"L01_015":false,"L01_016":false,"L01_017":47207,"L01_018":"石垣","L01_019":"沖縄県 石垣市新栄町70番12","L01_020":208,"L01_021":"住宅,店舗","L01_022":0,"L01_023":"RC2","L01_024":true,"L01_025":false,"L01_026":true,"L01_027":"美崎町バスターミナル","L01_028":1200,"L01_029":"近商,都市","L01_030":80,"L01_031":200}}}
18      221480  112785  {"type":"Feature","geometry":{"type":"Point","coordinates":[124.157169,24.345613],"properties":{"L01_001":0,"L01_002":2,"L01_003":0,"L01_004":2,"L01_005":"西暦 2013","L01_006":38800,"L01_007":1,"L01_008":false,"L01_009":false,"L01_010":false,"L01_011":false,"L01_012":false,"L01_013":false,"L01_014":false,"L01_015":false,"L01_016":false,"L01_017":47207,"L01_018":"石垣","L01_019":"沖縄県 石垣市字新川喜田盛14番1","L01_020":283,"L01_021":"住宅","L01_022":0,"L01_023":"RC1","L01_024":true,"L01_025":false,"L01_026":true,"L01_027":"美崎町バスターミナル","L01_028":800,"L01_029":"1住居,都市","L01_030":60,"L01_031":200}}}
...

国土数値情報(地価公示データ) 国土交通省

次回

次回は、上記の結果を sort でフィルタしたものを処理させる reduce.rb を解説する。