类型错误:无法根据规则“安全"将数组数据从 dtype('O') 转换为 dtype('float64') [英] TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'

查看:203
本文介绍了类型错误:无法根据规则“安全"将数组数据从 dtype('O') 转换为 dtype('float64')的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要对 g(u)jn(u) 类型的积分进行积分,其中 g(u) 是一个没有零的平滑函数,而贝塞尔函数中的 jn(u) 是具有无穷大零的,但是我得到了以下错误:

I need to make an integral of the type g(u)jn(u) where g(u) is a smooth function without zeros and jn(u) in the Bessel function with infinity zeros, but I got the following error:

TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'

首先,我需要将变量 x 更改为变量 u 并在新变量 u 中进行积分,但是函数 u(x) 不是解析可逆的,因此我需要使用插值来进行数值反演.

First I need to change of variable x to variable u and make an integration in the new variable u but how the function u(x) is not analytically invertible so I need to use interpolation to make this inversion numerically.

import numpy as np
from scipy.interpolate import InterpolatedUnivariateSpline

x = np.linspace(0.1, 100, 1000)
u = lambda x: x*np.exp(x)
dxdu_x = lambda x: 1/((1+x) * np.exp(x))               ## dxdu as function of x: not invertible
dxdu_u = InterpolatedUnivariateSpline(u(x), dxdu_x(x)) ## dxdu as function of u: change of variable

在此之后,积分为:

from mpmath import mp

def f(n):
    integrand = lambda U: dxdu_u(U) * mp.besselj(n,U)
    bjz = lambda nth: mp.besseljzero(n, nth)
    return mp.quadosc(integrand, [0,mp.inf], zeros=bjz)

我使用 mpmath 中的 quadosc 而不是 scipy 中的 quad 因为 quadosc更适合对快速振荡函数(如贝塞尔函数)进行积分.但是,另一方面,这迫使我使用两个不同的包,scipy 通过插值计算 dxdu_umpmath 计算贝塞尔函数mp.besselj(n,U) 和积的积分 dxdu_u(U) * mp.bessel(n,U) 所以我怀疑这两种不同的混合软件包可能会产生一些问题/冲突.所以当我做:

I use quadosc from mpmath and not quad from scipy because quadosc is more appropriate to make integral of rapidly oscillating functions, like Bessel functions. But, by other hand, this force me to use two different packges, scipy to calculate dxdu_u by interpolation, and mpmath to calculate the Bessel functions mp.besselj(n,U) and the integral of the product dxdu_u(U) * mp.bessel(n,U) so I suspect that this mix of two different packages can make some issue/ conflict. So when I make:

print(f(0))

我收到错误:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-38-ac2976a6b736> in <module>
     12     return mp.quadosc(integrand, [0,mp.inf], zeros=bjz)
     13 
---> 14 f(0)

<ipython-input-38-ac2976a6b736> in f(n)
     10     integrand = lambda U: dxdu_u(U) * mp.besselj(n,U)
     11     bjz = lambda nth: mp.besseljzero(n, nth)
---> 12     return mp.quadosc(integrand, [0,mp.inf], zeros=bjz)
     13 
     14 f(0)

TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'

有谁知道我如何解决这个问题?谢谢

Does anyone know how I can solve this problem? Thanks

推荐答案

完整的回溯(你狙击的部分)显示错误在 univariatespline 对象的 __call__ 方法中.所以确实问题在于 mpmath 集成例程以它的 mpf 小数形式输入,而 scipy 无法处理它们.

The full traceback (the part you sniped) shows that the error is in the __call__ method of the univariatespline object. So indeed the problem is that the mpmath integration routine feeds in its mpf decimals, and scipy has no way of dealing with them.

最简单的解决方法是手动将 integrand 的参数的违规部分强制转换为浮点数:

A simplest fix is then to manually cast the offending part of the argument of the integrand to a float:

被积函数 = lambda U: dxdu_u(float(U)) * mp.besselj(n,U)

一般来说,这很容易出现数值错误(mpmath 故意使用其高精度变量!)所以要谨慎行事.在这种特定情况下,它可能没问题,因为插值实际上是以双精度完成的.不过,最好检查一下结果.

In general this is prone to numerical errors (mpmath uses its high-precision variables on purpose!) so proceed with caution. In this specific case it might be OK, because the interpolation is actually done in double precision. Still, best check the results.

一种可能的替代方法是避免使用 mpmath 并使用 scipy.integrate.quadweights 参数,请参阅 docs(向下滚动到 weights="sin" 部分)

A possible alternative might be to avoid mpmath and use the weights argument to scipy.integrate.quad, see the docs (scroll down to weights="sin" part)

另一种选择是一直坚持使用 mpmath 并在纯 python 中自己实现插值(这样,mpf 对象可能很好,因为它们应该支持通常的算术).可能一个简单的线性插值就足够了.如果不是,编写自己的三次样条插值器也没什么大不了的.

Another alternative is to stick with mpmath all the way and implement the interpolation yourselves in pure python (this way, mpf objects are probably fine since they should support usual arithmetics). It's likely a simple linear interpolation is enough. If it's not, it's not too big of a deal to code up your own cubic spline interpolator.

这篇关于类型错误:无法根据规则“安全"将数组数据从 dtype('O') 转换为 dtype('float64')的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