根据一维数组中的值更改二维numpy数组中的某些值而无需for循环
Posted
技术标签:
【中文标题】根据一维数组中的值更改二维numpy数组中的某些值而无需for循环【英文标题】:Change certain values in 2D numpy array based on values in 1D array without for-loop 【发布时间】:2019-01-15 02:31:42 【问题描述】:我的问题对我来说似乎很基本,以至于我有点不好意思自己没有解决它。尽管咨询了 this、this 和 that,但我不知道如何在不使用 for 循环的情况下根据 1D numpy 数组中的值更改 2D numpy 数组中的某些值。
具有所需结果的示例是:
import numpy as np
# sample data:
a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
b = np.array([2, 0, 2])
c = np.array([[10, 20, 30], [40, 50, 60], [70, 80, 90]])
# for-loop solution:
for i in range(len(a)):
a[i][b[i]] = 0.9 * c[i][b[i]]
# desired result:
print(a)
# [[ 1 2 27]
# [36 5 6]
# [ 7 8 81]]
编辑 1
在对 Rafael 的答案进行修改后,我现在可以在没有 for 循环的情况下获得所需的结果。然而,令我惊讶的是,索引解决方案比 for 循环慢。
import numpy as np
import time
# set seed for reproducibility:
np.random.seed(1)
x = np.random.randint(10, size=(10, 10))
y = np.random.randint(10, size=10)
z = np.random.randint(10, size=(10, 10))
# for-loop solution:
start1 = time.clock()
for i in range(len(x)):
x[i][y[i]] = 2 * z[i][y[i]]
end1 = time.clock()
print("time loop: " + str(end1 - start1))
# time loop: 0.00045699999999726515
print("result for-loop:")
print(x)
# result for-loop:
# [[ 5 8 9 5 0 0 1 7 6 4]
# [12 4 5 2 4 2 4 7 7 9]
# [ 1 7 2 6 9 9 7 6 9 1]
# [ 2 1 8 8 3 9 8 7 3 6]
# [ 5 1 9 3 4 8 1 16 0 3]
# [ 9 14 0 4 9 2 7 7 9 8]
# [ 6 9 3 7 7 4 5 0 3 6]
# [ 8 0 2 7 7 9 7 3 0 16]
# [ 7 7 1 1 3 0 8 6 16 5]
# [ 6 2 5 7 14 4 4 7 7 4]]
# set seed for reproducibility:
np.random.seed(1)
x = np.random.randint(10, size=(10, 10))
y = np.random.randint(10, size=10)
z = np.random.randint(10, size=(10, 10))
# indexing solution:
start2 = time.clock()
r = x.shape[0]
x[range(r), y] = z[range(r), y] * 2
end2 = time.clock()
print("time indexing: " + str(end2 - start2))
# time indexing: 0.0005479999999948859
print("result indexing:")
print(x)
# result indexing:
# [[ 5 8 9 5 0 0 1 7 6 4]
# [12 4 5 2 4 2 4 7 7 9]
# [ 1 7 2 6 9 9 7 6 9 1]
# [ 2 1 8 8 3 9 8 7 3 6]
# [ 5 1 9 3 4 8 1 16 0 3]
# [ 9 14 0 4 9 2 7 7 9 8]
# [ 6 9 3 7 7 4 5 0 3 6]
# [ 8 0 2 7 7 9 7 3 0 16]
# [ 7 7 1 1 3 0 8 6 16 5]
# [ 6 2 5 7 14 4 4 7 7 4]]
这是什么原因造成的?还有,我怎样才能实现加速?
【问题讨论】:
【参考方案1】:似乎实际上被屏蔽的数组很慢。见here。
这是用户在另一个答案中所说的。
请记住,MaskedArrays 更多的是方便而不是真正的 解决方案。如果您需要对数组执行密集计算 缺少/未定义值的数组,在大多数情况下你会更好 自己处理掩码和数据。直到更好 NumPy 代码中烘焙了缺失/未定义值的实现 (这应该很快就会发生),你被 MaskedArrays 困住了。 是的,它们很慢,因为它们是用纯 Python 编写的, 当然不能像依赖一些 C 代码那样高效
希望它能解决您的疑问。
【讨论】:
【参考方案2】:IIUC
r = np.arange(a.shape[0]) # same as range(len(a)) here, but faster.
a[r, b] = c[r, b] * 0.9
array([[ 1, 2, 27],
[36, 5, 6],
[ 7, 8, 81]])
【讨论】:
感谢您的回答。由于我的实际应用程序有点复杂,如果我成功实施了您的解决方案,我会回复您。不过看起来很有希望! 抱歉耽搁了。不幸的是,即使将您的代码应用于示例,我也会收到IndexError: index 3 is out of bounds for axis 0 with size 3
。
然而,对这个例子起作用的是a[range(r), b] = c[range(r), b] * 0.9
我看不到arange
,删除了反对票:)。
np.arange
确实加快了代码速度。感谢您的帮助。以上是关于根据一维数组中的值更改二维numpy数组中的某些值而无需for循环的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 for 循环将一维数组的值放入 C++ 中的二维数组