python - 在 Numpy 中迭代的更多 pythonic 方式

标签 python numpy iterator scientific-computing

我是一名工科学生,我习惯于使用 Fortran 编写代码,但现在我正尝试使用 Numpy 更深入地了解 Python,以编写我的数字食谱。

如果我需要使用来自多个数组的元素重复执行计算,那么我用 Fortran 编写的内容的直接翻译将是

k = np.zeros(N, dtype=np.float)
u = ...
M = ...
r = ...
for i in xrange(N):
  k[i] = ... # Something with u[i], M[i], r[i] and r[i - 1], for example

但我想知道这种方式是否更像 pythonic,或者以任何方式更可取:

for i, (k_i, u_i, M_i, r_i) in enumerate(zip(k, u, M, r)):
  k_i = ... # Something with u_i, M_i, r_i and r[i - 1]

感谢 enumerate 我有索引,否则如果我不需要它我可以只使用 zip 或 itertools.izip。

有什么想法吗?代码在性能方面如何受到影响?有没有其他方法可以做到这一点?

最佳答案

几乎所有的 numpy 操作都是按元素执行的。因此,与其编写显式循环,不如尝试使用基于数组的公式定义 k:

r_shifted = np.roll(x, shift = 1)
k = ... # some formula in terms of u, M, r, r_shifted

例如,代替

import numpy as np

N=5
k = np.zeros(N, dtype=np.float)
u = np.ones(N, dtype=np.float)
M = np.ones(N, dtype=np.float)
r = np.ones(N, dtype=np.float)
for i in xrange(N):
  k[i] = u[i] + M[i] + r[i] + r[i-1]
print(k)  
# [ 4.  4.  4.  4.  4.]

使用:

r_shifted = np.roll(r, shift = 1)
k = u + M + r + r_shifted
print(k)
# [ 4.  4.  4.  4.  4.]

np.roll(r, shift = 1)返回一个与 r 大小相同的新数组,其中 r_shifted[i] = r[i-1] for i = 0, ..., N -1.

In [31]: x = np.arange(5)

In [32]: x
Out[32]: array([0, 1, 2, 3, 4])

In [33]: np.roll(x, shift = 1)
Out[33]: array([4, 0, 1, 2, 3])

制作这样的副本需要更多内存(与 r 大小相同)但允许您执行快速 numpy 操作而不是使用慢速 Python 循环。


有时 k 的公式可以根据 r[:-1]r[1:] 来定义。注意 r[:-1]r[1:]r 的切片并且具有相同的形状。 在这种情况下,您不需要任何额外的内存,因为 r 的基本切片是 r 的所谓 View ,而不是副本。

在上面的例子中我没有这样定义 k 因为 k 的长度是 N-1 而不是 N,因此它与您的原始代码生成的内容略有不同。

关于python - 在 Numpy 中迭代的更多 pythonic 方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8634850/

相关文章:

python - 从另一列 pandas df 分配值的有效方法

python - 重复可迭代对象元素的迭代器

java - 如何从集合中删除

python - QMetaProperty::read:无法处理未注册的数据类型 'QAbstractListModel*'

python - 类型错误 : () got an unexpected keyword argument

python - 如何创建具有不同值的新表,但从另一列中选择最大值

c++ - C++ 中是否有标准的循环迭代器

python - Cython lapack 不会覆盖参数

python - 从 numpy 数组中的每个字符串中提取第一个字母

python - python/numpy中的线性组合