我有这些信息:
a = array([[ 1, 1, 1, 1, 1],
[ 1, 1, 1, 1, 2],
[ 1, 1, 1, 1, 3],
[ 1, 1, 1, 18, 16],
[ 1, 1, 1, 18, 17]], dtype=int16)
b = np.arange(0,50).reshape(5,10)
change_cols = [1,2,5,7,9]
我想用 a[:,:,-1]
的值更改由 change_cols
定义的列中 b
的每一行> 得到:
b = array([[ 0, 1, 1, 3, 4, 1, 6, 1, 8, 1],
[10, 2, 1, 13, 14, 1, 16, 1, 18, 1],
[20, 3, 1, 23, 24, 1, 26, 1, 28, 1],
[30, 16, 18, 33, 34, 1, 36, 1, 38, 1],
[40, 17, 18, 43, 44, 1, 46, 1, 48, 1]])
目前我正在这样做:
for n, i in enumerate(change_cols):
b[:,i] = a[:,-(n+1)]
如何在不使用 Python 的 for 循环的情况下在 NumPy 中高效地执行此操作?
更新:
我尝试比较完成@ogdencave 和@U12-forward 与 python 的 for-loop_enumerate 的答案所花费的时间。令人惊讶的是,Python3 for-loop+enumerate 是最快的。这是为什么?
>>> def splice():
b[:, change_cols] = a[:, ::-1]
>>> def splice_arange():
b[:, change_cols] = a[:,-(np.arange(len(change_cols)) + 1)]
>>> def enumerate_for_loop():
for n, i in enumerate(change_cols):
b[:,i] = a[:,-(n+1)]
>>> timeit.timeit('splice()', number=10000, globals=globals())
0.042480306001380086
>>> timeit.timeit('splice_arange()', number=10000, globals=globals())
0.05964866199065
>>> timeit.timeit('enumerate_for_loop()', number=10000, globals=globals())
0.03969518095254898
>>>
我还尝试了接近真实场景的数组大小。我很惊讶 python 的 for-loop+enumerate 方法是最快的。
>>> a = np.array([ 1, 1, 1, 18, 17]*300).reshape(300,5)
>>> b = np.arange(0,300*200).reshape(300,200)
>>> for i in range(5):
timeit.timeit('splice()', number=10000, globals=globals())
0.04873670096276328
0.04880331002641469
0.055170061998069286
0.04291973798535764
0.031961234053596854
>>> for i in range(5):
timeit.timeit('splice_arange()', number=10000, globals=globals())
0.07321989600313827
0.07536661700578406
0.06798515404807404
0.07559602102264762
0.07348818198079243
>>> for i in range(5):
timeit.timeit('enumerate_for_loop()', number=10000, globals=globals())
0.054252722999081016
0.03883319004671648
0.036229485005605966
0.036062364000827074
0.03962253499776125
最佳答案
这是避免 for 循环的一种方法。
import numpy as np
a = np.array([[ 1, 1, 1, 1, 1],
[ 1, 1, 1, 1, 2],
[ 1, 1, 1, 1, 3],
[ 1, 1, 1, 18, 16],
[ 1, 1, 1, 18, 17]], dtype=np.int16)
b = np.arange(0,50).reshape(5,10)
change_cols = [1,2,5,7,9]
b[:, change_cols] = a[:, ::-1]
更新时间信息
对于一些更大的数组大小,看起来这种“拼接”方法可能比 Sun Bear 的 for 循环或 U12-Forward 的排列更快。
import numpy as np
import timeit
rng = np.random.default_rng(12345)
a = rng.random(size=(500, 100))
b = rng.integers(100, size=(500, 500))
change_cols = rng.choice(500, size=100)
def splice():
b[:, change_cols] = a[:, ::-1]
def splice_arange():
b[:, change_cols] = a[:,-(np.arange(len(change_cols)) + 1)]
def enumerate_for_loop():
for n, i in enumerate(change_cols):
b[:,i] = a[:,-(n+1)]
print("Splice")
print(timeit.timeit('splice()', number=10000, globals=globals()))
print("Splice arange")
print(timeit.timeit('splice_arange()', number=10000, globals=globals()))
print("Enumerate for loop")
print(timeit.timeit('enumerate_for_loop()', number=10000, globals=globals()))
结果:
Splice
1.2409849390387535
Splice arange
1.4882377870380878
Enumerate for loop
2.198731765151024
关于python - 如何在指定的 col 位置更改 2D numpy 数组中的某些元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69340638/