Google Chromeのabout:flagsを無効にして起動する

--no-experimentsオプションを指定してGoogle Chromeを起動すると,about:flagsの設定を一時的に無効にすることができる.

Mac OS Xの場合は,ターミナルで以下のコマンドを実行すればOK.

$ /Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --no-experiments

Chromeのabout:flagsで問題が発生した時はこの方法で起動し直し,about:flagsを開いて当該機能を無効にすれば何とかなるはず.

日本全国の地震の推移をggplot2で可視化する

RubyやRでスクリプトを書いて可視化してみた.

tenki.jpの地震情報を取得するRubyスクリプト (fetch_quake_info.rb)

以下は2011/3/11 0:00から現在時刻までのtenki.jp地震情報を取得するRubyスクリプト.Nokogiriを使ってスクレイピングする.

#!/usr/bin/env ruby
# -*- coding: utf-8 -*-

require "open-uri"
require "nokogiri"

puts "datetime\tplace\tmagnitude"

i = 1
cont = true
stop = Time.parse(ARGV[0] || "2011/03/11 0:00")

while cont
  doc = Nokogiri::HTML(URI("http://tenki.jp/earthquake/entries?p=#{i}").read)
  first = true
  doc.search("table#seismicInfoEntries/tr").each do |row|
    # skip the first row
    if first
      first = false
      next
    end

    entry = row.search("td").map{|e| e.text}
    entry[0].gsub!("", "/"); entry[0].gsub!("", "/"); entry[0].gsub!(/.+/, "")
    entry[1].gsub!("", ":"); entry[1].delete!("")
    entry[2].gsub!("", ":"); entry[2].delete!("")

    # datetime
    datetime = Time.parse("#{entry[0]} #{entry[2]}")
    if datetime < stop
      cont = false
      break
    end

    # place
    place = entry[3].gsub("---", "不明")

    # magnitude
    magnitude = entry[4][0] == ?M ? entry[4][1..-1].to_f : nil

    puts [datetime, place, magnitude].join("\t")
  end
  i += 1
end

以下のように実行すれば,2011/3/11 0:00から現在時刻までの地震情報を取得することができる.Ruby 1.9で動作確認済み.

$ ruby fetch_quake_info.rb > quake.tsv
$ head quake.tsv
datetime	place	magnitude
2011-03-19 19:41:00 +0900	茨城県南部	3.0
2011-03-19 18:57:00 +0900	不明	
2011-03-19 18:56:00 +0900	茨城県北部	6.1
2011-03-19 16:24:00 +0900	長野県中部	2.9
2011-03-19 16:14:00 +0900	長野県北部	2.3
2011-03-19 13:07:00 +0900	新潟県上越地方	3.3
2011-03-19 12:58:00 +0900	長野県北部	2.3
2011-03-19 12:08:00 +0900	福島県会津	2.9
2011-03-19 10:59:00 +0900	新潟県中越地方	2.0

なお,スクリプトを実行するとtenki.jpへのアクセスが発生するため,何度も実行して負荷をかけ過ぎたりしないように注意する必要がある.

Rのggplot2ライブラリによる可視化

Rを起動してデータの読み込みと整形を行う.

library(ggplot2)

# タブ区切りデータなのでread.delim関数を使う
d <- read.delim("quake.tsv")

# マグニチュードが欠損している行を取り除く
d <- d[!is.na(d$magnitude),]

# 日時の文字列をPOSIXctオブジェクトに変換する
d$datetime <- as.POSIXct(d$datetime)
地震の発生日時とマグニチュードの可視化

qplot関数をgeom = "bar", stat = "identity", position = "identity"で呼び出し,ヒストグラムライクな垂線プロットで可視化する.地震の発生時刻,マグニチュードの大きさ,発生頻度がひと目で分かって便利.

qplot(datetime, magnitude, data = d, color = I("red"),
  main = "Earthquakes in Japan (3/11 0:00 ~ 3/19 20:00)",
  geom = "bar", stat = "identity", position = "identity") +
  scale_x_datetime(format = "%m/%d")

