脍炙《通鉴》
Submitted by kzeng on Sun, 2012-09-23 00:15(这是一篇关于很枯燥的技术,很枯燥的历史文本,和不太枯燥的统计的 blog)
看过一篇关于《全宋词》词频统计文章,挺有趣的,想用类似的方法处理一下《资治通鉴》,所以就趁周末花了几个小时作了一下。
词是长短句,统计两个字组成的词频比较合适,《通鉴》是古文,文字结构不同,所以我统计了单字频,两字词词频,三字词词频,四字词词频,和五字词词频。同时也记录各个统计单位(字或词)出现的卷数。《通鉴》294卷,从三家分晋到五代结束共共1362年,所以卷数可以作为时间的度量。
《全宋词》的词频是用 R 作的。R 虽然是不错的统计软件,也是我的最爱之一,但是 R 并不适合作文本分析,更不适合来作数据库操作。所以就用了 C# 和 Kdb +3.0。 C# 用来分析文本,.Net 是懒人的福音,并且多线程运算非常简单,能够大大提升文本处理速度,Kdb+用来储存数据,它差不多是性能最好的 in-memory 数据库了,从它的网站上能下载到免费版本。这个分析里数据库是重头戏,因为需要查询数百万行的数据 row,如果用 MySQL,估计会龟速到死。另外 Kdb + 本身只有 300多K,不用安装,很方便。还有就是 Kdb+ 的 Q 语言也能满足编程需要。
Kdb+ 的网站提供了各种语言 API 的源码,C# 的 API 不支持多线程,所以需要在适当的地方加锁。Kdb 唯一的问题是不支持 UTF-8。它用的是 UTF-7,所以在注入中文文字数据的时候可能会出现乱码,为了省事,从 C# 里 publish 数据的时候,直接 publish 为三字节的 int[] 了。query kdb 时用了一个免费的 GUI QPad。QPad 似乎是用 Java 写的,它的编码默认是 UTF-8,所以在 query Kdb 的时候直接把三字节的 int vector cast 成 char,在 QPad 里显示的就是中文了,所以也很方便。
产生数据的 C# 代码非常简单,发布数据的时候自动生成 Kdb 的 schema。使用的《资治通鉴》的文本是网上广为流传的国学网简体版,在生成数据前,先用 C# 作了预处理,主要是用正则表达式替换掉了现代语言的“污染”(譬如:“后一页”,公元xxx年 等)
下表是各个字、词频的数据量:
类别 | 数据行数 |
单字 | 2,586,329 |
双字 | 2,102,023 |
三字 | 1,633,875 |
四字 | 1,221,713 |
五字 | 851,403 |
从上表看,《资治通鉴》应该有近两百六十万字。
单字的字频统计如下:
排名 | 字 | 次数 | 百分比 | 累积百分比 |
1 | 之 | 66087 | 2.56% | 2.56% |
2 | 以 | 39874 | 1.54% | 4.10% |
3 | 为 | 35677 | 1.38% | 5.48% |
4 | 不 | 34376 | 1.33% | 6.81% |
5 | 王 | 21578 | 0.83% | 7.64% |
6 | 曰 | 21279 | 0.82% | 8.46% |
7 | 于 | 20182 | 0.78% | 9.24% |
8 | 其 | 20100 | 0.78% | 10.02% |
9 | 人 | 19035 | 0.74% | 10.76% |
10 | 将 | 18209 | 0.70% | 11.46% |
11 | 军 | 18083 | 0.70% | 12.16% |
12 | 使 | 17160 | 0.66% | 12.82% |
13 | 州 | 16116 | 0.62% | 13.45% |
14 | 大 | 16031 | 0.62% | 14.07% |
15 | 子 | 15600 | 0.60% | 14.67% |
16 | 而 | 15558 | 0.60% | 15.27% |
17 | 上 | 15252 | 0.59% | 15.86% |
18 | 兵 | 14746 | 0.57% | 16.43% |
19 | 者 | 12826 | 0.50% | 16.93% |
20 | 有 | 12536 | 0.48% | 17.41% |
“之”字当之无愧的排在了第一位。第一个非虚词是“王”,它包含了姓和爵位,第一个动词是“曰”。“人”的频率也很高,“将”,“军” 在双字词频中也会遇到。“帝”字排名32,“后”字排名33。但是因为是简体字,“后”并不专指皇\王后。
下面是价值观念的排名:
排名 | 字 | 次数 | 百分比 |
152 | 义 | 3507 | 0.14% |
181 | 忠 | 3004 | 0.12% |
223 | 孝 | 2475 | 0.10% |
240 | 礼 | 2287 | 0.09% |
253 | 信 | 2190 | 0.08% |
294 | 仁 | 1935 | 0.07% |
767 | 智 | 694 | 0.03% |
义、忠、孝排名在前,智排名最后,倒正印证了司马温公那句话:“凡取人之术,苟不得圣人、君子而与之,与其得小人,不若得愚人。”当然这个数据里噪音很多。
另外还有很多有趣的东西,就不一一叙述了。下面看一下两个字的词频:
排名 | 词 | 最早卷数 | 次数 | 百分比 |
1 | 将军 | 1 | 6,176 | 0.29% |
2 | 刺史 | 21 | 4,790 | 0.23% |
3 | 州刺 | 21 | 4,110 | 0.20% |
4 | 节度 | 29 | 3,698 | 0.18% |
5 | 以为 | 1 | 3,479 | 0.17% |
6 | 度使 | 203 | 3,202 | 0.15% |
7 | 天下 | 1 | 2,972 | 0.14% |
8 | 尚书 | 20 | 2,742 | 0.13% |
9 | 太子 | 1 | 2,584 | 0.12% |
10 | 陛下 | 6 | 2,492 | 0.12% |
11 | 不能 | 1 | 2,375 | 0.11% |
12 | 不可 | 1 | 2,351 | 0.11% |
13 | 太后 | 3 | 2,165 | 0.10% |
14 | 皇帝 | 6 | 2,050 | 0.10% |
15 | 太守 | 5 | 2,010 | 0.10% |
16 | 大将 | 6 | 1,813 | 0.09% |
17 | 遣使 | 4 | 1,501 | 0.07% |
18 | 司马 | 1 | 1,480 | 0.07% |
19 | 二月 | 4 | 1,477 | 0.07% |
20 | 馀人 | 2 | 1,463 | 0.07% |
“将军”出现的频率最高,在第一卷里就出现了,“度史”显然是“节度使”里出现的,虽然在203卷才出现,但是它居然出现了3202次,唉,唐朝啊!“节度”一次出现的要比“节度使”早。“皇帝”一次最早在第6卷出现,其实那时还是昭襄王元年,但是因为文本中出现了“秦始皇帝上”。
两字地名出现的最多的是“长安”,排名43,最早出现在第5卷,不过那里的“长安”并不是长安城,而是赵国的长安君。“洛阳”其次,排名81,最早出现在第2卷,三家分晋不久,洛阳附近就成了三晋与秦国的战场。
三个字的词频:
排名 | 词 | 最早卷数 | 次数 | 百分比 |
1 | 州刺史 | 21 | 4102 | 0.25% |
2 | 节度使 | 210 | 3195 | 0.20% |
3 | 大将军 | 6 | 1547 | 0.09% |
4 | 平章事 | 203 | 933 | 0.06% |
5 | 同平章 | 203 | 901 | 0.06% |
6 | 十二月 | 4 | 704 | 0.04% |
7 | 之子也 | 13 | 700 | 0.04% |
8 | 十一月 | 7 | 686 | 0.04% |
9 | 部尚书 | 70 | 655 | 0.04% |
10 | 指挥使 | 254 | 578 | 0.04% |
比较有趣的是“之子也”,老子英雄儿好汉。
四字字频:
排名 | 词 | 最早卷数 | 次数 | 百分比 |
1 | 同平章事 | 203 | 900 | 0.07% |
2 | 仪同三司 | 49 | 403 | 0.03% |
3 | 都指挥使 | 254 | 374 | 0.03% |
4 | 日有食之 | 1 | 368 | 0.03% |
5 | 中书侍郎 | 73 | 325 | 0.03% |
6 | 节度使李 | 217 | 312 | 0.03% |
7 | 散骑常侍 | 69 | 308 | 0.03% |
8 | 开府仪同 | 79 | 300 | 0.02% |
9 | 府仪同三 | 79 | 283 | 0.02% |
10 | 御史大夫 | 9 | 281 | 0.02% |
鉴于“州刺史”在三字字频中频繁出现,所以频率出现比较高的各个州刺史的频率单列出来:
排名 | 词 | 最早卷数 | 次数 | 百分比 |
15 | 豫州刺史 | 58 | 220 | 0.02% |
19 | 荆州刺史 | 49 | 195 | 0.02% |
26 | 兗州刺史 | 37 | 172 | 0.01% |
32 | 徐州刺史 | 30 | 167 | 0.01% |
38 | 扬州刺史 | 24 | 152 | 0.01% |
42 | 雍州刺史 | 65 | 147 | 0.01% |
52 | 江州刺史 | 86 | 122 | 0.01% |
64 | 益州刺史 | 39 | 113 | 0.01% |
68 | 二州刺史 | 49 | 111 | 0.01% |
74 | 秦州刺史 | 79 | 109 | 0.01% |
101 | 青州刺史 | 21 | 91 | 0.01% |
105 | 梁州刺史 | 84 | 90 | 0.01% |
107 | 冀州刺史 | 27 | 88 | 0.01% |
114 | 并州刺史 | 52 | 84 | 0.01% |
135 | 凉州刺史 | 31 | 71 | 0.01% |
165 | 幽州刺史 | 50 | 62 | 0.01% |
196 | 广州刺史 | 80 | 55 | 0.00% |
豫州刺史第58卷时才登场,但是雄踞第一,而豫、荆、兖、徐、扬也勾勒出了中国政治地理的热点。顺便提一句,最早登场的豫州刺史是王允,而最早登场的荆州刺史是杨震。
五字词已经没有太大的意义:
排名 | 词 | 最早卷数 | 次数 | 百分比 |
1 | 府仪同三司 | 79 | 283 | 0.03% |
2 | 开府仪同三 | 79 | 283 | 0.03% |
3 | 尚书左仆射 | 77 | 167 | 0.02% |
4 | 皇帝上之下 | 10 | 140 | 0.02% |
5 | 为中书侍郎 | 84 | 118 | 0.01% |
6 | 尚书右仆射 | 81 | 115 | 0.01% |
7 | 军都指挥使 | 256 | 111 | 0.01% |
8 | 骠骑大将军 | 39 | 107 | 0.01% |
9 | 河东节度使 | 214 | 101 | 0.01% |
10 | 督中外诸军 | 74 | 97 | 0.01% |
最后看看慕容家的英杰们谁的全名被提到的次数最多:
词 | 次数 |
慕容彦超 | 27 |
慕容垂 | 26 |
慕容廆 | 24 |
慕容绍宗 | 15 |
慕容恪 | 18 |
慕容评 | 18 |
慕容皝 | 17 |
慕容农 | 15 |
慕容翰 | 15 |
慕容仁 | 12 |
慕容白曜 | 10 |
似乎是慕容彦超险胜慕容垂……慢着!慕容垂最初的名字是慕容霸,而慕容霸被提及了10次,所以慕容垂以 36 次远远胜出 (慕容缺这个全名并没有出现在《通鉴》中:))。