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

时间:2018-12-16 20:44:29

标签: python loops numpy

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

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的运行速度通常会更快,但是我不知道如何做到这一点。

2 个答案:

答案 0 :(得分:3)

您可以使用np.mgrid

arr = np.random.uniform(size=(5,5))

n_rows, n_cols = arr.shape
r, c = np.ogrid[0:n_rows, 0:n_cols]
arr -= 1000 * r + 500 * c

答案 1 :(得分:3)

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

观察:

  • 对于大小为1000的数组,最快的方法比mgrid快三倍以上
  • 使用ogrid或手动操作,最好分别添加两个范围,从而避免出现全尺寸的临时图片
  • mgridogrid这样的便利往往会以numpy为代价,实际上,手动方法的速度是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