震源地の情報を無視しているため,余震以外の地震もプロットされているので注意.

各日の地震のマグニチュードと回数の可視化

facetsパラメータを使えば,d$dateの値ごとにグラフを作ることができる(条件付きプロット).

# 日付のカラムを追加する
d$date <- as.Date(d$date, tz = "Asia/Tokyo")

# 各日のヒストグラムをプロットする
qplot(magnitude, data = d, color = I("red"),
  main = "Earthquakes in Japan (3/11 0:00 ~ 3/19 20:00)",
  facets = ~ date, binwidth = 0.5)

ここ数日の地震はそれほど減ってないように見える.

以上

Rubyによるスクレイピングやggplot2による可視化の例として参考になれば幸いです.

ggsave関数でggplot2のグラフをファイルに保存する

ggplot2で描画したグラフをファイルに保存するにはggsave関数を使う.

library(ggplot2)

p <- qplot(carat, price, data = diamonds, color = clarity)

# 描画して確認
print(p)

# PNG画像として保存
ggsave(file = "diamonds.png", plot = p)


解像度/画像サイズの指定

画像の解像度やサイズを指定するには,それぞれdpiパラメータ(pixel/inch),widthパラメータ(inch),heightパラメータ(inch)を使う.

p <- qplot(carat, price, data = diamonds, color = clarity)
ggsave(file = "diamonds.png", plot = p, dpi = 100, width = 6.4, height = 4.8)

上の例では,保存される画像の解像度は100dpi,画像サイズは幅6.4inches (= 640pixels),高さ4.8inches (= 480pixels).画像のピクセルサイズはdpiとインチの積となる.

解像度や画像サイズを指定しないで保存すると非常に大きなサイズの画像が生成される傾向があるみたいなので,小さい画像を作りたい場合はちゃんと手動でサイズを指定した方がいいだろう.

画像形式

保存される画像の形式はggsave関数がfileパラメータの拡張子を判別してよしなにやってくれる.ggplot2 ver 0.8.9で保存可能な画像形式は以下の通り.

  • eps/ps
  • tex (pictex)
  • pdf
  • jpeg
  • tiff
  • png
  • bmp
  • svg
  • wmf (Windowsのみ)

plotパラメータの省略

ggsave関数のplotパラメータには保存対象のggplotオブジェクトを指定するが,省略した場合はlast_plot関数の値が利用される.そのため,最後に描画した図を保存する場合はplotパラメータは省略できる.

qplot(carat, price, data = diamonds, color = clarity)
ggsave(file = "diamonds.png")

参考資料

ggsave関数のヘルプ.恐らくこれを読むだけで十分だと思う.

?ggsave

福島原発のγ線量測定データをggplot2で可視化してみた

東京電力が福島原発周辺におけるγ線量などの測定データをPDFで随時公開しているが,これを奥村先生がCSV形式に加工して配布なさっている.

http://oku.edu.mie-u.ac.jp/~okumura/stat/data/

このデータをRのggplot2ライブラリで可視化してみた.

CSVデータの特徴

各CSVファイルは以下のような形式になっている.

$ head fukushima1.csv
【別紙】福島第一原子力発電所モニタリングカーによる計測状況,,,,,,,,,
計測日,計測時間,計測場所,γ線,中性子線,風向,風速(m/s),,,
3月11日,午後5時30分,体育館付近,49nGy/h,-,-,-,,,
,午後5時40分,正門付近,56nGy/h,-,-,-,,,
,午後5時50分,管理棟,64nGy/h,-,-,-,,,
,午後6時45分,MP-6,56nGy/h,-,-,-,,,
,午後7時00分,MP-7,57nGy/h,-,-,-,,,
,午後7時10分,MP-5,55nGy/h,-,-,-,,,
,午後7時15分,MP-4,59nGy/h,-,-,-,,,
,午後7時20分,MP-3,59nGy/h,-,-,-,,,

線量のカラムには測定値の単位も含まれており,このままでは扱いづらい.また,データが欠損している時間帯もあるため,可視化の際にはそのような時間帯が一目で分かるようにすることが望ましい.

