代码之家  ›  专栏  ›  技术社区  ›  fstab

创建索引矩阵/列表的更简单方法?

  •  1
  • fstab  · 技术社区  · 12 年前

    我想知道创建一个二维数组的最简单方法是什么,它为每一行提供另一个多维数组的索引。

    例如,假设我有一个4x4的立方体,“索引矩阵”如下:

    np.concatenate([
        np.expand_dims(curr.ravel(),axis=0).T
        for curr
        in np.meshgrid(
            np.arange(4),
            np.arange(4),
            np.arange(4)
        )
    ],axis=1)
    

    结果如下:

    array([[0, 0, 0],
          [0, 0, 1],
          [0, 0, 2],
          [0, 0, 3],
          [1, 0, 0],
          [1, 0, 1],
          ...
          [2, 3, 2],
          [2, 3, 3],
          [3, 3, 0],
          [3, 3, 1],
          [3, 3, 2],
          [3, 3, 3]])
    

    除了第二列似乎应该取代第一列之外,是否有一种更为“numpythonic”的方法来以更紧凑的方式创建相同或相似的矩阵?

    如果存在一个只接受任意多维数组并返回其索引表的函数就好了。

    5 回复  |  直到 12 年前
        1
  •  7
  •   abarnert    12 年前

    你可以使用 np.indices :

    >>> a = np.random.random((4,4,4))
    >>> np.indices(a.shape).reshape((a.ndim, -1)).T
    array([[0, 0, 0],
           [0, 0, 1],
           [0, 0, 2],
           [0, 0, 3],
           [0, 1, 0],
           [0, 1, 1],
    [...]
           [3, 3, 2],
           [3, 3, 3]])
    

    还有其他实用程序,如 np.ndindex ,具体取决于您的用例。(FWIW我不认为以你想要的形式获得坐标会像你想象的那样有用,但YMMV。)

        2
  •  4
  •   Joran Beasley    12 年前

    我想

    list(itertools.product(range(4),range(4),range(4)))
    

    更像蟒蛇。。(注意,您可以使用 numpy.array 而不是列表,如果你很想…)

        3
  •  3
  •   abarnert    12 年前

    如果存在一个只接受任意多维数组并返回其索引表的函数就好了。

    如果我理解你的问题,有: indices :

    i = np.indices(a.shape)
    

    这不会为您提供所需形状的结果:

    >>> a = np.array([[1,2], [3,4], [5,6]])
    >>> print(np.indices(a.shape))
    [[[0 0]
      [1 1]
      [2 2]]
    
     [[0 1]
      [0 1]
      [0 1]]]
    

    但您可以将其展平并转置:

    [[0 0]
     [0 1]
     [1 0]
     [1 1]
     [2 0]
     [2 1]]
    
        4
  •  1
  •   abarnert    12 年前

    下面是如何做我认为你实际上 希望 根据您的评论:

    我需要测试存储在三维数组中的一些概率值。如果它们通过了一些测试条件,那么我会将它们添加到一个坐标列表中,该列表将在三维散点图中可视化。

    为了简单起见,我们假设测试是简单的,比如“是肯定的”。因此,我们只需将数组转换为每个元素的“元素为正”布尔数组 arr > 0 ,然后使用 nonzero 要获取该布尔数组的真实索引:

    >>> arr = np.array([[-1, 1], [2, -2], [-3, -3]])
    >>> print(arr > 0)
    [[False  True]
     [ True False]
     [False False]]
    >>> print(np.nonzero(arr > 0))
    (array([0, 1]), array([1, 0]))
    

    再简单不过了。

        5
  •  0
  •   Muhammad Yasirroni    4 年前

    对于那些来这里做MATLAB数组索引的人来说,这里有一个解决方案:

    idx = np.indices(a.shape).reshape((a.ndim, -1)).T
    idx = idx[idx[:,0].argsort()]
    for i in range(1,len(a.shape),1):
        idx = idx[idx[:,i].argsort(kind='mergesort')]
    

    测试:

    a = np.arange(24).reshape(3,2,4)
    # array([[[ 0,  1,  2,  3],
    #         [ 4,  5,  6,  7]],
    
    #        [[ 8,  9, 10, 11],
    #         [12, 13, 14, 15]],
    
    #        [[16, 17, 18, 19],
    #         [20, 21, 22, 23]]])
    idx = np.indices(a.shape).reshape((a.ndim, -1)).T
    idx = idx[idx[:,0].argsort()]
    for i in range(1,len(a.shape),1):
        idx = idx[idx[:,i].argsort(kind='mergesort')]
    
    for i in idx:
        print(i, a[tuple(i)])
    # [0 0 0] 0
    # [1 0 0] 8
    # [2 0 0] 16
    # [0 1 0] 4
    # [1 1 0] 12
    # [2 1 0] 20
    # [0 0 1] 1
    # [1 0 1] 9
    # [2 0 1] 17
    # [0 1 1] 5
    # [1 1 1] 13
    # [2 1 1] 21
    # [0 0 2] 2
    # [1 0 2] 10
    # [2 0 2] 18
    # [0 1 2] 6
    # [1 1 2] 14
    # [2 1 2] 22
    # [0 0 3] 3
    # [1 0 3] 11
    # [2 0 3] 19
    # [0 1 3] 7
    # [1 1 3] 15
    # [2 1 3] 23