【问题标题】:Integrate a function with each element of numpy arrays as limit of integration将函数与 numpy 数组的每个元素集成为集成限制
【发布时间】:2017-09-28 19:27:41
【问题描述】:

我在 python 中有一个函数(也使用 scipy 和 numpy)定义为

import numpy as np
from scipy import integrate
LCDMf = lambda x: 1.0/np.sqrt(0.3*(1+x)**3+0.7)

我想将它从 0 整合到一个 numpy 数组中的每个元素,比如 z = np.arange(0,100)

我知道我可以为每个迭代的元素编写一个循环

an=integrate.quad(LCDMf,0,z[i])

但是,我想知道是否有一种更快、更有效(和更简单)的方法来处理每个 numpy 元素。

【问题讨论】:

  • 我记得很久以前使用 np.vectorize 方法解决了这个问题。我不太记得我是怎么做到的……但当时它似乎是一个通用的解决方案,并且对我有用。任何人都可以在类似的方向解决它吗?
  • np.vectorize 只是将迭代包装在函数调用中。它不会加速您的代码。
  • 我用它来处理 numpy 数组...不是为了加快速度

标签: python arrays numpy scipy integrate


【解决方案1】:

您可以将问题重新表述为 ODE。

然后可以使用odeint 函数计算F(z) 的一系列z

>>> scipy.integrate.odeint(lambda y, t: LCDMf(t), 0, [0, 1, 2, 5, 8])
array([[ 0.        ],    # integrate until z = 0 (must exist, to provide initial value)
       [ 0.77142712],    # integrate until z = 1
       [ 1.20947123],    # integrate until z = 2
       [ 1.81550912],    # integrate until z = 5
       [ 2.0881925 ]])   # integrate until z = 8

【讨论】:

  • 有趣的解决方法。但是对于初始条件必须有一个“0”值是一种限制,对我来说似乎并不普遍。比如说,如果我想与从 0.1 到 0.5 不等的 z 集成,例如
  • @RohinKumar 你总是可以prepend a 0。
【解决方案2】:

在修改np.vectorize 之后,我找到了以下解决方案。简单 - 优雅且有效!

import numpy as np
from scipy import integrate
LCDMf = lambda x: 1.0/math.sqrt(0.3*(1+x)**3+0.7)
np.vectorize(LCDMf)

def LCDMfint(z):
    return integrate.quad(LCDMf, 0, z)

LCDMfint=np.vectorize(LCDMfint)
z=np.arange(0,100)

an=LCDMfint(z)
print an[0]

此方法适用于未排序的浮点数组或我们向其抛出的任何内容,并且不像 odeint 方法中那样具有任何初始条件。

我希望这也对某个地方的人有所帮助...感谢大家的投入。

【讨论】:

    【解决方案3】:

    绝对可以更有效地完成。最后你得到的是一系列的计算:

    1. 将 LCDMf 从 0 积分到 1。
    2. 将 LCDMf 从 0 集成到 2。
    3. 将 LCDMf 从 0 集成到 3。

    所以你可以做的第一件事就是改变它以整合不同的子区间,然后将它们相加(毕竟,还有什么是整合!):

    1. 将 LCDMf 从 0 积分到 1。
    2. 将 LCDMf 从 1 积分到 2,将第 1 步的结果相加。
    3. 将 LCDMf 从 2 积分到 3,将第 2 步的结果相加。

    接下来您可以深入了解 LCDMf,它是这样定义的:

    1.0/np.sqrt(0.3*(1+x)**3+0.7)
    

    您可以使用 NumPy 广播在多个点上立即评估此函数:

    dx = 0.0001
    x = np.arange(0, 100, dx)
    y = LCDMf(x)
    

    这应该很快,并在曲线上为您提供一百万个点。现在您可以使用scipy.integrate.trapz() 或相关功能之一来集成它。使用已经计算的 y 和 dx 调用它,使用上面的工作流程,您可以在其中整合每个间隔,然后使用 cumsum() 获得最终结果。您需要在循环中调用的唯一函数就是积分器本身。

    【讨论】:

    • 可能是我没有完全遵循您的解决方案。 0 到 1、0 到 2 等是示例情况。它不必总是等距或整数。那么,假设 z=[0.1, 0.15, 0.367, 0.265...] 那么会发生什么?
    • 好吧,您说的是z = np.arange(0,100),但如果您还有其他z,那么只需先对其进行排序,我的解决方案应该仍然有效——只需从0 积分到最小的z 值,然后从即z 到下一个最小的z,等等。
    猜你喜欢
    • 1970-01-01
    • 2019-09-23
    • 1970-01-01
    • 2019-12-26
    • 2016-08-22
    • 1970-01-01
    • 2020-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多