计算numpy中每个单词中每26个字符的出现次数

1 投票
1 回答
43 浏览
提问于 2025-04-13 19:11

我有一个存储在 wordlist_arr 中的 numpy 数组:

[b'aabi\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00abcdefghijklmnopqrstuvwxyz'
 b'aabinomin\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00abcdefghijklmnopqrstuvwxyz'
 b'aaji\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00abcdefghijklmnopqrstuvwxyz'
 ...
 b'zus\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00abcdefghijklmnopqrstuvwxyz'
 b'zuzumo\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00abcdefghijklmnopqrstuvwxyz'
 b'zuzuni\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00abcdefghijklmnopqrstuvwxyz']
(71729,)
|S64

我希望能对每个单词列表计算 26 个字母,所以输出的形状应该是 (71729, 26)

[[3,2,1,1,1,1,1,1,2,1,...,1],
...
]

'''
In [3,2,1,1,1,1,1,1,2,1,...,1]
index 0 represent num "a" counted, index 1 represent num "b" counted, and so on...
'''

我改变了视角并重新调整形状,这样就可以按字母来查看了。

wordlist.view('S1').reshape((wordlist.size, -1))

'''
[[b'a' b'a' b'b' ... b'x' b'y' b'z']
 [b'a' b'a' b'b' ... b'x' b'y' b'z']
 [b'a' b'a' b'j' ... b'x' b'y' b'z']
 ...
 [b'z' b'u' b's' ... b'x' b'y' b'z']
 [b'z' b'u' b'z' ... b'x' b'y' b'z']
 [b'z' b'u' b'z' ... b'x' b'y' b'z']]
(71729, 64)
|S1
'''

正如你所看到的,我在索引的末尾加上了 abcdefghijklmnopqrstuvwxyz,这样我就可以使用 np.unique 方法,确保每个字母至少被计算一次。但结果似乎不太对,它返回了所有可能使用的字符。

[b'' b'a' b'b' b'c' b'd' b'e' b'f' b'g' b'h' b'i' b'j' b'k' b'l' b'm' b'n'
 b'o' b'p' b'q' b'r' b's' b't' b'u' b'v' b'w' b'x' b'y' b'z']
(27,)
|S1

我尝试了另一种方法,使用 numpy 的字符计数,但似乎也不行:

np.char.count(wordlist.view('S1').reshape(wordlist.size, -1), alphabet, axis=1)
# ValueError: shape mismatch: objects cannot be broadcast to a single shape.  Mismatch is between arg 0 with shape (71729, 64) and arg 1 with shape (26,).

其实我可以用原生的方法来做,但现在我想找一种 numpy 风格的方法,这样我就能利用用 C 语言 编写的 numpy 的性能。

1 个回答

1

如果我理解正确,你可以这样做:

考虑这个数组:

s = np.array([b"aabbdd", b"aabbcc", b"eeffgg", b"xxyyzz"], dtype="S6")
print(s.view("uint8").reshape(s.shape[0], -1))

这段代码会输出:

[[ 97  97  98  98 100 100]
 [ 97  97  98  98  99  99]
 [101 101 102 102 103 103]
 [120 120 121 121 122 122]]

然后:

x = np.apply_along_axis(
    lambda x: np.resize(np.bincount(x), 128)[97:123],  # 97 - a, 123 - z according ASCII
    axis=1,
    arr=s.view("uint8").reshape(s.shape[0], -1),
)
print(x)

输出结果是:

[[2 2 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2]]

撰写回答