Skip to main content
 首页 » 编程设计

Python 非循环方式根据行和列位置更改数组值

2025年05月04日15pengyingh

我正在尝试根据它们的列和行位置更改 numpy 数组值,目前正在以这种方式实现它:

for r in range(ResultArr2.shape[0]): 
    for c in range(ResultArr2.shape[1]): 
        ResultArr2[r,c] = ResultArr2[r,c]-r*1000-c*500 

是否有一种非循环的方法可以达到相同的结果?我知道如果实现非循环结构,Python 通常会运行得更快,但我不知道如何做到这一点。

请您参考如下方法:

以下是使用 mgrid 或 ogrid 或手动创建 ogrid 生成的相同范围的一些变体。

观察:

  • 对于大小为 1000 的数组,最快的方法比 mgrid 快三倍以上
  • 使用 ogrid 或手动将两个范围分开添加会更好一些,从而避免全尺寸临时
  • mgrid 或 ogrid 等便利性往往以 numpy 为代价,实际上手动方法的速度是 的两倍code>ogrid

代码:

import numpy as np 
 
from timeit import timeit 
 
A = np.arange(1000).reshape(20, 50) 
 
def f(): 
    B = A.copy() 
    m, n = B.shape 
    I, J = np.mgrid[:m*1000:1000, :n*500:500] 
    B += I+J 
    return B 
 
def g(): 
    B = A.copy() 
    m, n = B.shape 
    I, J = np.ogrid[:m*1000:1000, :n*500:500] 
    B += I+J 
    return B 
 
def h(): 
    B = A.copy() 
    m, n = B.shape 
    I, J = np.ogrid[:m*1000:1000, :n*500:500] 
    B += I 
    B += J 
    return B 
 
def i(): 
    B = A.copy() 
    m, n = B.shape 
    BT = B.T 
    BT += np.arange(0, 1000*m, 1000) 
    B += np.arange(0, 500*n, 500) 
    return B 
 
def j(): 
    B = A.copy() 
    m, n = B.shape 
    B += np.arange(0, 1000*m, 1000)[:, None] 
    B += np.arange(0, 500*n, 500) 
    return B 
 
 
assert np.all(f()==h()) 
assert np.all(g()==h()) 
assert np.all(i()==h()) 
assert np.all(j()==h()) 
 
print(timeit(f, number=10000)) 
print(timeit(g, number=10000)) 
print(timeit(h, number=10000)) 
print(timeit(i, number=10000)) 
print(timeit(j, number=10000)) 

样本运行:

0.289166528998976    # mgrid                                                                                                
0.25259370900130307  # ogrid 1 step                                                                                                
0.24528862700026366  # ogrid 2 steps                                                                                                
0.09056068700010655  # manual transpose                                                                                              
0.08238107499892067  # manual add dim