LoginSignup
13
11

More than 5 years have passed since last update.

総務省統計局の地域メッシュを経緯度に変換してみる。

Last updated at Posted at 2015-04-21

これで市区町村の境界線を Google Maps にマッピング出来ると思ったけど、無理だった地域メッシュを経緯度に変換するメモ。

どうせだから GeoJSON で吐くようにした。

使用するデータは下記、総務省統計局の都道府県別に提供されている CSV データ:

上記 CSV データから経緯度を取得する計算方法は次のページを参考にした:

Gist はこちら:

例えば 東京都のメッシュコード から GeoJSON ファイルを出力する場合は、こんな感じのコマンドを叩く:

npm run convert ./city-mesh_13.csv 

すると、GeoJSON 形式の city-mesh_13.json が出力される。

コードはこんな感じ:

mesh2geojson.js
'use strict';

var fs = require('fs');
var path = require('path');

var _ = require('underscore');
var concat = require('concat-stream');
var csv = require('csv');
var GeoJSON = require('geojson');
var iconv = require('iconv');


// 地域メッシュを経緯度に変換
var latlng = function (_mesh) {
  var mesh = _mesh.toString();
  var mesh1 = mesh.slice(0, 4);  // 1 次メッシュ
  var mesh2 = mesh.slice(4, 6);  // 2 次メッシュ
  var mesh3 = mesh.slice(6, 8);  // 3 次メッシュ

  // 経度の度分秒
  var latDeg = parseInt(mesh1.slice(0, 2)) / 1.5;
  var latMin = parseInt(mesh2.slice(0, 1)) * 5;
  var latSec = parseInt(mesh3.slice(0, 1)) * 30;
  // 緯度の度分秒
  var lngDeg = parseInt(mesh1.slice(2, 4)) + 100;
  var lngMin = parseInt(mesh2.slice(1, 2)) * 7.5;
  var lngSec = parseInt(mesh3.slice(1, 2)) * 45;

  // 10 進数表記に変換
  var lat = ((latDeg * 3600) + (latMin * 60) + latSec) / 3600;
  var lng = ((lngDeg * 3600) + (lngMin * 60) + lngSec) / 3600;

  return [ lat, lng ];
};

var f = fs.statSync(process.argv[2]).isFile() ? path.resolve(process.argv[2]) : undefined;
var filein = fs.createReadStream(f);
var fileconv = new iconv.Iconv('Shift_JIS', 'UTF-8//TRANSLIT//IGNORE');
var fileout = fs.createWriteStream(f.replace(/\.csv$/, '.json'));

filein
  .pipe(fileconv)
  .pipe(csv.parse())
  .pipe(csv.transform(function (values) {
    return {
      code: parseInt(values[0]),
      name: values[1],
      coords: [ latlng(values[2]) ]
    };
  }))
  .pipe(concat(function (_data) {
    var data = _.reduce(_data, function (memo, item) {
      if (!_.isArray(memo)) return [ item ];
      var last = _.last(memo);
      if (last.code === item.code) {
        last.coords.push(item.coords[0]);
      } else {
        memo.push(item);
      }
      return memo;
    });
    var geoData = GeoJSON.parse(data, { 'MultiPoint': 'coords' });
    fileout.end(JSON.stringify(geoData));
  }));
package.json
{
  "name": "mesh2latlng",
  "author": "Yu I.",
  "license": "UNLICENSE",
  "scripts": {
    "convert": "node ./mesh2geojson.js"
  },
  "dependencies": {
    "concat-stream": "^1.4.8",
    "csv": "^0.4.1",
    "geojson": "^0.2.0",
    "iconv": "^2.1.6",
    "underscore": "^1.8.3"
  }
}
13
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
11