文字コード,改行コードの修正

fukushima*.csvの中身をlessやheadでちゃんと見られない場合は,ファイルの文字コードや改行コードがおかしい可能性がある.この場合はnkfを使って文字コードや改行コードを変換すれば大丈夫.

以下を実行すれば,文字コードを直して元のファイルを上書きすることができる.

$ nkf --overwrite fukushima1.csv

CSVファイル加工スクリプト (convert_fukushima.rb)

fukushima*.csvをRなどで扱いやすい形式に変換するためのRubyスクリプト(convert_fukushima.rb)を用意した.Gistはこちら

#!/usr/bin/env ruby
# -*- coding: utf-8 -*-

require "time"

puts %w[datetime mon day hour min place gamma neutron wind_dir wind_speed].join("\t")

lines = ARGF.each_line.to_a[2..-1]
date = ""
lines.each do |line|
  list = line.split(",")

  # date
  date = list[0].empty? ? date : list[0]
  date =~ /(\d+)\D+(\d+)/
  mon = $1
  day = $2

  # time
  time = list[1].gsub(/午後(\d+)/){$1.to_i + 12}
  time =~ /(\d+)\D+(\d+)/
  hour = $1
  min = $2

  # datetime
  datetime = "2011/#{mon}/#{day} #{hour}:#{min}"

  # place
  place = list[2].gsub("付近", "")

  # gamma
  gamma = list[3].to_f * (list[3].include?("μ") ? 1 : 1.0/1000)

  # neutron
  neutron = list[4].to_f * (list[4].include?("μ") ? 1 : 1.0/1000)

  # wind_dir
  wind_dir = list[5]

  # wind_speed
  wind_speed = list[6].chomp

  puts [datetime, mon, day, hour, min, place, gamma, neutron, wind_dir, wind_speed].join("\t")
end

使い方は以下の通り.

$ ruby convert_fukushima.rb fukushima1.csv > fukushima1.tsv

Ruby 1.8の場合は-Kオプションで文字コードを指定する必要があるかもしれない.

$ ruby -Ku convert_fukushima.rb fukushima1.csv > fukushima1.tsv

生成されたファイルはTSV形式(タブ区切り)となる.各列はそれぞれ日時,月,日,時,分,地点名,γ線量,中性子線量,風向,風量となっている.各線量の単位はμSv/h.

$ head fukushima1.tsv
datetime        mon     day     hour    min     place   gamma   neutron wind_dir        wind_speed
2011/3/11 17:30 3       11      17      30      体育館  0.049   0.0     -       -
2011/3/11 17:40 3       11      17      40      正門    0.056   0.0     -       -
2011/3/11 17:50 3       11      17      50      管理棟  0.064   0.0     -       -
2011/3/11 18:45 3       11      18      45      MP-6    0.056   0.0     -       -
2011/3/11 19:00 3       11      19      00      MP-7    0.057   0.0     -       -
2011/3/11 19:10 3       11      19      10      MP-5    0.055   0.0     -       -
2011/3/11 19:15 3       11      19      15      MP-4    0.059   0.0     -       -
2011/3/11 19:20 3       11      19      20      MP-3    0.059   0.0     -       -
2011/3/11 19:52 3       11      19      52      MP-6    0.057   0.0     -       -

ggplot2でγ線量を可視化

加工したデータを使って各地点のγ線量をggplot2で可視化してみる.

> library(ggplot2)

TSV形式のファイルはRのread.delim関数で読み込むことができる.

> d <- read.delim("fukushima1.tsv")
> head(d)
         datetime mon day hour min  place gamma neutron wind_dir wind_speed
1 2011/3/11 17:30   3  11   17  30 体育館 0.049       0        -          -
2 2011/3/11 17:40   3  11   17  40   正門 0.056       0        -          -
3 2011/3/11 17:50   3  11   17  50 管理棟 0.064       0        -          -
4 2011/3/11 18:45   3  11   18  45   MP-6 0.056       0        -          -
5 2011/3/11 19:00   3  11   19   0   MP-7 0.057       0        -          -
6 2011/3/11 19:10   3  11   19  10   MP-5 0.055       0        -          -

