【问题标题】:Is there a multi-dimensional version of arange/linspace in numpy?numpy 中是否有 arange/linspace 的多维版本?
【发布时间】:2015-11-19 09:57:19
【问题描述】:

我想要一个二维 NumPy 数组 (x,y) 的列表,其中每个 x 在 {-5, -4.5, -4, -3.5, ..., 3.5, 4, 4.5, 5} 和y 也一样。

我可以的

x = np.arange(-5, 5.1, 0.5)
y = np.arange(-5, 5.1, 0.5)

然后遍历所有可能的对,但我确信有更好的方法...

我想要一些类似的东西:

[[-5, -5],
 [-5, -4.5],
 [-5, -4],
 ...
 [5, 5]]

但顺序无关紧要。

【问题讨论】:

标签: python numpy cartesian-product


【解决方案1】:

你可以使用np.mgrid,它通常比np.meshgrid更方便,因为它一步创建数组:

import numpy as np
X,Y = np.mgrid[-5:5.1:0.5, -5:5.1:0.5]

对于类似 linspace 的功能,将步骤(即0.5)替换为a complex number,其大小指定了您想要在系列中的点数。使用这种语法,与上面相同的数组被指定为:

X, Y = np.mgrid[-5:5:21j, -5:5:21j]

然后您可以将您的配对创建为:

xy = np.vstack((X.flatten(), Y.flatten())).T

正如@ali_m 建议的那样,这一切都可以在一行中完成:

xy = np.mgrid[-5:5.1:0.5, -5:5.1:0.5].reshape(2,-1).T

祝你好运!

【讨论】:

  • ...或作为单行,xy = np.mgrid[-5:5.1:0.5, -5:5.1:0.5].reshape(2, -1).T
【解决方案2】:

这正是您要寻找的:

matr = np.linspace((1,2),(10,20),10)

这意味着:

对于第一列; 从 (1,2) 的 1 到 (10,20) 的 10,输入递增的 10 个数字。

对于第二列; 从 (1,2) 的 2 到 (10,20) 的 20,输入递增的 10 个数字。

结果将是:

[[ 1.  2.]
 [ 2.  4.]
 [ 3.  6.]
 [ 4.  8.]
 [ 5. 10.]
 [ 6. 12.]
 [ 7. 14.]
 [ 8. 16.]
 [ 9. 18.]
 [10. 20.]]

你也可以只增加一列的值,例如,如果你这样说:

matr = np.linspace((1,2),(1,20),10)

第一列将从 (1,2) 的 1 到 (1,20) 的 1 持续 10 次,这意味着它将保持为 1,结果将是:

[[ 1.  2.]
 [ 1.  4.]
 [ 1.  6.]
 [ 1.  8.]
 [ 1. 10.]
 [ 1. 12.]
 [ 1. 14.]
 [ 1. 16.]
 [ 1. 18.]
 [ 1. 20.]]

【讨论】:

  • 在 1.16 之前的 numpy 版本中,这将引发错误。见stackoverflow.com/questions/57269217/…
  • 这不是二维的。
  • 也可以使用列表作为输入!非常适合作为网格网格的预处理步骤
【解决方案3】:

我想你想要np.meshgrid:

从坐标向量返回坐标矩阵。

在给定一维坐标数组 x1、x2、...、xn 的情况下,为 N 维网格上的 N 维标量/向量场的矢量化评估创建 N 维坐标数组。

import numpy as np
x = np.arange(-5, 5.1, 0.5)
y = np.arange(-5, 5.1, 0.5)
X,Y = np.meshgrid(x,y)

您可以将其转换为您想要的输出

XY=np.array([X.flatten(),Y.flatten()]).T

print XY
array([[-5. , -5. ],
       [-4.5, -5. ],
       [-4. , -5. ],
       [-3.5, -5. ],
       [-3. , -5. ],
       [-2.5, -5. ],
       ....
       [ 3. ,  5. ],
       [ 3.5,  5. ],
       [ 4. ,  5. ],
       [ 4.5,  5. ],
       [ 5. ,  5. ]])

【讨论】:

  • 这会返回两个大矩阵,我认为我仍然需要对其进行迭代才能获得所需的对矩阵。我错了吗?
  • 查看我的编辑:您可以轻松地将其转换为所需的数组,无需迭代
  • 在 numpy 中几乎从不需要迭代;)
【解决方案4】:

如果您只想遍历对(而不是一次对整个点集进行计算),您最好使用itertools.product 来遍历所有可能的对:

import itertools

for (xi, yi) in itertools.product(x, y):
    print(xi, yi)

这避免了通过meshgrid 生成大型矩阵。

