読者です 読者をやめる 読者になる 読者になる

データ分析エンジニアが気まぐれに更新するブログ

勉強してきた技術などを適当に書いていければと思います。

Leaflef.jsとD3.jsでマップデータを可視化してみた

JavaScript D3.js データ可視化 Leaflet.js

Leaflet.js

Leaflet.jsというWebマップ表示ライブラリを知りましたので、使ってみました。


Leaflet.js : http://leafletjs.com/


結構前からあったそうな。


※画像をクリックするとページを移動します。


OpenStreetMapは知っていたけども、敷居が高そうと思っていましたが、たったこれだけのソースで表示できてしまった...。

function _map(){
  this.targetDivId = "map";
  this.leafletMap;
  this.viewLocation = {"lon": 139.691706, "lat": 35.689488}; 
  this.mapLink = '<a href="http://openstreetmap.org">OpenStreetMap</a>';
}
// _map draw
_map.prototype.draw = function(){
  this.leafletMap = L.map(this.targetDivId).setView([this.viewLocation.lat, this.viewLocation.lon], 4);
  L.tileLayer(
    "http://{s}.www.toolserver.org/tiles/bw-mapnik/{z}/{x}/{y}.png", {
      attribution: "&copy; " + this.mapLink + " Contributors",
      maxZoom: 18,
    }
  ).addTo(this.leafletMap);
  this.leafletMap._initPathRoot();
}

// init
function init(){
  var map = new _map();
  map.draw();
}


カスタマイズ性が低いとのことだけども、地図自体はカスタマイズする機会も少ないだろうし、基本的な可視化機能として、マーカーを置いたり、地形に色を塗ったりできるようです。

使いこなしていけば、いろんなことが出来るかもしれません。


D3.jsとの連携

ちなみにD3.jsとの連携も出来るようです。

実際に簡単にやってみたところ、このような感じになりました。


※画像をクリックするとページを移動します。

var map, svg, g;
function init(){
  map = L.map("map").setView([39.702053, 141.15448379999998], 6);
  L.tileLayer(
    "http://{s}.www.toolserver.org/tiles/bw-mapnik/{z}/{x}/{y}.png", {
    attribution: '&copy; <a href="http://openstreetmap.org">OpenStreetMap</a> Contributiors',
    maxZoom: 18,
  }).addTo(map);
  map._initPathRoot();
  svg = d3.select("#map").select("svg");
  g = svg.append("g");
  d3.json("data/japan.geojson", function(json){
    drawpolygon(json);
    d3.json("data/points.geojson", function(json){
      drawpoint(json);
    });
  });
}
function drawpolygon(json){
  var geojson = json.type == "Topology" ? topojson.feature(json, json.objects.ken) : json;
  var transform = d3.geo.transform({point: projectPoint});
  var path = d3.geo.path().projection(transform);
  featureElement = g.selectAll("path")
    .data(geojson.features)
    .enter()
    .append("path")
    .attr({
      "stroke": "#00AA11",
      "fill": "#AAFFAA",
      "fill-opacity": 0.4,
    });
  map.on("viewreset", update);
  update();
  function update (){
    featureElement.attr("d", path);
  }
  function projectPoint(x, y){
    var point = map.latLngToLayerPoint(new L.LatLng(y, x));
    this.stream.point(point.x, point.y);
  }
}
function drawpoint(json){
  json.features.forEach(function(d){
    d.LatLngObj = new L.LatLng(d.geometry.coordinates[1], d.geometry.coordinates[0]);
  });
  var circle = g.selectAll("circle")
    .data(json.features)
    .enter()
    .append("circle")
    .attr({
      "stroke": "black",
      "stroke-width": 1,
      "opacity": 0.7,
      "fill": "red",
      "r": 10,
    });
  map.on("viewreset", update);
  update();
  function update(){
    circle.attr("transform", function(d){
      return "translate(" + map.latLngToLayerPoint(d.LatLngObj).x + "," + map.latLngToLayerPoint(d.LatLngObj).y + ")";
    });
  }
}


いやいや十分でしょ!

あとは、D3.jsのスケール関数とかで色の濃淡や、ポイント円の大きさでデータを表示もできますし、ポイント間に線を引っ張ることもできますし。

2D地図のオーバーレイ可視化で良いのならば、かなり多彩な表現が可能なのでは...。

D3.jsでgeojsonやtopojsonを読み込んで地形を表示して頑張る必要はなかったらしい笑

まあ、デザイン性を追求するならば、自前で頑張るのも良いかもしれませんが、しかし、拡大・縮小で自動的に地名や境界線などの粒度も調整してくれる地図クライアントツールってところは大きいですねー。

