《傲慢与偏见》英文小说中各个单词出现的频率

起初想找一份英文单词文件,用于数据分析。没找到,​所以就想,找一本英文小说,将重复的单词去掉,几乎可以得到一份单词文件。本文以《傲慢与偏见》英文小说为例,统计小说中各个单词出现的次数。

1. 下载英文小说

我恰巧搜到《Pride and Prejudice》,将文件头尾无关部分删去。

2. 编写shell脚本

在博文《Linux Shell高级技巧(五)》中的统计英文文章中每个单词出现的频率,给出了SHELL源代码,稍加修改,本例SHELL源代码如下:

#!/usr/bin/env bash

# 1. 通过当前脚本的pid,生成awk脚本的临时文件名。
# 2. 捕捉信号,在脚本退出时删除该临时文件,以免造成大量的垃圾临时文件。
awk_script_file="/tmp/scf_tmp.$$"
count_words_file="/tmp/cwf_tmp.$$"
trap "rm -f $awk_script_file $count_words_file" EXIT
# 3. while循环将以当前目录下的testfile作为输入并逐行读取,在读取到末尾时退出循环。
# 4. getline读取到每一行将作为awk的正常输入。在内层的for循环中,i要从1开始,因为$0表示整行。NF表示域字段的数量。
# 5. 使$i作为数组的键,如果$i的值匹配正则表达式"^[a-zA-Z]+$",我们将其视为单词而不是标点。每次遇到单词时,其键值都会递增。
# 6. 最后通过awk脚本提供的特殊for循环,遍历数组的键值数据。
cat < < 'EOF' > $awk_script_file
BEGIN {
    while (getline < "Pride_and_Prejudice_count_words.txt" > 0) {
        for (i = 1; i < = NF; ++i) {
            if (match($i,"^[a-zA-Z]+$") != 0)
                arr[$i]++
        }
    }
    for (word in arr) {
        printf "%-*s\t%s\n", 20, word, arr[word]
    }
}
EOF

# 运行程序
awk -f $awk_script_file > $count_words_file
sort -k1,1n $count_words_file > count_words.txt

​正规表达式^[a-zA-Z]+$^[a-zA-Z]表示以小写或大写字母开头,+表示前面的字符至少重复一次,$表示结束(即也以小写或大写字母结尾)。细心的话,会发现,这样不够准确,因为少考虑了句子中最后一个单词的情况,如“me.”。 事实上,上述的代码很粗糙,很多情况没有考虑到,比如单复数、动词时态等。

3. 一些有趣的事

(1)共有多少单词

总行数      13044
总单词数    121598
总字符数    698013

不同的单词数只有5493(包括一个词的多种形式。如在本统计中look, looked, looking, looks算4个不同的词),如果把一个词的多种形式只算一个的话(如将look, looked, looking, looks算1个),那就更少了。但同时也应该注意到,一些常见单词并没有出现在小说中,如elephant。

(2)出现最多的词

词                      出现次数
to                      3767
the                     3655
of                      3289
and                     2992
a                       1746
was                     1673
her                     1672
I                       1650
in                      1634
that                    1293

可见,出现次数最多的词几乎是虚词,这也难怪,搜索引擎在切词时,要将虚词过滤。

(3)只出现i次的单词数

#出现次数                单词数
1                       2243
2                       841 
3                       488 
4                       313 
5                       219 
6                       158 
7                       116 
8                       122 
9                       62  
10                      67

很自然就想,单词分布会不会符合某种概率分布(如泊松分布、幂律分布)。下图的上半部分是单词出现次数,下半部分是单词出现次数为n的概述(如出现1次的单词有2243个,总单词数5493,所以概率是0.408338),右侧部分是左侧部分的放大。

pride_and_prejudice_all

从图形上看,蛮像服从幂律分布的图,但我也不确定。注:已将本文相关资料上传到GitHub,在这里.

2016/02/01更新:后来某天看到一个YouTube视频The Zipf Mystery,谈到了单词出现次数服从幂律故事。

Leave a Reply

Your email address will not be published. Required fields are marked *