【问题标题】:Iterate over two numpy 2d matrices using nditer使用 nditer 迭代两个 numpy 2d 矩阵
【发布时间】:2018-07-21 07:44:58
【问题描述】:

我正在尝试迭代两个 numpy 矩阵,一个大小为 nx3,另一个大小为 nx1

我正在尝试让 nditer 同时迭代它们的行。

如果我们有:

y = np.array([   [ 1],
                 [-1],
                 [ 1]   ])
x = np.array([[ 1.3432504 , -1.3311479 ,  1.        ],
             [ 1.8205529 , -0.6346681 ,  1.         ],
             [ 0.98632067, -1.8885762 ,  1.         ]])

我试试:

for (a,b) in iterator:
   print(a)
   print(b)

这应该给

[1]
[ 1.3432504 , -1.3311479 ,  1.        ]
[-1]
[ 1.8205529 , -0.6346681 ,  1.         ]
[1]
[ 0.98632067, -1.8885762 ,  1.         ]

我尝试了带有“external_loop flag”的 np.nditer,我得到了 x 的所需输出,但是当我一次只想要一个时,它强制 y 分成 3 个元素。

提前谢谢你。

【问题讨论】:

  • 什么是iteratornditer 使用起来并不容易,并且在 Python 代码中使用时不会提供任何性能价值。您需要一直阅读教程页面到cython 示例。
  • 查看apply_along_axis的代码。它使用ndindex 生成索引,然后使用这些索引遍历除一个轴之外的所有数组。看看ndindex。它使用nditermulti_index。我不知道另一个使用 Python API 到 nditernumpy 函数。

标签: python numpy matrix iterator


【解决方案1】:

使用nditer 很难控制迭代的“深度”。比如最简单的情况:

In [35]: for i,j in np.nditer([y, x]):
    ...:     print(i, j)
    ...:     
1 1.3432504
1 -1.3311479
1 1.0
-1 1.8205529
-1 -0.6346681
-1 1.0
1 0.98632067
1 -1.8885762
1 1.0

这会创建一个(i,j) pair of values for each broadcastable combination ofyandx.xis (3, 3),yis (3,1),结果是对 (3,3).flat 的迭代。

(如果xnp.arange(n)nditer 将生成 (3,1) 数组与 (1,n) 的所有组合,即 (3,n) 集合。

您不能轻易告诉nditer 仅在x 的行上进行迭代。 external_loop 可以做到,但无法预测。

ndindex 为给定深度生成索引,但它通过创建正确形状的数组来实现。

In [38]: for i,j in np.ndindex(2,3):
    ...:     print(i,j)
    ...:     
0 0
0 1
0 2
1 0
1 1
1 2

或者迭代你的 2 个数组的行:

In [39]: for i in np.ndindex(3):
    ...:     print(y[i], x[i,:])
    ...:     
[1] [[ 1.3432504 -1.3311479  1.       ]]
[-1] [[ 1.8205529 -0.6346681  1.       ]]
[1] [[ 0.98632067 -1.8885762   1.        ]]

但你也可以使用for i in range(3):

np.nditer 是开发cython 或其他c-api 代码的垫脚石。 nditer的c-api版本功能强大,速度也比较好。 python 等价物既不快也不强大。

您的 cmets 提到了与 apply_along_axis 的进一步接口。这是用 Python 编写的,并使用 ndindex 为需要迭代的轴生成索引。它可能会使某些任务更方便,但不会加快您的代码速度。

【讨论】:

  • 这澄清了很多事情,我应该继续使用一些更简单的东西,例如 zip、range 或 nditer。这背后的想法是为 numpy 数组找到某种 zip 等价物,nditer 并非如此。感谢您的清晰解释。
【解决方案2】:

可以使用zip()内置函数:

In [22]: for i, j in zip(y, x):
             print(i);print(j)
   ....:     
[1]
[ 1.3432504 -1.3311479  1.       ]
[-1]
[ 1.8205529 -0.6346681  1.       ]
[1]
[ 0.98632067 -1.8885762   1.        ]

【讨论】:

  • 我知道 zip,但我正在尝试使用 np.nditer 来提高效率
  • 如果你只想打印项目nditer 对这个任务来说有点过分了,zip 足够高效。
  • 它不是用于打印,而是用于带有 (a,b) 参数的函数,我将使用 np.apply_along_axis 的函数。这里的目标是创建提供两行的迭代,然后将该函数沿每一行应用到一个巨大的矩阵。
  • @Roulbacha 好吧,apply_along_axis 已经是您的 newar-C 级性能流程的问题,并且抽象会破坏链。因此,我认为在这种情况下使用zip 不会造成任何伤害。不过,您可以对这两种方法进行基准测试(即使使用错误的nditer 代码)只是为了安心;)。
  • zip 成为首选解决方案。 nditer 是不合适的。
猜你喜欢
  • 2013-05-14
  • 1970-01-01
  • 1970-01-01
  • 2019-12-26
  • 2016-05-12
  • 1970-01-01
  • 2014-09-25
  • 2018-01-02
  • 2013-06-30
相关资源
最近更新 更多