杂记 › 技术笔记 › 字频还是词频:同一句中文,一份 23 项榜单和一份空表

字频还是词频:同一句中文,一份 23 项榜单和一份空表

做中文稿的关键词排查,动作通常都一样:把整段正文贴进频率统计、切到词频、等一张榜单。第一次拿到「总单词数 0」和一行「暂无数据」时,很难把它和刚贴进去的那 25 个汉字联系起来——字明明都在框里。

空表不是坏了,是抽取只认 ASCII 字母

模板第 152 行的抽取正则是 /[a-zA-Z]+/g,词的定义就是连续 ASCII 字母串。同一句「中文根本不按词切分所以字频统计会把每个汉字单独计数」交给文本频率统计,两个 tab 给出两份完全不同的东西:字符频率下是 25 字符、23 项榜单,榜首「字」2 次 8.0%,第二项「计」同为 8.0%,其余上榜的汉字各 1 次 4.0%,23 项显示占比加起来正好 100.0%;英文词频下是 0 个词,把每个汉字之间敲上空格再喂进去仍然是 0——它不按空白切词,手动分词救不回来。

同一句 25 字中文 字符频率:23 项 字 8.0% 计 8.0% 中 4.0% 文 4.0% 其余汉字各 1 次 英文词频:0 词 暂无数据 总单词数 0 逐字加空格仍 0

图 1:同一句 25 字中文的两份榜单

汉字、标点、全角空格在这张榜里同权

字符模式的跳过名单只有空格、换行、制表、回车这 4 个字符(模板第 123 行),其余全部计入。前 5 名里出现「。」并不奇怪:43 字符的段落里它以 3 次 7.0% 挤进前 5;全角空格更不在跳过名单,5 字符的 A B C 里它以 2 次 40.0% 直接坐榜首。

分母也带着这些字符:58 字符的模板混排样例只计到 49 个,41 项占比之和只有 83.5%,缺的 16.5% 正是被跳过却又留在分母里的空白。计数单位是 UTF-16 码元,50 个表情符加 abc 长度是 103、代码点只有 53,一个表情被拆成 2 项、各 50 次 48.5%。

停用词开关改的不只是名次,还有分母

模板自带那段 117 字符、24 个词的英文样例最能暴露口径。停用词字段留空时榜单 17 项,榜首 the 4 次 16.7%,逐行占比加起来 100.3%——多出的部分是 17 行 toFixed(1) 的舍入残差。把默认那张 30 词的表打开,榜首换成 fox 2 次 8.3%,第 1 到第 4 名 fox、over、dog、again 同频并列,不同单词 17 个减到 11 个,占比之和掉到 62.6%。

同一份 117 字符样例 the 16.7% fox 8.3% over 8.3% dog 8.3% again 8.3% 停用词 OFF:17 项 榜首 the,占 16.7% 占比之和 100.3% 停用词 ON:11 项 榜首 fox,占 8.3% 占比之和 62.6%

图 2:停用词开与关的 top5 与占比之和

这 62.6% 不是留存率:分母仍是过滤前的 24 个词,11 项计数之和只有 15 个词次,24 减 15 = 9 才是被抹掉的词次。开关带来的不是名次位移而是换人——原本并列第 5 档的四个词被抬成榜首,唯一的第 1 名 the 直接消失。

勾上「区分大小写」,停用词表半失效

词表里的 30 项装载时被统一转成小写,匹配却拿原样大小写查表。勾上「区分大小写」后句首的 The 逃过过滤,榜首变成 The 2 次 8.3%,统计栏照样报排除停用词 30 个。停用词清空再勾同一个开关,the 家族被拆成 The 2 与 the 2 两行、各 8.3%,而合并口径本是一行 4 次 16.7%——任何一行都不到真实占比的一半。

同频并列时,三个模式三套次序