うーん、これで色々格好良くて、便利に可視化してみたいです。

統計検定を受験してみた

タイトルの通りです。

統計検定を受験してきました。


統計検定:http://www.toukei-kentei.jp


レベルは準1級を受けてみましたが...、


落ちました!←


試験1週間前に過去問をやってみるという舐めプレイ笑

どんな感じなのかと思っていましたが、結構難しくて、半分くらいしか分かりませんでした。

全然慣れも足りなくて、時間も全然足りなかったですし...。

確率や仮説検定などはともかく、多変量解析らへんがちょっと勉強しないと無理っすねー。

しかし、どの書籍で勉強すれば良いのだろうか?

ただ、手応えとして合格は無理ではないと思いましたので、また来年しっかり勉強して受けてみたいですね。

D3.jsでよくあるツリーレイアウトの可視化をしてみた

D3.js データ可視化 JavaScript

「よくある」ってなんだよって感じではありますが…。

ひとまず例のサイトがありますので、こちらになります。

例:http://bl.ocks.org/mbostock/1093025

これを見ていて、よく端末内のディレクトリ構成と容量を同時に表示しているような感じにしてみようと思い、例のソースコードを参考にしながら作ってみました。

データが適切なものがなかったので、都道府県のデータになりますが、階層構造を持つデータを下に開いていくツリーレイアウトです。

量の部分には、政府統計の平成22年の国勢調査から人口データを拝借しました。


※画像をクリックするとページを移動します。


こんな感じ!

人口を長さに置き換えて、パーセンテージで表示しました。

こうしてみると、たとえ東京の人口でも、日本全体の人口の約10%程度なんですねー。

個人的には思ったより少ない印象を受けました。

都道府県人口データを地形の高さに可視化してみた

D3.js Three.js データ可視化 JavaScript

明けましておめでとうございます。

表題の通り、今回は都道府県人口データを、D3.jsとThree.jsの日本地図に、都道府県ごとの地形の高さに表してみました。

地形の色の濃淡で表すのは、国勢調査の封筒の裏にも描いてあるくらいよく見ますけど(ちなみにコロプレスマップというらしいです)、「地形の高さにも表したら二重で表せるじゃん!」と思ってやってみたら、意外といけました。


画像をクリックするとページを移動します。



見づらいっすね←



今年もどうぞ、よろしくお願い申し上げます。

MeCabの新語辞書「MeCab-ipadic-NEologd」について

MeCab

備忘録も兼ねるのですが、形態素解析器のMeCabに、「MeCab-ipadic-NEologd」という素晴らしい新語辞書がありますので、その使い方について記します。


MeCab-ipadic-NEologd : https://github.com/neologd/mecab-ipadic-neologd


MeCab-ipadic-NEologdのインストールは下記で可能。

[root]# git clone https://github.com/neologd/mecab-ipadic-neologd.git
[root]# cd mecab-ipadic-neologd/
[root]# ./bin/install-mecab-ipadic-neologd --create_user_dic


私はCentOSで動かしていて、MeCabyumからインストールしており、最初はmecab-configが見つからないと言われてしまいましたが、mecab-develをyumでインストールすれば大丈夫でした。

[root]# which mecab-config
/usr/bin/which: no mecab-config in (/root/.pyenv/shims:/root/.pyenv/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/root/bin:/usr/local/rbenv/bin:/usr/local/rbenv/shims)
[root]# yum -y install mecab-devel
[root]# which mecab-config
/usr/bin/mecab-config


MeCab-ipadic-NEologdが正常にインストールできましたら、辞書を指定してMeCabを実行します。

デフォルトと比べるとこんな感じに、今風の単語は固有名詞として認識してくれます。

[root]# echo 魔法少女まどか☆マギカ | mecab
魔法 名詞,一般,*,*,*,*,魔法,マホウ,マホー
少女 名詞,一般,*,*,*,*,少女,ショウジョ,ショージョ
まどか 名詞,固有名詞,人名,名,*,*,まどか,マドカ,マドカ
☆ 記号,一般,*,*,*,*,☆,☆,☆
マギカ 名詞,固有名詞,組織,*,*,*,*
EOS
[root]# echo 魔法少女まどか☆マギカ | mecab -d /usr/lib64/mecab/dic/mecab-ipadic-neologd
魔法少女まどか☆マギカ 名詞,固有名詞,一般,*,*,*,魔法少女まどか☆マギカ,マホウショウジョマドカマギカ,マホーショージョマドカマギカ
EOS
[root]# echo とある科学の超電磁砲 | mecab
とある 連体詞,*,*,*,*,*,とある,トアル,トアル
科学 名詞,一般,*,*,*,*,科学,カガク,カガク
の 助詞,連体化,*,*,*,*,の,ノ,ノ
超 接頭詞,名詞接続,*,*,*,*,超,チョウ,チョー
電磁 名詞,一般,*,*,*,*,電磁,デンジ,デンジ
砲 名詞,接尾,一般,*,*,*,砲,ホウ,ホー
EOS
[root]# echo とある科学の超電磁砲 | mecab -d /usr/lib64/mecab/dic/mecab-ipadic-neologd
とある科学の超電磁砲 名詞,固有名詞,一般,*,*,*,とある科学の超電磁砲,トアルカガクノレールガン,トアルカガクノレールガン
EOS


