我试图根据给定的键翻译numpy.array
的每个元素:
例如:
a = np.array([[1,2,3],
[3,2,4]])
my_dict = {1:23, 2:34, 3:36, 4:45}
我想得到:
array([[ 23., 34., 36.],
[ 36., 34., 45.]])
我可以看到如何用一个循环来实现:
def loop_translate(a, my_dict):
new_a = np.empty(a.shape)
for i,row in enumerate(a):
new_a[i,:] = map(my_dict.get, row)
return new_a
有没有更有效和/或纯粹的numpy方式?
编辑:
我对它进行了计时,DSM提出的np.vectorize
方法对于更大的阵列来说要快得多:
In [13]: def loop_translate(a, my_dict):
....: new_a = np.empty(a.shape)
....: for i,row in enumerate(a):
....: new_a[i,:] = map(my_dict.get, row)
....: return new_a
....:
In [14]: def vec_translate(a, my_dict):
....: return np.vectorize(my_dict.__getitem__)(a)
....:
In [15]: a = np.random.randint(1,5, (4,5))
In [16]: a
Out[16]:
array([[2, 4, 3, 1, 1],
[2, 4, 3, 2, 4],
[4, 2, 1, 3, 1],
[2, 4, 3, 4, 1]])
In [17]: %timeit loop_translate(a, my_dict)
10000 loops, best of 3: 77.9 us per loop
In [18]: %timeit vec_translate(a, my_dict)
10000 loops, best of 3: 70.5 us per loop
In [19]: a = np.random.randint(1, 5, (500,500))
In [20]: %timeit loop_translate(a, my_dict)
1 loops, best of 3: 298 ms per loop
In [21]: %timeit vec_translate(a, my_dict)
10 loops, best of 3: 37.6 ms per loop
In [22]: %timeit loop_translate(a, my_dict)
7条答案
按热度按时间sqxo8psd1#
我不知道效率如何,但你可以在字典的
.get
方法上使用np.vectorize
:62lalag42#
下面是另一种方法,使用
numpy.unique
:当数组中唯一元素的数量很小时,这种方法比
np.vectorize
方法快得多。* 解释:* Python很慢,在这种方法中,使用in-python循环来转换唯一元素,然后我们依靠非常优化的numpy索引操作(在C中完成)来进行Map。因此,如果唯一元素的数量与数组的整体大小相当,则不会有加速。另一方面,如果只有几个独特的元素,那么您可以观察到高达x100的加速。new9mtju3#
我认为最好迭代字典,并“一次”设置所有行和列的值:
编辑:
虽然它可能没有使用
numpy.vectorize
的DSM's (really good) answer那么性感,但我对所有建议方法的测试表明,这种方法(使用@jamylak的建议)实际上更快:输出:
z4bn682m4#
numpy_indexed软件包(免责声明:我是它的作者)为这类问题提供了一个优雅而高效的矢量化解决方案:
实现的方法类似于John Vinyard提到的方法,但更通用。例如,数组的项不需要是int,但可以是任何类型,甚至是nd-subarrays本身。
如果将可选的'missing' kwarg设置为'raise'(默认值为'ignore'),性能会稍微好一点,如果不是'a'的所有元素都存在于键中,则会得到KeyError。
wvyml7n55#
假设你的dict键是正整数,没有巨大的差距(类似于从0到N的范围),你最好把你的转换dict转换成一个数组,比如
my_array[i] = my_dict[i]
,并使用numpy索引来进行转换。使用这种方法的代码是:
随机数组测试:
对于这些大小,我使用这种方法得到大约
140 ms
。get矢量化大约需要5.8 s
,unique_translate
大约需要8 s
。可能的概括:
a
和字典键中的值移动一个常量,将它们Map回正整数:9wbgstp76#
如果你真的不需要**使用字典作为替换表,简单的解决方案是(对于你的例子):
当然,只有当
d
的索引覆盖了a
的所有可能值时,这才有效,换句话说,只有a
具有带符号的整数。4dc9hkyq7#
充分利用 @DSM 和 @John Vinyard 解决方案:
dict.__getitem__
。验证码:
这与 @DSM answer具有相同的优点,同时也避免了数组中唯一元素的python循环。