python - 如何在指定的 col 位置更改 2D numpy 数组中的某些元素?

标签 python numpy

我有这些信息:

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/

相关文章:

python - Keras 中间层输出

python - 获取 Telegram 机器人所有者的位置

python - 使用 python 定位矩阵中的第 j-k 个元素

numpy - 跨两个 2D numpy 数组获取相交行

python - 数据框中单列的多个条件,pandas

python - 将静态项目上传到谷歌应用引擎

Python - csr_matrix 的数据结构

python - 具有二维值和索引数组的 numpy 二维数组赋值

python - Numpy 无法在内存中存储大于 1GB 的矩阵

python - Django StreamingHttpResponse 格式错误