超電磁砲」も「レールガン」という風に、読み方も補完されています!


辞書も更新されていくみたいなので、下記コマンドでアップデートします。

[root]# ./bin/install-mecab-ipadic-neologd -n


毎月更新をしていくとのことなので、月末にcronで自動アップデートするようにしておきました。

50 23 28-31 * * /usr/bin/test $( date -d '+1 day' +\%d ) -eq 1 && /root/mecab-ipadic-neologd/bin/install-mecab-ipadic-neologd -n -y > /dev/null 2>&1

性別、職業別、趣味別の行動者数データを対応分析してみた

R Ruby データ分析

やってはみたけど、どうなんでしょう?

政府統計データのいろんな地域別のデータを眺めながら、先日のマップ可視化に乗せるだけでも面白いなぁとか思っていたのですが、例えば、タイトルの通りの集計データから、業種別で趣味の傾向があるのかどうか、見えたりするのかとか思ったので、やるだけやってみました。


性別、職業別、趣味別の行動者数データ :
https://www.e-stat.go.jp/SG1/estat/GL08020101.do?_toGL08020101_&tstatCode=000001050585&requestSender=search


上記のダウンロードして、簡単にデータ部分だけCSVで切り取りまして、下記の構造のデータを用意しました。

data.csv の構造

趣味1趣味2...趣味m
総数職業1データ
職業2
...
職業n
職業1
職業2
...
職業n
職業1
職業2
...
職業n


Rプログラムを以下のようにしておきます。コマンドラインからファイル名を指定して実行できるようにしたいので、commandArgsで引数を取れるようにしました。

corresp.R

library(MASS)
argv <- commandArgs(T)
input_file <- argv[1]
nf <- as.numeric(argv[2])
data <- read.table(input_file, sep=",", header=T, row.names=1)
data.corresp <- corresp(data, nf=nf)
f <- paste(input_file, "png", sep=".")
png(f)
biplot(data.corresp)
dev.off()


Rubyで実行します。(Rで多重クロス集計表をそのまま多重対応分析する方法もあるらしいのですが、よく分かりませんでした!)

ruby exec.rb

exec.rb

# -*- coding: utf-8 -*-
require "fileutils"
col_names = Hash.new()
row_names = Hash.new()
all_data = Array.new()
man_data = Array.new()
woman_data = Array.new()
input_file = "data.csv"
col_names_file = "col_names"
row_names_file = "row_names"
all_file = "all.csv"
man_file = "man.csv"
woman_file = "woman.csv"
FileUtils.safe_unlink([col_names_file, row_names_file, all_file, man_file, woman_file, all_file + ".png", man_file + ".png", woman_file + ".png"])
sex = ""
File.open(input_file, "r:Shift_JIS:UTF-8") do |f|
  cnt = 0
  while line = f.gets
    cnt = cnt + 1
    arr = line.gsub(/(\r|\n)/, "").split(",")
    sex_tmp = arr.shift
    if cnt == 1
      arr.each_with_index do |a, i|
        col_names[a.gsub(/.*?|【千人】/, "")] = i == 0 ? "" : "C" + i.to_s
      end
      next
    end
    sex = sex_tmp if sex_tmp != "" && sex_tmp != sex
    case sex
    when "総数" then all_data.push(arr) 
    when "" then man_data.push(arr)
    when "" then woman_data.push(arr)
    end
  end
end
all_data.each_with_index do |row, i|
  row_names[row[0].gsub(/うち|従事者/, "")] = "R" + (i + 1).to_s
end
nf = col_names.size - 1 < row_names.size ? col_names.size - 1 : row_names.size
[all_data, man_data, woman_data].each do |data|
  data.each do |row|
    row.collect! do |d|
      d = d.gsub(/うち|従事者/, "").gsub("-", "0")
      d = d.match(/^[0-9]+$/) ? d + "000" : row_names[d]
    end
  end
  data.unshift(col_names.values)