あらかじめ日時の文字列をPOSIXctオブジェクトに変換しておく.これをやっておかないとqplot関数で日時データを使ったプロットがうまくいかないので注意.

d$datetime <- as.POSIXct(d$datetime)

また,ggplot2の日本語文字化け対策を行っておく(参考:Using CJK Fonts in R and ggplot2 – Hi!!).

> quartzFonts(HiraMaru=quartzFont(rep("HiraMaruProN-W4", 4)))
正門付近のγ線量

まず,正門付近のγ線量のみをプロットする.ここではqplot関数を使ってみる.

  • x軸は経過時間(emin / 60で単位はhours),y軸はγ線量(単位はμSv/h)
  • geom,stat,positionを設定し,ヒストグラムライクの垂線プロットを行う(plot関数のtype = "h"と同じ)
  • scaleレイヤーで日時のフォーマットを指定する
  • 文字化け対策としてthemeレイヤーを追加する
> qplot(datetime, gamma, data = d[d$place == "正門",], color = I("blue"),
    geom = "bar", stat = "identity", position = "identity",
    xlab = "Date", ylab = "Gamma ray [μSv/h]") +
    scale_x_datetime(format = "%m/%d") +
    theme_grey(base_family="HiraMaru")

γ線量のピークが数ヶ所あり,特に最後のピークは飛び抜けて大きいことが分かる.また,何もプロットされていない時間帯は,その時間帯のデータがないことを示している.垂線プロットのおかげでデータが欠損している時間帯が一目で分かる.

測定地点ごとに色分け

次に,各測定地点のデータを色分けしてひとつのグラフで描画してみる.color(colour)パラメータを使えば地点ごとに色分けしたグラフを描画することができる.

> qplot(datetime, gamma, data = d, color = place,
    geom = "bar", stat = "identity", position = "identity",
    xlab = "Date", ylab = "Gamma ray [μSv/h]") +
    scale_x_datetime(format = "%m/%d") +
    theme_grey(base_family="HiraMaru")


測定地点ごとにグラフ分割

最後に,各測定地点を別々のグラフに分けて描画してみる.facetsパラメータを使えば地点ごとにグラフを分割して描画することができる.

> qplot(datetime, gamma, data = d, color = place, facets = ~ place,
    geom = "bar", stat = "identity", position = "identity",
    xlab = "Date", ylab = "Gamma ray [μSv/h]") +
    scale_x_datetime(format = "%d") +
    theme_grey(base_family="HiraMaru")

正門の線量のピークが大きすぎて,他の地点の線量の変化が分かりづらくなってしまった.軸などを工夫する余地がありそうだ.

以上

geom = "bar", stat = "identity", position = "identity"による垂線プロットは割と便利そうだ.覚えておこう.

Thanks, @koh_t, @y_benjo, @nozma, @takotakot, @syou6162, @a_bicky.

関連記事

id:koh-t さんもRのzooライブラリによる可視化を行っている.

参考資料

Tsukuba.R#9の開催/延期については16日(水)までにお知らせします

http://wiki.livedoor.jp/syou6162/d/Tsukuba.R%239

Tsukuba.R#9は3/20(日)に東京大学で開催する予定でしたが,東北地方太平洋沖地震の状況を鑑み,予定通りに開催するべきかどうかを検討中です.開催/延期については16日(水)までに決定してお知らせします.よろしくお願いします.

Rubyによるワンライナーのまとめ

Rubyでワンライナーを書く際によく使うコマンドライン引数と具体例をまとめてみた.

基本

-e : コマンドラインからスクリプトを指定

コマンドラインからスクリプトを指定する場合に使う.ワンライナーでは必須.

$ ruby -e 'puts "Hello, world!"'

行単位の処理

-n : 各行ごとに処理

プログラム全体が以下のwhileで囲まれているように動作する.

