Zipf の法則というのは以下のようなものです。英語で書かれた長編小説を用意します(小説でなくてもいいんだけど)。そして、本文中に出てくる英単語を頻度順に並べます。すると、第2位の単語の頻度は第1位の単語の頻度の半分になります。第10位の単語の頻度は第1位の単語の頻度の1/10です。第100位の単語の頻度は第1位の単語の頻度の1/100です。そんな感じの法則です。リンク先にもあるように対数グラフにプロットするときれいな直線になります。
さて、Zipf の法則は日本語に対して当てはまるでしょうか。とはいっても、日本語は英語みたいに単語毎に区切ることが簡単ではないので、ここでは n-gram を使います。2文字毎に文を区切って、その2文字を単語だと思って頻度を数えます。ひらがなと漢字だけを対象にしました。日本語のデータとしてはこの日記の本文を使いました。
REG = /([ぁ-ん亜-腕]([ぁ-ん亜-腕]))/e H = Hash.new(0) def count(line) while REG =~ line word = $1 c = $2 H[word] += 1 line = c + (Regexp.last_match.post_match || '') end return line end def read_and_count(io) ret = '' io.each_line{|l| ret += l.chop ret = count(ret) } end def plot2(h) h = h.to_a.sort{|a, b| b[1] <=> a[1] } 500.times{|n| e = h[n] puts "#{n+1} #{e[1]}" } end read_and_count(ARGF) plot2(H)
結果です。横軸が順位、縦軸が頻度です。割ときれいな直線になっていると言えなくもないですね。英語の場合、直線の傾きはだいたい -1 になるそうです。しかし、この場合、直線の傾きは約 -0.734 です。この違いはどこから来るのでしょうか。英語と日本語の違い?
■追記(2006/8/21)。
最近のコメント