【问题标题】:How to specify depth of iterator in numpy?如何在numpy中指定迭代器的深度?
【发布时间】:2015-09-18 01:19:24
【问题描述】:

我在 numpy 中有一个多维数组(例如 4D),我想指定 numpy 迭代器的深度,但不知道该怎么做?

例如,假设我有一个 4D numpy 数组,并且我想从迭代器中获取元素,仅用于 2D 级别(因此每个项目也是 2D)。请问有没有办法在迭代器中指定这样的深度?

我确实想使用迭代器而不是双循环,并且我想使用 numpy 而不是字典和 pandas 等其他工具。

因此,我希望这段代码输出 [1 2] 而不是 1,2...

x = np.array(\
(\
\
(\
(np.array([1,2]), np.array([1,2])),\
(np.array([1,2]), np.array([1,2]))\
),\
\
(\
(np.array([1,2]), np.array([1,2])),\
(np.array([1,2]), np.array([1,2]))\
)\
\
)
, dtype = np.ndarray)

for i in np.nditer(x, flags = ["refs_ok"]):
     print i

给我:

1
2
1
2
1
2
1
2
1
2
1
2
1
2
1
2

代替:

[1 2]
[1 2]
[1 2]
[1 2]
[1 2]
[1 2]
[1 2]
[1 2]

【问题讨论】:

    标签: python arrays numpy iterator


    【解决方案1】:

    np.ndindex 在迭代指定维度方面做得很好。

    您的x 是一个4d object 数组dtype=ndarray 变为dtype=object。尽管元组大小相同,但元素实际上只是标量,而不是数组。

    In [385]: x
    Out[385]: 
    array([[[[1, 2],
             [1, 2]],
    
            [[1, 2],
             [1, 2]]],
    
    
           [[[1, 2],
             [1, 2]],
    
            [[1, 2],
             [1, 2]]]], dtype=object)
    
    In [386]: x.shape
    Out[386]: (2, 2, 2, 2)
    

    在任何情况下,np.ndindex 都会生成将迭代给定形状的数组的索引。

    In [387]: for i,j in np.ndindex(x.shape[:2]):
        print(i,j)       
        print(x[i,j])
       .....:     
    0 0
    [[1 2]
     [1 2]]
    0 1
    [[1 2]
     [1 2]]
    1 0
    [[1 2]
     [1 2]]
    1 1
    [[1 2]
     [1 2]]
    

    ndindex 的关键部分是as_strided 用于生成正确大小的虚拟矩阵,nditermulti_index 模式生成索引。

    此用法的早期示例:

    https://stackoverflow.com/a/28727290/901925

    Iterating over first d axes of numpy array

    更多关于尝试创建数组数组(不仅仅是更高维的数字数组):

    Convert a numpy array to an array of numpy arrays

    要创建一个真正是数组数组的x,您需要执行以下操作:

    In [397]: x=np.zeros((2,2,2),dtype=object)
    In [398]: for ijk in np.ndindex(x.shape):
                 x[ijk] = np.array([1,2])
    
    
    In [399]: x
    Out[399]: 
    array([[[array([1, 2]), array([1, 2])],
            [array([1, 2]), array([1, 2])]],
    
           [[array([1, 2]), array([1, 2])],
            [array([1, 2]), array([1, 2])]]], dtype=object)
    

    另一种选择是重塑初始尺寸,以便您可以对这些尺寸进行平面迭代:

    for i in x.reshape(-1,2):
        print(i)
    

    nditer(以及扩展名ndindex)被描述为高效,但这更适用于其C/cython 的使用。在纯 Python 代码中,迭代机制并不重要。迭代主体中的操作通常需要更多时间。当您需要在多个数组上进行坐标迭代时,nditer 也是最好的,如out[...] = a[...] * b[...]。仅遍历一个数组并没有什么特别之处。

    http://docs.scipy.org/doc/numpy-dev/reference/arrays.nditer.html

    是一个很好的nditer 教程。最后的cython部分是最好的部分。

    【讨论】:

    • 非常感谢,我要试试这个。你真棒!快速澄清一下:ndindex 和 nditer 之间有什么性能差异吗?
    • 我扩展了效率问题。
    • 非常感谢!我是 numpy 的新手。请问您是如何在 numpy 的细节方面变得如此出色的,以便我可以向您学习?请问有什么好的资源(书籍、课程等)可以推荐吗?对不起,如果我打扰你,那将是我的最后一个问题。再次感谢你! :)
    • @dvvvvvvvvvvvvvaaaaaaaaaaaaa 仔细阅读一个资源 (example),它深入地介绍了 numpy,找到你最喜欢 numpy 的特性,然后练习那些(代码 katas?)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-23
    • 1970-01-01
    • 2011-05-21
    • 2013-03-20
    • 1970-01-01
    • 2021-01-06
    • 1970-01-01
    相关资源
    最近更新 更多