numpy - 评估点网格上的函数

时间:2014-04-01 00:35:07

标签: python arrays numpy

生成包含在n维网格点上计算的函数值的numpy数组有什么好方法?

例如,假设我想评估

定义的函数
def func(x, y):
    return <some function of x and y>

假设我想在二维点阵列上对其进行评估,其中x值以10步为单位从0到4,并且y值在20步中从-1到1。在numpy中这样做的好方法是什么?

P.S。这已经多次在StackOverflow上以各种形式提出,但我找不到简明扼要的问题和答案。我发布了这个提供简洁的简单解决方案(下面)。

5 个答案:

答案 0 :(得分:22)

更短,更快,更清晰的答案,避免使用meshgrid:

import numpy as np

def func(x, y):
    return np.sin(y * x)

xaxis = np.linspace(0, 4, 10)
yaxis = np.linspace(-1, 1, 20)
result = func(xaxis[:,None], yaxis[None,:])

如果你得到像x ^ 2 + y这样的函数,那么内存会更快,因为x ^ 2是在一维数组(而不是2D数组)上完成的,而尺寸的增加只发生在你做&#34; +&#34;。对于meshgrid,x ^ 2将在2D数组上完成,其中基本上每行都相同,导致大量时间增加。

编辑:&#34; x [:,无]&#34;,使x成为2D数组,但第二维空。这&#34;无&#34;与使用&#34; x [:,numpy.newaxis]&#34;相同。使用Y完成同样的事情,但是先制作一个空的第一维。

编辑:3维:

def func2(x, y, z):
    return np.sin(y * x)+z

xaxis = np.linspace(0, 4, 10)
yaxis = np.linspace(-1, 1, 20)
zaxis = np.linspace(0, 1, 20)
result2 = func2(xaxis[:,None,None], yaxis[None,:,None],zaxis[None,None,:])

这样,您可以根据需要轻松扩展到n个维度,使用尽可能多的None:维度。每个:生成一个维度,每个None生成一个&#34;空的&#34;尺寸。下一个示例更多地展示了这些空白维度的工作原理。正如您所看到的,如果您使用None,形状会发生变化,在下一个示例中显示它是一个3D对象,但只有在您实际拥有这些尺寸内容的对象相乘时,空尺寸才会被填满(听起来很复杂,但下一个例子显示了我的意思)

In [1]: import numpy

In [2]: a = numpy.linspace(-1,1,20)

In [3]: a.shape
Out[3]: (20,)

In [4]: a[None,:,None].shape 
Out[4]: (1, 20, 1)

In [5]: b = a[None,:,None] # this is a 3D array, but with the first and third dimension being "empty"
In [6]: c = a[:,None,None] # same, but last two dimensions are "empty" here

In [7]: d=b*c 

In [8]: d.shape # only the last dimension is "empty" here
Out[8]: (20, 20, 1)

编辑:无需自己输入“无”

def ndm(*args):
    return [x[(None,)*i+(slice(None),)+(None,)*(len(args)-i-1)] for i, x in enumerate(args)]


x2,y2,z2  = ndm(xaxis,yaxis,zaxis)
result3 = func2(x2,y2,z2)

通过这种方式,您可以通过将第一个参数赋予ndm作为第一个完整维度,第二个参数作为第二个完整维度等来进行None - 切片以创建额外的空维度 - 它也是相同的作为&#39;硬编码&#39;之前使用的无类型语法。

简短说明:执行x2, y2, z2 = ndm(xaxis, yaxis, zaxis)与执行

相同
x2 = xaxis[:,None,None]
y2 = yaxis[None,:,None]
z2 = zaxis[None,None,:]

但是ndm方法也适用于更多维度,而不需要像刚刚显示的那样在多行中对None - 片进行硬编码。这也适用于1.8之前的numpy版本,而numpy.meshgrid仅适用于高于2维的情况,如果你有1.8或更高的numpy。

答案 1 :(得分:10)

import numpy as np

def func(x, y):
    return np.sin(y * x)

xaxis = np.linspace(0, 4, 10)
yaxis = np.linspace(-1, 1, 20)
x, y = np.meshgrid(xaxis, yaxis)
result = func(x, y)

答案 2 :(得分:3)

如果您的函数实际上采用了d元素的元组,即f((x1,x2,x3,...xd))(例如scipy.stats.multivariate_normal function),并且您想在N ^上评估f d组合/ N个变量的网格,您也可以执行以下操作(2D情况):

x=np.arange(-1,1,0.2)   # each variable is instantiated N=10 times
y=np.arange(-1,1,0.2)
Z=f(np.dstack(np.meshgrid(x,y)))    # result is an NxN (10x10) matrix, whose entries are f((xi,yj))

此处np.dstack(np.meshgrid(x,y))创建一个10x10&#34;矩阵&#34; (技术上是一个10x10x2 numpy数组),其条目是由f评估的二维元组。

答案 3 :(得分:3)

我使用此函数来准备绘制X,Y,Z值:

def npmap2d(fun, x_spec, y_spec, doPrint=False):
  xs = np.linspace(*x_spec)
  ys = np.linspace(*y_spec)
  Z = np.empty(len(xs) * len(ys))
  i = 0
  for y in ys:
    for x in xs:
      Z[i] = fun(x, y)
      if doPrint: print([i, x, y, Z[i]])
      i += 1
  X, Y = np.meshgrid(xs, ys)
  Z.shape = X.shape
  return X, Y, Z

用法:

def f(x, y): 
  # ...some function that can't handle numpy arrays

X, Y, Z = npmap2d(f, (0, 0.5, 21), (0.6, 0.4, 41))

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_wireframe(X, Y, Z)

使用map:

可以获得相同的结果
xs = np.linspace(0, 4, 10)
ys = np.linspace(-1, 1, 20)
X, Y = np.meshgrid(xs, ys)
Z = np.fromiter(map(f, X.ravel(), Y.ravel()), X.dtype).reshape(X.shape)

答案 4 :(得分:0)

我的两分钱:

    import numpy as np

    x = np.linspace(0, 4, 10)
    y = np.linspace(-1, 1, 20)

    [X, Y] = np.meshgrid(x, y, indexing = 'ij', sparse = 'true')

    def func(x, y):
        return x*y/(x**2 + y**2 + 4)
        # I have defined a function of x and y.

   func(X, Y)