【讨论】:

    【解决方案5】:

    我们可以使用排列函数:

    z1 = np.array([np.array(np.arange(1,5)),np.array(np.arange(1,5))])
    print(z1)
    o/p=> [[1 2 3 4]
           [1 2 3 4]]
    

    【讨论】:

    • np.array(np.arange(?
    • 这不是二维的。
    【解决方案6】:

    不确定我是否理解这个问题 - 制作一个 2-element NumPy 数组的列表,这样可以:

    import numpy as np
    x = np.arange(-5, 5.1, 0.5)
    X, Y = np.meshgrid(x, x)
    Liszt = [np.array(thing) for thing in zip(X.flatten(), Y.flatten())] # for python 2.7
    

    zip 为您提供一个元组列表,其余的由列表推导式完成。

    【讨论】:

      【解决方案7】:

      这是一种优雅的做法:

      xy = [(i,j) for i in np.linspace(1,4,4) for j in np.linspace(0,2,3)]
      

      这是print(xy) 的输出:

      [(1.0, 0.0),
       (1.0, 1.0),
       (1.0, 2.0),
       (2.0, 0.0),
       (2.0, 1.0),
       (2.0, 2.0),
       (3.0, 0.0),
       (3.0, 1.0),
       (3.0, 2.0),
       (4.0, 0.0),
       (4.0, 1.0),
       (4.0, 2.0)]
      

      【讨论】:

        【解决方案8】:

        这不是超快速的解决方案,但适用于任何维度

        import numpy as np
        def linspace_md(v_min,v_max,dim,num):
            output = np.empty( (num**dim,dim)  )
            values = np.linspace(v_min,v_max,num)
            for i in range(output.shape[0]):
                for d in range(dim):
                    output[i][d] = values[( i//(dim**d) )%num]
            return output
        

        【讨论】:

          【解决方案9】:

          我仍然使用 Linspace,因为我更喜欢坚持这个命令。

          您可以创建如下格式: np.linspace(np.zeros(width)[0], np.full((1,width),-1)[0], height)

          np.linspace(np.zeros(5)[0],np.full((1,5),-1)[0],5)
          

          输出以下内容:

          array([[ 0.  ,  0.  ,  0.  ,  0.  ,  0.  ],
                 [-0.25, -0.25, -0.25, -0.25, -0.25],
                 [-0.5 , -0.5 , -0.5 , -0.5 , -0.5 ],
                 [-0.75, -0.75, -0.75, -0.75, -0.75],
                 [-1.  , -1.  , -1.  , -1.  , -1.  ]])
          

          添加 .tranpose() 然后你得到:

          array([[ 0.  , -0.25, -0.5 , -0.75, -1.  ],
                [ 0.  , -0.25, -0.5 , -0.75, -1.  ],
                [ 0.  , -0.25, -0.5 , -0.75, -1.  ],
                [ 0.  , -0.25, -0.5 , -0.75, -1.  ],
                [ 0.  , -0.25, -0.5 , -0.75, -1.  ]])
          

          【讨论】:

            【解决方案10】:

            这是我仅使用 numpy 从数组创建坐标网格的解决方案(我必须想出一个在 jax 中使用 vmap 的解决方案):

            def grid(*args):
              return np.stack(np.meshgrid(*args, indexing='ij'), axis=-1)
            

            现在grid([1,2,3], [4,5,6])会给你:

            array([[[1, 4],
                    [1, 5],
                    [1, 6]],
            
                   [[2, 4],
                    [2, 5],
                    [2, 6]],
            
                   [[3, 4],
                    [3, 5],
                    [3, 6]]])
            

            您可以将其与 linspace 组合如下以获得 2D 坐标网格:

            def lingrid(x_start, x_stop, x_steps, y_start, y_stop, y_steps):
              a = np.linspace(x_start, x_stop, x_steps)
              b = np.linspace(y_start, y_stop, y_steps)
              return grid(a, b)
            

            例如,lingrid(0, 1, 3, 0, 2, 3) 给你:

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

            【讨论】:

              【解决方案11】:

              您可以利用 Numpy 的广播规则来简单地创建网格。例如,当我想在从 1 到 24 的线性数组上执行与 np.reshape 等效的操作(这是另一个不错的选择)时,我会这样做:

              row = np.array([1,2,3,4,5,6])
              col = np.array([0,6,12,18])
              grid = col[:, None] +row[None, :]
              

              结果是:

              array([[ 1,  2,  3,  4,  5,  6],
                     [ 7,  8,  9, 10, 11, 12],
                     [13, 14, 15, 16, 17, 18],
                     [19, 20, 21, 22, 23, 24]])
              

              注意np.newaxis 是 None 的别名,用于扩展 Numpy 数组的维度。许多人更喜欢 np.newaxis 而不是 None ,因为我使用它的可读性。

              这里我使用 sum 来组合网格,所以它将是行加上第一个列元素构成结果中的第一行,然后是同一行加上第二个列元素构成结果中的第二行等。当内容基于这样的两个数组时,其他算术运算可用于所需的任何网格。

              如上所述,上面的结果与下面给出的reshape 返回的结果相同,但广播选项为其他选项提供了更大的灵活性,因此值得注意。

              np.reshape(np.arange(1,25),(4,6))
              

              【讨论】:

                【解决方案12】:

                根据这个例子,你可以做任何你想要的暗淡

                def linspace3D(point1,point2,length):
                    v1 = np.linspace(point1[0],point2[0],length)
                    v2 = np.linspace(point1[1],point2[1],length)
                    v3 = np.linspace(point1[2],point2[2],length)
                    line = np.zeros(shape=[length,3])
                    line[:,0]=v1
                    line[:,1]=v2
                    line[:,2]=v3
                    return line
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2018-03-23
                  • 2020-08-17
                  • 2021-02-19
                  • 1970-01-01
                  • 2015-06-25
                  • 2018-02-07
                  • 2012-11-16
                  • 1970-01-01
                  相关资源
                  最近更新 更多