三个模式用的是同一个按次数降序的比较器,排序稳定,于是并列名次完全取决于排序前数组的来源,而这三处来源不同:

  • 字符模式取自 Object.keys,整数型键被提到最前按数值升序:输入 1234567890 的榜首是 0,b a a b 5 5 z 给出 5、b、a、z,数字 5 被顶到第 1 位(15.4%)。
  • 词模式也取自 Object.keys,但键只能是字母串,于是纯首次出现序:zebra apple zebra apple 里 zebra 2 次 50.0% 排在 apple 之前,字典序会给出相反结果。
  • 关键词模式就是你写列表的顺序,与文本里谁先出现无关。

带数字的词还会整体塌缩:w0 到 w4999 这 5000 个编号词只剩 1 行 w 5000 次 100.0%,版本号、SKU 这类名单全被并成同一行。

关键词那一栏的百分比不是密度

它的分子是命中次数、分母是字符数。43 字符的默认样例里「人工智能」出现 3 次,界面显示 7.0%;按实际占用的 12 个字符算是 27.9%,差 4 倍。列表还不去重:同一个词写 3 行再加 1 行别的,关键词数报 4 个、总命中次数报 10 次,而文本里真实只有 4 处。匹配也不重叠,aaa 里找 aa 报 1 次 33.3%(真实 2 个位置),aaaa 报 2 次 50.0%(真实 3 个)。榜单也没有取前 N 项的开关,1000 行关键词就渲染 1000 行。

模式什么算一项占比分母并列时谁在前中文实测
字符频率非空白字符,含标点与全角空格文本长度,空白留在里面数字插队,其余按首次出现25 字符出 23 项,榜首 8.0%
英文词频连续 ASCII 字母串过滤前的词数 24首次出现序同一句话 0 个词
关键词列表里的每一行,不去重字符数(非占用字符)列表的书写序3 次显示 7.0%,实占 27.9%

这份榜单能回答什么,不能回答什么

能回答的是相对多少:463 字符的一段固定英文里榜首确实是 e(50 次),与单字母频率表的说法一致,但工具打印 10.8%,只按 379 个字母算是 13.2%,教科书那个 12.7% 两头都不沾——差额全来自留在分母的 78 个空白与 6 个标点。

不能回答的是中文的词:词由 ASCII 字母序列定义,中文在这张榜上永远不出现,关键词那栏又拿字符数当分母。真要用的话,可以先用文本排序去重把关键词列表压成唯一行,免得重复行把总命中次数抬高;如果本来只要「这篇稿子多少字」那种总量,字数统计讲的是另一套口径,跟排名无关。

Q:中文为什么永远是 0 个词?

词的定义是 /[a-zA-Z]+/g 抓到的连续 ASCII 字母,汉字进不了这个字符类。逐字敲空格仍是 0——它不按空白切词;重音字母反倒被当切分符,café 只剩 caf 一项。

Q:占比加起来不等于 100%,是算错了吗?

三种成因实测都存在:停用词留空时 17 项之和 100.3%,是逐行保留一位小数的舍入残差;字符模式 41 项之和只有 83.5%,因为空白被跳过却留在分母;停用词打开后 11 项之和 62.6%,因为分母仍是过滤前的 24 词。能不能相加,取决于分子与分母是不是同一份集合。

Q:并列同频时榜首到底算谁?

看模式:字符模式里 ASCII 数字按数值升序插队,1234567890 的榜首是 0;词模式按首次出现,zebra 排在 apple 前;关键词模式照抄列表书写顺序。三套都不是字典序,同频时不要把第 1 行当唯一答案。

📎 相关文章

文本合并后行数对不上:缺尾换行、被吃掉的 BOM 和不可靠的顺序 2026-10-26 Excel 粘贴转 JSON:日期、长数字和精度在「粘贴那一刻」就已经变了 2026-10-26 条形码解码只吐原文:EAN-13 校验位、UPC-A 的前导零与 CODE128 的模 103 2026-10-26 二维码解码实测:纠错等级救不了遮挡,每模块 2 像素才是生死线 2026-10-26 CSS 压缩没吃掉 calc 的空格,美化却把 .btn:hover 劈成了两截 2026-10-26