做中文稿的關鍵字排查,動作通常都一樣:把整段正文貼進頻率統計、切到詞頻、等一張榜單。第一次拿到「總單詞數 0」和一行「暫無資料」時,很難把它和剛貼進去的那 25 個漢字聯想在一起——字明明都在框裡。
空表不是壞了,是抽取只認 ASCII 字母
範本第 152 行的抽取正則是 /[a-zA-Z]+/g,詞的定義就是連續 ASCII 字母串。同一句「中文根本不按詞切分所以字頻統計會把每個漢字單獨計數」交給文本頻率統計,兩個分頁給出兩份完全不同的東西:字元頻率下是 25 字元、23 項榜單,榜首「字」2 次 8.0%,第二項「計」同為 8.0%,其餘上榜的漢字各 1 次 4.0%,23 項顯示佔比加起來正好 100.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%。
圖 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 行當唯一答案。