都道府県市区町村 メッセージ画面 を GNU R で読めるテーブルに変換する Ruby スクリプト

http://www.tctv.ne.jp/members/mkim/geography/city_population_2001.htm に関するはてブのエントリに次のようなコメントがありました:

# 2007年03月05日 http://www.hatena.ne.jp/users/ca/caramelly/profile_s.gif caramelly 地理 最新のは→http://uub.jp/rnk/rnk.cgi?T=c&S=jとかhttp://uub.jp/rnk/rnk.cgi?T=cktv&S=j

はてなブックマーク - Gov Capital » Gov Capital Investor Blog

この id:caramelly さんのコメントにある人口の最新データを取得し,GNU R で読めるテーブル形式に変換し標準出力へ吐く Ruby スクリプトを作りました.


スクリプトの内容は次のとおりです:

require 'iconv'
require 'open-uri'

PATTERN = Regexp.compile('<TR[^<]+<TH[^>]+>(\d+)</TH>' + # ランク
                         '<TD[^>]+>([^<]+)</TD>' +       # 都道府県名
                         '<TD[^>]+>([^<]+)</TD>' +       # 都市名
                         '<TD[^>]+>([^<]+)</TD></TR>')   # 人口

open(ARGV[0]) do |io|
  puts "Rank\tPref\tCity\tPop"

  while line = io.gets
    line = Iconv.conv('UTF-8', 'Shift_JIS', line)
    if line =~ PATTERN then
      rank, pref, city, pop = $1.to_i, $2, $3, $4.split(',').join('').to_i

      puts "#{rank}\t#{pref}\t#{city}\t#{pop}"
    end
  end
end

これを例えば city2tab.rb という名前で保存し,次のように実行することで HTML 内の人口データがタブ区切りのテキストデータに変換され,city.tab に保存されます:

$ ruby city2tab.rb 'http://uub.jp/rnk/rnk.cgi?T=c&S=j' > city.tab

変換したテキストデータを GNU R で使用するには次のようにします:

> city <- read.table("city.tab", header=T)
> plot(city$Pop ~ city$Rank, log="xy", type="l")

手始めに,ランクと人口の関係を両対数プロットしてみました.結果は次の画像です:

こうして,いとも簡単に人口ランクの Zipf 則を確認することができました.

都道府県毎にプロットしてみると…

北海道内の都市だけを取り出してプロットするには次のようにします*1

> hokkaido <- city$Pref == "北海道"
> plot(city$Pop[hokkaido] ~ city$Rank[hokkaido], log="xy")

1位 (札幌市) と2位 (旭川市) の差が歴然としていますね.

続いて,東京都の都市だけを取り出してプロットしてみましょう:

> tokyo <- city$Pref == "東京都"
> plot(city$Pop[tokyo] ~ city$Rank[tokyo], log="xy")

東京都は,北海道と異なり,最下位都市まで綺麗なベキ分布を保っていますね.個人的にはどの都道府県でも分布にカットオフがあると予想していたので,この結果には驚きました!

その他いろいろ

都道府県毎の都市数も簡単に計算できます:

> rev(sort(table(city$Pref)))

  埼玉県   千葉県   北海道   愛知県   大阪府   茨城県   兵庫県   福岡県
      40       36       35       35       33       32       29       28
  東京都   静岡県   岐阜県   新潟県   長野県 神奈川県 鹿児島県   岡山県
      27       23       21       20       19       19       17       15
  栃木県   大分県   三重県   広島県   熊本県   京都府   福島県   長崎県
      14       14       14       14       14       14       13       13
  秋田県   滋賀県   山梨県   山口県   山形県   宮城県   岩手県   奈良県
      13       13       13       13       13       13       13       12
  群馬県   高知県   沖縄県   愛媛県   富山県   石川県   青森県   佐賀県
      12       11       11       11       10       10       10       10
和歌山県   福井県   宮崎県   徳島県   島根県   香川県   鳥取県
       9        9        9        8        8        8        4
>

埼玉県が最も多くの都市を持っているようですね.

まとめ

  • 都市の人口ランクデータを GNU R で読めるようなテキストデータに変換する Ruby スクリプトを作りました.
  • 実際に GNU R でデータを読み込み,全国規模の 人口ランクに関する Zipf 則を確認しました.
  • 同様に,北海道内,東京都内の都市に限定した人口ランクに関する Zipf 則を確認し,東京都はカットオフの無い分布を示していることが分かりました.
  • ついでに,各都道府県の都市数を計算してみました.

GNU R は手軽に統計処理ができるので,とても面白いですね.このエントリを読んで下さった皆さんも,是非やってみて下さいね.

補足

GNU R でのプロット結果を PNG 画像として保存するには次のようにします:

> png("ファイル名", width=画像の幅, height=画像の高さ)
> plot()
> dev.off()

例えば,上の全国規模でランクと人口をプロットした例では,実際に次のようにして画像を出力しています:

> png("cityrank.png", width=450, height=450)
> plot(city$Pop ~ city$Rank, log="xy", type="l")
> dev.off()

GNU R についての日本語での情報源は,http://www.okada.jp.org/RWiki/ が最良だと思います.

次の書籍は,GNU R の使い方を実問題をベースに学習するのに最適です:

The R Book―データ解析環境Rの活用事例集

The R Book―データ解析環境Rの活用事例集

また,次の書籍は,GNU R を実際に仕事や研究で使っている際に,使い方の逆引き辞典のように扱えて便利です:

The R Tips―データ解析環境Rの基本技・グラフィックス活用集

The R Tips―データ解析環境Rの基本技・グラフィックス活用集

*1:文字エンコーディングに注意して下さい.変換後のテキストデータは UTF-8 になっています.