SciPy有三种方法可以对样本(trapz,simps和romb)进行一维积分,一种方法可以在函数上进行二维积分(dblquad),但它似乎没有办法做一个样本上的二维积分 - 甚至是矩形网格上的二维积分。
我看到的最接近的是scipy.interpolate.RectBivariateSpline.integral - 你可以从矩形网格上的数据创建一个RectBivariateSpline然后集成它。但是,这并不快。
我想要比矩形方法更精确的东西(即只是总结一切)。我可以说,使用2D Simpson规则,通过制作一个具有正确权重的数组,将其乘以我想要整合的数组,然后总结结果。
然而,如果已经有更好的东西,我不想重新发明轮子。有吗?
答案 0 :(得分:18)
使用1D规则两次。
>>> from scipy.integrate import simps
>>> import numpy as np
>>> x = np.linspace(0, 1, 20)
>>> y = np.linspace(0, 1, 30)
>>> z = np.cos(x[:,None])**4 + np.sin(y)**2
>>> simps(simps(z, y), x)
0.85134099743259539
>>> import sympy
>>> xx, yy = sympy.symbols('x y')
>>> sympy.integrate(sympy.cos(xx)**4 + sympy.sin(yy)**2, (xx, 0, 1), (yy, 0, 1)).evalf()
0.851349922021627
答案 1 :(得分:0)
如果您要处理矩形上的真实二维积分,您将拥有类似的东西
>>> import numpy as np
>>> from scipy.integrate import simps
>>> x_min,x_max,n_points_x = (0,1,50)
>>> y_min,y_max,n_points_y = (0,5,50)
>>> x = np.linspace(x_min,x_max,n_points_x)
>>> y = np.linspace(y_min,y_max,n_points_y)
>>> def F(x,y):
>>> return x**4 * y
# We reshape to use broadcasting
>>> zz = F(x.reshape(-1,1),y.reshape(1,-1))
>>> zz.shape
(50,50)
# We first integrate over x and then over y
>>> simps([simps(zz_x,x) for zz_x in zz],y)
2.50005233
您可以将其与真实结果进行比较
答案 2 :(得分:0)
trapz。示意性地绘制点网格,
整个网格上的积分等于小区域 dS 上的积分之和。梯形规则将小矩形 dS 上的积分近似为面积 dS 乘以 dS 角中函数值的平均值,即网格点:
∫f(x,y)dS =(f1 + f2 + f3 + f4)/ 4
其中f1,f2,f3,f4是矩形 dS 的角上的数组值。
观察到,每个内部网格点为整个整数输入公式四次,这对于四个矩形是常见的。不在角落的那一侧的每个点输入两次,这对于两个矩形是常见的,并且每个角落点仅输入一次。因此,积分是通过以下函数以numpy计算的:
def double_Integral(xmin, xmax, ymin, ymax, nx, ny, A):
dS = ((xmax-xmin)/(nx-1)) * ((ymax-ymin)/(ny-1))
A_Internal = A[1:-1, 1:-1]
# sides: up, down, left, right
(A_u, A_d, A_l, A_r) = (A[0, 1:-1], A[-1, 1:-1], A[1:-1, 0], A[1:-1, -1])
# corners
(A_ul, A_ur, A_dl, A_dr) = (A[0, 0], A[0, -1], A[-1, 0], A[-1, -1])
return dS * (np.sum(A_Internal)\
+ 0.5 * (np.sum(A_u) + np.sum(A_d) + np.sum(A_l) + np.sum(A_r))\
+ 0.25 * (A_ul + A_ur + A_dl + A_dr))
在David GG提供的功能上进行测试:
x_min,x_max,n_points_x = (0,1,50)
y_min,y_max,n_points_y = (0,5,50)
x = np.linspace(x_min,x_max,n_points_x)
y = np.linspace(y_min,y_max,n_points_y)
def F(x,y):
return x**4 * y
zz = F(x.reshape(-1,1),y.reshape(1,-1))
print(double_Integral(x_min, x_max, y_min, y_max, n_points_x, n_points_y, zz))
2.5017353157550444
其他方法(辛普森(Simpson),罗姆伯格(Romberg)等)也可以类似地推导。