使用SciPy在矩形网格上集成2D样本

时间:2013-12-18 21:23:37

标签: numpy scipy

SciPy有三种方法可以对样本(trapz,simps和romb)进行一维积分,一种方法可以在函数上进行二维积分(dblquad),但它似乎没有办法做一个样本上的二维积分 - 甚至是矩形网格上的二维积分。

我看到的最接近的是scipy.interpolate.RectBivariateSpline.integral - 你可以从矩形网格上的数据创建一个RectBivariateSpline然后集成它。但是,这并不快。

我想要比矩形方法更精确的东西(即只是总结一切)。我可以说,使用2D Simpson规则,通过制作一个具有正确权重的数组,将其乘以我想要整合的数组,然后总结结果。

然而,如果已经有更好的东西,我不想重新发明轮子。有吗?

3 个答案:

答案 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)

可以按以下方式在2D中完成

trapz。示意性地绘制点网格,

enter image description here

整个网格上的积分等于小区域 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)等)也可以类似地推导。

相关问题