统计词话配图

不知道这个标题是否有足够的吸引力把你骗进来。如果你认为统计是一个到处充满了期望方差分布回归随机多元和概率的东西,那么……你可能是对的,不过本文想要告诉你的是,你其实还可以用统计来做一些你关心的事情,比如现在,我们既谈风月,也谈统计。:D

相信大家对宋词都不会陌生。无论你是否喜欢,总还是可以吟诵出几句名篇来的。如果你经常找一些宋词来读的话,你可能会发现一个有趣的现象,那就是有些词语或意象似乎特别受到词人的青睐,像是东风,明月,芳草等等。当然,对于这个现象,不同的人有不同的看法。一种观点是这些意象往往具有特定的含义,或是抒发离恨,或是寄托相思,总之是把人们的情感倾注在了这些最常见的事物之中,让人触景生情;而另一种看法则觉得词的雕琢痕迹太明显,内容也相对单调,使得用词容易造成重复。本文当然不是来探讨这些话题的,而是想用统计的方法来给大家展示一下究竟有哪些话语被词人一次一次地书写,被读者一遍一遍地传唱。

从统计的角度来看,上面这个问题其实非常简单,无非就是计算一下宋词之中词语出现的频率,然后做一个排序就可以了。但这个问题对于中文来说恰恰是最难攻克的一个环节。在英语中,词语与词语之间有着天然的分隔符,但对于中文,只有句子之间有标点符号,句子之内只能通过词语的含义来进行辨别。这也就是为什么在文本挖掘领域中,中文的分词依然是一个富有挑战性的任务的原因。

不过好在宋词本身的形式帮了我们很大的忙。首先,宋词的句子一般都非常短,这相当于已经有了一次粗略的词语划分;其次,宋词的用词也很简洁,一个词一般是两个字,偶尔可能有三个字、四个字,超过四个字的词就非常罕见了。于是我们就有一种比较“野蛮”的做法,来对宋词中的用词进行划分。

举个例子来说,《青玉案》中的这句“东风夜放花千树”,如果把所有可能的两个字的组合列出来,就是:

东风  风夜  夜放  放花  花千  千树

如果再把三个字的可能组合列出来,则有:

东风夜  风夜放  夜放花  放花千  花千树

如果不考虑其它的可能,那么总共就有11个词语。当然,这其中会有很多无意义的组合,但是我们可以预想的是,这些无意义的组合将不太可能大规模地重复出现,因此在排序的过程中它们自动地就被排在高频词语之后了。通过这种做法,宋词中的每句话大体都能分成10个左右的词语单位,然后对所有的这些词语单位进行频数统计,就可以得到最终的高频词语列表了。

下面就通过一段R程序来进行一次实际的分析,用到的数据是从网络上整理的《全宋词》电子资料,其中可能有部分字词不正确。完整的程序和数据可以从这里下载

首先,当然是读取数据。

txt=read.csv("SongPoem.csv",colClasses="character");

接下来提取出宋词的内容,并根据标点符号对句子进行分割。

sentences=strsplit(txt$Sentence,",|。|!|?|、");
sentences=unlist(sentences);
sentences=sentences[sentences!=""];

对句子进行分割后需要检查一遍,如果有些句子的长度超过了15个字,那么很可能是错误的字符,应该剔除掉。

s.len=nchar(sentences);
sentences=sentences[s.len<=15];
s.len=nchar(sentences);

下面的这个函数非常重要,其作用就是按照之前的做法把所有可能的字的组合计算出来。这里只是考虑了两个字的组合。

splitwords=function(x,x.len) substring(x,1:(x.len-1),2:x.len);

接下来就好办了,无非就是应用上面的函数对句子进行拆分,然后统计词频并排序。

words=mapply(splitwords,sentences,s.len,SIMPLIFY=TRUE,USE.NAMES=FALSE);
words=unlist(words);
words.freq=table(words);
words.freq=sort(words.freq,decreasing=TRUE);
words.freq[1:100];

最后的结果如下:

排序  词语    频数          排序  词语    频数
1     □□     1584         51    匆匆    357
2     东风    1379         52    芙蓉    356
3     何处    1231         53    今日    354
4     人间    1164         54    扁舟    351
5     风流    843          55    西湖    350
6     归去    818          56    憔瘁    349
7     春风    800          57    消息    347
8     西风    782          58    桃花    343
9     归来    768          59    何事    335
10    江南    760          60    一片    333
11    相思    759          61    神仙    332
12    梅花    725          62    一声    331
13    千里    668          63    黄花    330
14    多少    653          64    心事    330
15    回首    649          65    鸳鸯    328
16    如今    647          66    十分    327
17    明月    646          67    人生    324
18    阑干    632          68    断肠    323
19    年年    605          69    佳人    323
20    万里    587          70    长安    321     
21    一笑    579          71    东君    319     
22    黄昏    561          72    桃李    319     
23    当年    537          73    而今    318     
24    芳草    533          74    为谁    317     
25    天涯    531          75    无情    307     
26    相逢    523          76    去年    306     
27    尊前    519          77    天气    306     
28    一枝    510          78    不是    305     
29    风雨    500          79    海棠    305     
30    流水    481          80    少年    305     
31    风吹    474          81    今夜    304     
32    依旧    469          82    不似    303     
33    多情    458          83    十年    303     
34    风月    452          84    行人    300     
35    当时    451          85    谁知    300     
36    故人    445          86    寂寞    299     
37    斜阳    444          87    肠断    297     
38    无人    443          88    江上    297     
39    不知    426          89    悠悠    297     
40    深处    424          90    富贵    295     
41    不见    416          91    时候    295     
42    时节    407          92    昨夜    295     
43    凄凉    404          93    几度    292     
44    平生    394          94    月明    292     
45    春色    393          95    何时    291     
46    无限    381          96    青山    291     
47    一点    374          97    蓬莱    290     
48    功名    366          98    往事    290     
49    杨柳    363          99    如何    287     
50    天上    361          100   惟有    287

需要解释一下的是,排在第一位的方框是词库中的一些出错的字符,直接略去即可。

至此,真相大白。至于这个结果意味着什么,就留给读者自己细细品读吧。

发表/查看评论