在numpy中是否有arange / linspace的多维版本?

119

我想要一个2d 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]]

但是顺序并不重要。


1
你有问题吗?编辑:我看到了这个问题 xy = np.matrix([x, y]) - Andy Kubiak
1
这只是将两个数组连接起来。 - Hilemonstoer
1
我有点困惑,“我想要的输出结果是:”和“其中每个x在{-5,-4.5,-4,-3.5,...,3.5,4,4.5,5}中,并且y也是如此”的描述似乎不匹配。 - Ciro Santilli OurBigBook.com
12个回答

110
您可以使用 np.mgrid 来实现此功能,它通常比 np.meshgrid 更方便,因为它可以一步创建数组:
import numpy as np
X,Y = np.mgrid[-5:5.1:0.5, -5:5.1:0.5]

如果需要类似于linspace的功能,请使用复数(例如0.5j)代替步长。复数的幅度指定了你想要在序列中有多少个点。使用这种语法,可以将与上述相同的数组指定为:

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

祝你好运!


24
将该代码翻译为一句话:xy = np.mgrid[-5到5.1间隔0.5, -5到5.1间隔0.5].reshape(2, -1).T,翻译后的代码与原代码意思相同,但更加通俗易懂。 - ali_m

42

这正是您正在寻找的内容:

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.]]

在numpy 1.16之前的版本中,这将会抛出一个错误。请参见https://stackoverflow.com/questions/57269217/the-truth-value-of-an-array-with-more-than-one-element-is-ambiguous-numpy-error - Techniquab
3
这不是二维的。 - oulenz
也适用于列表作为输入!作为网格预处理步骤非常好。 - Yuri Feldman

19
我认为你需要的是 np.meshgrid
从坐标向量返回坐标矩阵。
使用一维坐标数组 x1,x2,...,xn,为标量/向量场在 N-D 网格上进行向量化评估,生成 N-D 坐标数组。
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. ]])

这将返回两个大矩阵,我认为我仍然需要迭代这些矩阵才能得到我想要的成对矩阵。我错了吗? - Hilemonstoer
请看我的编辑:您可以轻松地将其转换为所需的数组,而无需迭代。 - tmdavison
1
在numpy中几乎从不需要迭代 ;) - JoseOrtiz3

8

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

import itertools

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

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

5
我们可以使用arrange函数,如下所示:
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]]

1
np.array(np.arange(? - CristiFati
这不是二维的。 - oulenz

2

这是一种优雅的做法:

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)]

1
我不确定我是否理解了这个问题——要创建一个由两个元素的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会给你一个元组列表,而列表推导式则完成其余部分。


1

我仍然使用 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.  ]])

添加.transpose(),然后你会得到:

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.  ]])

0

您可以利用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))

0
这是我使用仅限于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方法,得到二维坐标网格:
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. ]]])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接