Python numpy - 在点网格上评估函数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22774726/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
numpy - evaluate function on a grid of points
提问by DanielSank
What is a good way to produce a numpy array containing the values of a function evaluated on an n-dimensional grid of points?
生成包含在 n 维点网格上评估的函数值的 numpy 数组的好方法是什么?
For example, suppose I want to evaluate the function defined by
例如,假设我想评估由
def func(x, y):
return <some function of x and y>
Suppose I want to evaluate it on a two dimensional array of points with the x values going from 0 to 4 in ten steps, and the y values going from -1 to 1 in twenty steps. What's a good way to do this in numpy?
假设我想在一个二维点数组上对其进行评估,其中 x 值分十步从 0 到 4,而 y 值分二十步从 -1 到 1。在 numpy 中这样做的好方法是什么?
P.S. This has been asked in various forms on StackOverflow many times, but I couldn't find a concisely stated question and answer. I posted this to provide a concise simple solution (below).
PS 这个已经在 StackOverflow 上以各种形式被问过很多次了,但是我找不到一个简明扼要的问答。我发布这个是为了提供一个简洁的简单解决方案(如下)。
采纳答案by usethedeathstar
shorter, faster and clearer answer, avoiding 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,:])
This will be faster in memory if you get something like x^2+y as function, since than x^2 is done on a 1D array (instead of a 2D one), and the increase in dimension only happens when you do the "+". For meshgrid, x^2 will be done on a 2D array, in which essentially every row is the same, causing massive time increases.
如果你得到像 x^2+y 这样的函数,这在内存中会更快,因为 x^2 是在一维数组(而不是二维数组)上完成的,并且维度的增加只会在你执行“ +”。对于 meshgrid,x^2 将在二维数组上完成,其中基本上每一行都是相同的,从而导致大量时间增加。
Edit: the "x[:,None]", makes x to a 2D array, but with an empty second dimension. This "None" is the same as using "x[:,numpy.newaxis]". The same thing is done with Y, but with making an empty first dimension.
编辑:“x[:,None]”,使 x 为二维数组,但第二维为空。此“无”与使用“x[:,numpy.newaxis]”相同。对 Y 也做同样的事情,但要创建一个空的第一维。
Edit: in 3 dimensions:
编辑:在 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,:])
This way you can easily extend to n dimensions if you wish, using as many None
or :
as you have dimensions. Each :
makes a dimension, and each None
makes an "empty" dimension. The next example shows a bit more how these empty dimensions work. As you can see, the shape changes if you use None
, showing that it is a 3D object in the next example, but the empty dimensions only get filled up whenever you multiply with an object that actually has something in those dimensions (sounds complicated, but the next example shows what i mean)
这样,您就可以轻松地扩展到N维,如果你愿意的话,使用尽可能多None
或:
作为你的尺寸。每个:
构成一个维度,每个None
构成一个“空”维度。下一个示例更多地展示了这些空维度是如何工作的。如您所见,如果使用 ,则形状会发生变化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)
edit: without needing to type the None yourself
编辑:无需自己输入 None
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)
This way, you make the None
-slicing to create the extra empty dimensions, by making the first argument you give to ndm as the first full dimension, the second as second full dimension etc- it does the same as the 'hardcoded' None-typed syntax used before.
通过这种方式,您可以None
通过将您提供给 ndm 的第一个参数作为第一个完整维度,将第二个作为第二个完整维度等进行-slicing 以创建额外的空维度 - 它与“硬编码”无类型之前使用的语法。
Short explanation: doing x2, y2, z2 = ndm(xaxis, yaxis, zaxis)
is the same as doing
简短说明:做x2, y2, z2 = ndm(xaxis, yaxis, zaxis)
与做相同
x2 = xaxis[:,None,None]
y2 = yaxis[None,:,None]
z2 = zaxis[None,None,:]
but the ndm method should also work for more dimensions, without needing to hardcode the None
-slices in multiple lines like just shown. This will also work in numpy versions before 1.8, while numpy.meshgrid only works for higher than 2 dimensions if you have numpy 1.8 or higher.
但是 ndm 方法也应该适用于更多维度,而无需None
像刚刚显示的那样在多行中对-slices进行硬编码。这也适用于 1.8 之前的 numpy 版本,而 numpy.meshgrid 仅适用于高于 2 维的 numpy 1.8 或更高版本。
回答by DanielSank
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)
回答by Yibo Yang
In the case your function actually takes a tuple of d
elements, i.e. f((x1,x2,x3,...xd))
(for example the scipy.stats.multivariate_normal function), and you want to evaluate f
on N^d combinations/grid of N variables, you could also do the following (2D case):
在这种情况下你的功能,其实需要的元组d
元素,即f((x1,x2,x3,...xd))
(例如scipy.stats.multivariate_normal功能),你要评估f
N个^ 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))
Here np.dstack(np.meshgrid(x,y))
creates an 10x10 "matrix" (technically a 10x10x2 numpy array) whose entries are the 2-dimensional tuples to be evaluated by f
.
这里np.dstack(np.meshgrid(x,y))
创建了一个 10x10 的“矩阵”(技术上是一个 10x10x2 的 numpy 数组),其条目是由f
.
回答by rainman
My two cents:
我的两分钱:
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)
回答by grabantot
I use this function to get X, Y, Z values ready for plotting:
我使用此函数来获取 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
Usage:
用法:
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)
The same result can be achieved using map:
使用 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)