三句话,完成英文语料的词频统计

简介

有时候有必要对一个英文语料进行统计,以便发现其中的规律。例如,统计词频从而知道哪些词使用得比较频繁。本文实现了三个函数完成英文语料的统计功能,重点研究在什么条件下能够使语料中90%单词能被人读懂。

数据集

本文使用MASC数据集,下载地址:https://www.anc.org/data/masc/
该数据集是一个开放的社区资源,从更大的语料集Open American National Corpus (OANC)上抽取而成, 由500,000多个单词组成。

统计代码

代码由js写成。对数据集中的每一个文本文档进行分词、去停词处理,统计出现过的每个单词的词频数。最后把统计结果输出到一个文件。

const fs = require('fs');
const { resolve } = require('path');

/**
 * 统计结果,是一个map
 */
let words = new Array();

/**
 * 总词数
 */
let total = 0;

/**
 * 统计一个文件
 * @param {string} filename  文件的文件名
 */
function readFile(filename){
    console.log("正在处理:" + filename);
    var data = fs.readFileSync(filename, 'utf-8');
    var str = data.toString();
    var tokens = str.split(/\W+/) //分词
        .filter((token)=>{return token != '' && ! /^(\w|\d+)$/.test(token)}) // 去停词
        .map((token)=>{return token.toLowerCase()});
    for(let token of tokens){
        if(words[token] === undefined){
            words[token] = 1;
        }else{
            words[token] += 1;
        }
        total += 1;
    }

}

/**
 * 统计一个目录下的所有文件
 * @param {string} path 目录的路径
 */
function readAllFiles(path){
    const files = fs.readdirSync(path);
    for(let file of files){
        var filePath = resolve(path, file);
        var stat = fs.statSync(filePath);
        if (stat.isFile()) {
            readFile(filePath);
        } else if (stat.isDirectory()) {
            readAllFiles(filePath)
        }
    }
}


/**
 * 把统计结果写到文件中
 * @param {string} filename 文件的文件名
 */
function wirteCSV(filename){
    //根据词频由大到小排序
    var wordList = []
    for(let word in words){
        if(typeof(words[word]) == 'number')
            wordList.push({word: word, count: words[word]})
    }

    wordList.sort((a, b)=>{
        if(a.count < b.count) {
            return 1;
        }else if(a.count == b.count){
            return 0;
        }else{
            return -1;
        }
    })

    // 写文件
    let fWrite = fs.createWriteStream(filename);
    fWrite.write("词");
    fWrite.write(",")
    fWrite.write("频数");
    fWrite.write(",");
    fWrite.write("频率");
    fWrite.write(",");
    fWrite.write("累计百分比");
    fWrite.write('\n')
    let accumulate = 0;
    for(let obj of wordList){
        accumulate += obj.count;
        fWrite.write(obj.word);
        fWrite.write(",")
        fWrite.write(obj.count + "");
        fWrite.write(",");
        fWrite.write(obj.count * 100 / (total + 1) + "%");
        fWrite.write(",");
        fWrite.write(accumulate * 100 / (total + 1) + "%");
        fWrite.write('\n')
    }
    fWrite.close();


}

readAllFiles('./spoken');
readAllFiles('./written');
wirteCSV('./wordcout.csv');
console.log("处理完毕");

结果分析

统计结果如下。左边主要是各个单词在语料中的出现频数、频率,并按照词频由大到小排序。
在这里插入图片描述
如右边上方的图,我们可以发现,词频大小呈指数级下降,很好的符合“长尾理论”。
如右边下方的图,可知,2300左右的词汇量即可覆盖语料中80%的单词。6500左右的词汇量可覆盖语料中90%的单词。因此,如果人类掌握了上图中前6500词,则能读懂语料中90%词汇。

展望

该语料集比较小,可能不能很好的反应规律。如果能够在更大语料集中统计,并且如果语料是日常语料,则可统计外国人日常的英文词频。我们则可以有的放矢地去记忆单词。
本文的词频统计方法与语料规模无关,可直接用于更大的语料。

关注我,学习更多编程小技巧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值