Numpy索引的2个数组

rwo*_*lst 10 python arrays numpy

考虑两个numpy数组

a = np.array(['john', 'bill', 'greg', 'bill', 'bill', 'greg', 'bill'])
b = np.array(['john', 'bill', 'greg'])
Run Code Online (Sandbox Code Playgroud)

我怎样才能生成第三个数组

c = np.array([0,1,2,1,1,2,1])
Run Code Online (Sandbox Code Playgroud)

a表示a数组中每个条目的索引的长度相同b

我可以通过循环遍历bas b[i]和elements的元素来看到一种方法,np.where(a == b[i])但是想知道numpy是否可以通过更快/更好/更少的代码行来实现这一点.

Aka*_*all 7

这是一个选项:

import numpy as np

a = np.array(['john', 'bill', 'greg', 'bill', 'bill', 'greg', 'bill'])
b = np.array(['john', 'bill', 'greg'])

my_dict = dict(zip(b, range(len(b))))

result = np.vectorize(my_dict.get)(a)
Run Code Online (Sandbox Code Playgroud)

结果:

>>> result
array([0, 1, 2, 1, 1, 2, 1])
Run Code Online (Sandbox Code Playgroud)


Jai*_*ime 5

排序是使用numpy进行矢量化的一个很好的选择:

>>> s = np.argsort(b)
>>> s[np.searchsorted(b, a, sorter=s)]
array([0, 1, 2, 1, 1, 2, 1], dtype=int64)
Run Code Online (Sandbox Code Playgroud)

如果你的数组am元素并且bn,那么排序将是O(n log n),并且搜索O(m log n),这是不错的.基于字典的解决方案应该是线性分摊的,但如果数组不是很大,Python循环可能会使它们比这更慢.基于广播的解决方案具有二次复杂性,对于非常小的阵列,它们只会更快.


您的样本的一些时间安排:

In [3]: %%timeit
   ...: s = np.argsort(b)
   ...: np.take(s, np.searchsorted(b, a, sorter=s))
   ...: 
100000 loops, best of 3: 4.16 µs per loop

In [5]: %%timeit
   ...: my_dict = dict(zip(b, range(len(b))))
   ...: np.vectorize(my_dict.get)(a)
   ...: 
10000 loops, best of 3: 29.9 µs per loop

In [7]: %timeit (np.arange(b.size)*(a==b[:,newaxis]).T).sum(axis=-1)
100000 loops, best of 3: 18.5 µs per loop
Run Code Online (Sandbox Code Playgroud)