end
[[all_data, man_data, woman_data], [all_file, man_file, woman_file]].transpose.each do |data, file|
  data.each do |row|
    File.open(file, "a") do |f|
      f.puts(row.join(","))
    end
  end
end
col_names.delete("")
[[col_names, row_names], [col_names_file, row_names_file]].transpose.each do |names, file|
  names.each do |key, value|
    File.open(file, "a") do |f|
      f.puts(value + ":" + key)
    end
  end
end
[all_file, man_file, woman_file].each do |file|
  cmd = "Rscript corresp.R " + file + " " + nf.to_s
  res = system(cmd)
end
exit


結果、行名と列名、各プロット図が以下の通りになりました。

col_names

C1:スポーツ観覧
C2:美術鑑賞
C3:演芸・演劇・舞踊鑑賞
C4:映画鑑賞
C5:音楽会などによるクラシック音楽鑑賞
C6:音楽会などによるポピュラー音楽・歌謡曲鑑賞
C7:CD・テープ・レコードなどによる音楽鑑賞
C8:DVD・ビデオなどによる映画鑑賞
C9:楽器の演奏
C10:邦楽
C11:コーラス・声楽
C12:邦舞・おどり
C13:洋舞・社交ダンス
C14:書道
C15:華道
C16:茶道
C17:和裁・洋裁
C18:編み物・手芸
C19:趣味としての料理・菓子作り
C20:園芸・庭いじり・ガーデニング
C21:日曜大工
C22:絵画・彫刻の制作
C23:陶芸・工芸
C24:写真の撮影・プリント
C25:詩・和歌・俳句・小説などの創作
C26:趣味としての読書
C27:囲碁
C28:将棋
C29:パチンコ
C30:カラオケ
C31:テレビゲーム・パソコンゲーム
C32:遊園地,動植物園,水族館などの見物
C33:キャンプ
C34:その他

row_names

R1:農林漁業
R2:管理的職業
R3:専門的・技術的職業
R4:事務
R5:販売
R6:サービス職業
R7:保安職業
R8:生産工程
R9:輸送・機械運転
R10:建設・採掘
R11:運搬・清掃・包装等

all.csv.png
f:id:itoeiji110704:20151018192552p:plain

man.csv.png
f:id:itoeiji110704:20151018192553p:plain

woman.csv.png
f:id:itoeiji110704:20151018192554p:plain


ちょっと項目多くて、わけわかんないことに…。

総数の方は見ていると、全体としてなんとなく職業に対する年齢層の割合との関連が薄っすらと見えるようにも感じました。

R7とC29が近いのはなんでなん?笑

しかし、女性がなんでこんなに広がり具合が違うんだろう?

R1に対して、C12やC20が比較的近い目のはなんとなく頷ける気がします。

とりあえず、これはこれで眺めながら、また色々と考えてみようと思います。

D3.jsとThree.jsで日本地図を可視化してみた2

D3.js データ可視化 Three.js JavaScript

上記の前回記事では、D3.jsとThree.jsを使って日本地図を描画しました。


D3.js : http://d3js.org/

Three.js : http://threejs.org/


そこからさらに勉強を進めまして、より3Dに描画できるようになりましたので、データものせて作ってみました。


※画像をクリックするとページを移動します。


ちなみに色やウインドウの形状は、あるアニメっぽく作ってみました。*1

近未来っぽくてカッコイイ感じなのに惚れまして笑


前回は日本地図をHTML5CanvasとしてD3.jsで描画して、テクスチャとしてThree.jsのオブジェクトに貼り付ける方法を取っていました。

結局その方法をやめて、D3.jsのpathメソッドやtopojsonなどで描画する地形の座標を解析して、Three.jsのオブジェクトの座標として扱うようにして、描画をする部分に関しては完全にThree.jsに任せるようにしました。

データは、国土交通省の「航空旅客動態調査」からお借りしました。


国土交通省の「航空旅客動態調査」(平成25年度) : http://www.mlit.go.jp/koku/koku_tk6_000001.html


使わせてもらっといて言うのもなんですが、PDFでしたので、データの整備が結構大変でした。

公開されているデータでも、こういう形式だとなかなか扱いづらいです。


出発空港と行き先空港を放物線で繋いで、乗客数を行き先空港地点に円の半径の大きさとして表して描画してみましたが、結局値に差がありすぎる関係で、乗客数が1000人を超えないと、円を描いているのかすらわからない状態に…。

人口データなどはやっぱり定番ですので、ちょっと面白いものにと思って走ってみた結果、ただの遊ぶ道具になってしまった感はあります。


ちなみに、前回記事やここら辺までのことをThree.jsでやるとなると、それなりに勉強する参考書などがあれば良いですが、私の場合は下記を参考にしましたので、紹介します。