使用NumPy进行快速令牌到索引的转换

时间:2018-01-22 17:04:03

标签: python arrays string numpy

我们说我有两个大的文字串,我分成了几个字:

import numpy as np

s1 = 'this is a test test test'
s2 = 'that is another test'

terms1 = np.array(s1.split())
terms2 = np.array(s2.split())

现在terms1['this', 'is', 'a', 'test', 'test', 'test']terms2['that', 'is', 'another', 'test']

我现在想要为每个唯一的单词分配一个ID,然后为每个terms - 一个包含相应ID的向量得到一个数组,即指向公共"词汇表" terms1terms2

vocab = np.unique(np.concatenate((terms1, terms2)))
# yields ['a', 'another', 'is', 'test', 'that', 'this']

ind1 = [np.where(t == vocab)[0][0] for t in terms1]
# yields indices into "vocab": [5, 2, 0, 3, 3, 3]
ind2 = [np.where(t == vocab)[0][0] for t in terms2]
# yields indices into "vocab": [4, 2, 1, 3]

这基本上有效。但是,在for循环中使用np.where似乎效率低下,我想知道NumPy是否有更好的方法来做这些事情?

3 个答案:

答案 0 :(得分:6)

使用np.uniquereturn_inverse参数,然后使用连接输入的长度拆分返回的逆数组:

In [13]: vocab, inv = np.unique(np.concatenate((terms1, terms2)), return_inverse=True)

In [14]: inv[:len(terms1)]
Out[14]: array([5, 2, 0, 3, 3, 3])

In [15]: inv[len(terms1):]
Out[15]: array([4, 2, 1, 3])

答案 1 :(得分:2)

您可以使用broadcasting一次进行所有比较:

In [23]: np.where(terms1[:, None] == vocab)[1]
Out[23]: array([5, 2, 0, 3, 3, 3])

In [24]: np.where(terms2[:, None] == vocab)[1]
Out[24]: array([4, 2, 1, 3])

答案 2 :(得分:0)

如果您使vocab列表,则可以使用index()

vocab_list = list(np.unique(np.concatenate((terms1, terms2))))
ind1 = [vocab_list.index(t) for t in terms1]

在我的速度测试中,这似乎比np.where()快,但我不确定大型列表会发生什么。