zoukankan      html  css  js  c++  java
  • 用perl实现宋词词频统计——东风何处是人间

    最近,发现 yixuan 对全宋词做了个词频分析,结果吸引了广大人民群众的做词热情:“理科宅男们消灭文科生的日子到来了!拿起你的计算器,消灭文艺青年吧!” ^_^  作为一个perl爱好者,不免想用perl实现试试,毕竟perl在处理文本方面是行家。

    代码基本原理还是参照yixuan,但少量地方做了修改,根据维基百科中关于词的介绍:按长短规模分,词大致可分小令(58字以内)、中调(59一90字)和长调(91字以上,最长的词达240字)。所以最长设置为500是合理的,因为一个汉字是2个字节。宋词词牌名典型的长度是3个汉字:比如 永遇乐 阳关曲 江南忆等,但也有长达6个以上的词牌,比如:江南上云乐,潇湘逢故人慢,凤凰台上忆吹箫等,所以为了去掉作者名字和词牌名,设置了最小长度限制20. 同时由于数据源中有些词牌名还加了括号别名,比如:满庭芳(寿黄状元·三月初八),长度已经超过20,所以需要特别去掉这样的词牌名。

    所有代码如下:

     1 #!/usr/bin/perl -w
    2 use strict;
    3
    4 my $in = "全宋词.txt";
    5 open (IN, "<$in") || die "Cannot open file: $in";
    6 my $out = "freq.list";
    7 open (OUT, ">$out") || die "Cannot open file: $out";
    8
    9 my %phrase;
    10
    11 while (<IN>) {
    12 chomp;
    13 if (( length($_) > 20 ) && ( length($_) < 500 ) && ($_ !~ /(/)) { #1 chinese = 2 bytes
    14 my @sentences = split /,|。|?|、|!/;
    15 foreach (@sentences) {
    16 s/\s+//g; #delete all SPACES if any
    17 my @words = split //; #split sentence into char, that is half chinese.
    18 my $i = 0;
    19 while (defined $words[$i+3] ) {
    20 $phrase{$words[$i] . $words[$i+1] . $words[$i+2] . $words[$i+3]} ++;
    21 $i += 2; }
    22 }
    23 }
    24 }
    25
    26 #词频降序排列,若相同,则按照汉字拼音字母排序
    27 my @words_freq = sort { $phrase{$b} <=> $phrase{$a} or $a cmp $b } keys %phrase;
    28 foreach (@words_freq) {
    29 print OUT "$_\t" . "$phrase{$_}\n";
    30 }
    31
    32 close (IN);
    33 close (OUT);

    得出结果和yixuan的相类似,但在个别的词排序上有差别,可能是数据来源有区别,我只是临时从网上下载的。排在第一位的是无效字符□□,这是由于数据源的问题,下载的全宋词里面就有很所这种字符,应该是由于很多古体字打不出来,用□来代替的。如下是perl程序得到的排在出现频率前100的词组。 

    词频统计
      1 □□    1492
    2 东风 1321
    3 何处 1178
    4 人间 1147
    5 风流 805
    6 归去 788
    7 春风 770
    8 西风 755
    9 归来 735
    10 相思 725
    11 江南 701
    12 梅花 681
    13 千里 648
    14 回首 632
    15 明月 622
    16 如今 621
    17 多少 620
    18 阑干 597
    19 万里 572
    20 年年 566
    21 一笑 565
    22 天涯 518
    23 相逢 516
    24 芳草 511
    25 当年 501
    26 黄昏 493
    27 尊前 491
    28 风雨 488
    29 流水 463
    30 风吹 450
    31 依旧 449
    32 当时 439
    33 风月 433
    34 多情 432
    35 斜阳 429
    36 一枝 423
    37 故人 421
    38 不见 420
    39 无人 420
    40 不知 415
    41 深处 390
    42 凄凉 379
    43 时节 376
    44 匆匆 374
    45 平生 374
    46 春色 371
    47 无限 371
    48 功名 359
    49 扁舟 350
    50 杨柳 347
    51 西湖 344
    52 天上 342
    53 一点 341
    54 今日 337
    55 桃花 335
    56 憔悴 333
    57 何事 332
    58 芙蓉 322
    59 黄花 321
    60 心事 315
    61 人生 313
    62 消息 312
    63 一片 312
    64 十分 310
    65 长安 307
    66 神仙 307
    67 一声 307
    68 十年 305
    69 佳人 302
    70 桃李 302
    71 断肠 300
    72 而今 300
    73 鸳鸯 299
    74 去年 295
    75 肠断 294
    76 少年 294
    77 为谁 293
    78 江上 292
    79 不是 289
    80 今夜 289
    81 无情 287
    82 往事 286
    83 海棠 285
    84 何时 284
    85 谁知 284
    86 不似 283
    87 青山 283
    88 时候 283
    89 悠悠 282
    90 寂寞 281
    91 蓬莱 281
    92 惟有 279
    93 行人 279
    94 落花 276
    95 如何 276
    96 燕子 275
    97 一曲 275
    98 几度 274
    99 月明 274
    100 富贵 273

    从这个统计我们可以看出一些有趣的事实:

    出现频率最高的是:“东风” "何处" 是 "人间",分列第2,3,4名。

    古人对江南的确是情有独钟,不光词牌名有很多,比如:《忆江南》《江南忆》《江南好》《江南春》《江南柳》等,连词中统计出现“江南”的数目也是很庞大,占据了第11名。大部分词都是表达相思之苦(思故人,思情人,思故乡等等),比如占据前列的有:归去(6),归来(9),相思(10),千里(13),阑干(18),万里(19),天涯(22),相逢(23),故人(37)等等,真的是“为赋新词强说愁”啊。

    参考:

    http://yixuan.cos.name/cn/2011/03/text-mining-of-song-poems/

    http://www.cnbeta.com/articles/164096.htm

  • 相关阅读:
    C++ string 实现大整数相加减
    HDU2489 Minimal Ratio Tree 【DFS】+【最小生成树Prim】
    Quick-Cocos2d3.2RC1在Code IDE中实现代码提示
    Codeforces 558C Amr and Chemistry
    Linux编程---进程通信
    HDU 5371 Hotaru&#39;s problem(Manacher算法+贪心)
    微社区
    创业忌讳
    微信公众平台开发(82) 天气预报
    天气预报接口
  • 原文地址:https://www.cnblogs.com/yuyan/p/2274875.html
Copyright © 2011-2022 走看看