如何用NumPy高效统计数组中每个单词的26个字母出现次数
高效统计单词字母出现次数的NumPy方案
核心方法(Numpythonic实现)
直接利用字节转换、广播比较和维度求和,完全基于NumPy的C底层实现,避免Python循环开销:
import numpy as np # 假设wordlist_arr是你的形状(71729,)、类型|S64的NumPy数组 # 1. 将字符串数组转换为uint8字节数组(每个字符对应ASCII码),形状变为(71729, 64) char_bytes = np.frombuffer(wordlist_arr.tobytes(), dtype=np.uint8).reshape(wordlist_arr.shape[0], -1) # 2. 生成a-z对应的ASCII码数组,形状(26,) letter_codes = np.arange(ord('a'), ord('z') + 1, dtype=np.uint8) # 3. 广播比较+求和,得到每行26个字母的计数,最终形状(71729, 26) letter_counts = (char_bytes[..., np.newaxis] == letter_codes).sum(axis=1)
方法解释
- 字节转换:用
np.frombuffer直接读取字符串数组的原始字节,比view('S1')更稳定,同时自动忽略空字符干扰(空字节ASCII为0,不会匹配a-z的ASCII码97-122)。 - 广播机制:给
char_bytes添加新维度后(变为(71729,64,1)),和letter_codes((26,))自动广播为(71729,64,26)的布尔数组,标记每个字符是否等于对应字母。 - 维度求和:沿字符维度(axis=1)求和,直接得到每个单词的26字母出现次数。
针对你之前尝试的问题说明
np.unique出现空字符:|S64是固定长度字符串,不足部分会用空字节(ASCII 0)填充,view('S1')会包含这些空字符,而上面的方法会自动过滤它们。np.char.count形状不匹配:np.char.count要求第一个参数是一维字符串数组,你传入的是二维(71729,64)的|S1数组。如果非要用这个方法,需先合并回一维字符串数组,但效率远低于广播方案:
# 低效的np.char.count实现(不推荐) restored_words = char_bytes.view('|S64').ravel() letter_counts = np.array([np.char.count(restored_words, chr(code)) for code in letter_codes]).T
内容的提问来源于stack exchange,提问作者Muhammad Ikhwan Perwira
相关产品推荐
相关产品推荐

