ジョイス「Ulysses」の語彙を測定する

wikipedia:Ulyssesによれば、ユリシーズの語彙は30030(出典 Analyzing Ulysses)である。しかしこの出典のリンクが死んでいて測定に使われたというプログラムのコードを読むことができないため、自分で調べることにした。

結論:だいたい30000くらいであってる。

0. まず総単語数を数え合わせる

Ulyssesの総単語数はwikipediaによると265000である。手始めにこれが正しいのかどうかを調べてみる。

print len(file("./ulysses.txt", "r").read().split()) # => 264965

オーケー。

1. 語彙を数え上げる(何も考えずに)

defaultdict(int)で辞書のkeyは0で初期化される。出現頻度も数え上げているけど今回は使わない。

from collections import defaultdict
words = defaultdict(int)
for line in file("./ulysses.txt", "r"):
    for word in line.split():
        words[word] += 1

print len(words) # => 49662

結果はユニークな単語が5万単語近くある、ということになり何かが間違っている気がする。
wordをprintすることにより原因を調べていく。

2. 語彙を数え上げる(少し考えて)

出力結果の一部を見ると次のようになっている。

...
dressinggown,
ungirdled,
was
sustained
gently
behind
him
on
the
mild
morning
air.
...

dressinggown,やungirdled,など、単純にsplitするだけではコンマなどが残る。
これらはコンマなしのdressinggownやungirdledとは別に辞書に登録されるため、単語数を余計に数え上げさせる要因になっていたのである。
ざっと眺めたところ、文中では次の記号が使われていることが分かった。

!?.,:-_ \"\'

これはstripにより取り除くことができる。また大文字小文字による差異も考慮してlowercaseを行う。

word = word.lower().strip("!?.,:-_ \"\'")

これによりlen(words)は31679になった。出典の値にだいぶ近くなったようだ。
それでも1000以上の誤差は大きいのだけれど、主要因はちょっと思いつかない。
一つ思い当たるのは数値や日付などがカウントされている点。試しに、

re.compile(r"\d+")

とマッチするwordを除いてみると200ほど減った。うーん。ここまで。

追記

セミコロン(;)およびカッコを除くのを忘れていた。これをstripに含めると30143になる。
問題点の見つけ方はwordsをsortedしてカウントが少ない単語を地道に調べるというやり方。

\(\)!?.,:;-_ \"\'

おまけ. この3万という語彙数は多いのか

Gutenbergにあるプルーストの『失われた時を求めて スワン家のほう』(English:Swann's way)は単語数195203で語彙は13714である。ユーゴーの『レ・ミゼラブル』は、単語数はUlyssesの2倍以上あるにもかかわらず(560911)語彙数では及ばない(25922)。これはもちろんプルーストユーゴーの語彙が少ないのではなく、ジョイスパラフレーズ等の技巧を駆使して意識的にさまざまな語を用いているということを示している。

※数値は上記プログラムにより計測した値です。

さて

ここまで単純作業しかやっていなくて辟易しています!
時間があったらもうちょっとマシな数学ツールを使って分析してみようか。