while gets
  ...
end

標準入力やファイルの各行に対して処理を行いたい場合に便利.getsの結果は$_に格納される.

$ ruby -ne 'puts $_ if $_.include?("mickey24")' foo.txt
-p : 各行ごとに処理&出力

-nとほぼ同様だが,各ループの最後で

print $_

が実行されるようになる.標準入力の各行に対して処理を行いつつ出力していく場合に便利.

$ ruby -pe '$_.upcase!' foo.txt
-l : 入力&出力の改行文字の自動処理

以下の2つの効果がある.

  1. $\が$/と同じ値になる.つまりprintの出力結果の末尾にgetsの行区切り文字(デフォルトは改行文字"\n")が付くようになる
  2. -nや-pがセットされている場合,getsで読み込まれた各行に対してString#chop!が呼び出される

getsで読み込んだ$_の末尾に"\n"が付いてほしくない時や,-pで出力される文字列に自動的に"\n"を付けてほしい時に使うとよさげ.

-a : オートスプリットモード

-nや-pと組み合わせて使う.オートスプリットモードがオンになり,各ループの先頭で

$F = $_.split

が実行されるようになる.

$ ruby -aple '$_ = $F.join(",")' foo.tsv

-aを使う場合は-lも組み合わせて使う方がいいだろう(-lがないとsplit結果の最後の要素にだけ改行文字が付いてしまう).

-Fregexp : splitの区切り文字の変更

入力フィールドセパレータ($;)にregexpを代入し,splitでデフォルトで使われる区切り文字を変更する.-aと組み合わせると便利.

$ ruby -F, -aple '$_ = "#{$F[0]}, #{$F[2]]}"' foo.csv

その他

-r feature : require

スクリプト実行前にfeatureをrequireする.

$ ruby -r base64 -e 'puts Base64.encode64("mickey24")'
-Kc : エンコーディングの設定

外部エンコーディングとスクリプトエンコーディングを設定する.指定できるエンコーディングは以下の通り.

  • -Ke : EUC-JP
  • -Ks : Windows-31J, CP932
  • -Ku : UTF-8
  • -Kn : ASCII-8BIT, BINARY
$ ruby -Ku -e 'puts "うさみみ"'
-i[extension] : 入力ファイルの上書き

入力ファイルを出力結果で上書きする.

$ ruby -i -pe '$_.gsub!("\r\n", "\n")' foo.txt

元のファイルを残しておく場合は-iの直後に拡張子を指定する.以下の場合は元のファイルがfoo.txt.bakとして保持される.

$ ruby -i.bak -pe '$_.gsub!("\r\n", "\n")' foo.txt

コマンドライン引数まとめ

-eコマンドラインからスクリプトを指定
-n各行ごとに処理
-p各行ごとに処理&出力
-l入力&出力の改行文字の自動処理
-aオートスプリットモード
-Fsplitの区切り文字の変更
-rrequire
-Kエンコーディングの設定
-i入力ファイルの上書き

具体例

foo.txtの各行に行番号を付けて標準出力に出力する.

$ ruby -ne '$l ||= 1; puts "#{$l}: #{$_}"; $l += 1' foo.txt

foo.txtの各行の"\r\n"を"\n"に置き換え,foo.txtを上書きする.

$ ruby -i -pe '$_.gsub!("\r\n", "\n")' foo.txt

ユーザ"mickey24"が保持するプロセスのIDを標準出力に出力する.

$ ps aux | ruby -anle 'puts $F[1] if $F[0] == "mickey24"'

カンマ区切りのfoo.csvの3列目が24以上の行のみ標準出力に出力する.

$ ruby -F, -anle 'puts $_ if $F[2].to_i >= 24' foo.tsv

以上

-n,-p,-aあたりが使えるようになると劇的にワンライナーを書きやすくなるので,是非マスターしておきたい.

ここで挙げたRubyのコマンドライン引数はPerlのそれとほぼ同じなので,これらのことを覚えておけばPerlでもワンライナーが書けるようになると思う.