尝试在网格上实现功能时发生TypeError

时间:2018-07-13 14:23:17

标签: python function numpy typeerror

简介

我有一对函数,分别称为numeric(x,y,z)和analytic(x,y,z),其中numeric(x,y,z)是analytic(x,y,z)的近似值。我想绘制一些轮廓图以查看这些函数在x-y平面中的外观,因此对于下面的函数,我将z = 0设置为1。然后,我尝试在网格上定义函数;

def numerical_plane(x,y):
    return numerical(x, y, 0)

def analytic_plane(x,y):
    R = np.sqrt(x**2+y**2)
    return -G*M/(np.sqrt(R**2 + (a+np.sqrt(b**2))**2))

x = np.linspace(-20, 20, 50)
y = np.linspace(-20, 20, 50)

X, Y = np.meshgrid(x, y)
Z1 = numerical(X, Y)
Z2 = analytic(X, Y)

函数数字(x,y,z)在此问题的底部定义。

问题

Z2正常工作,但是Z1提高

TypeError: only size-1 arrays can be converted to Python scalars

因为这是一个TypeError,所以我尝试检查numeric(1,2)返回的类型;那是一个花车。另一方面,analytic(1,2)返回numpy.float64。我试图强迫numeric(x,y)返回一个numpy.float64,但这实际上并没有帮助,所以也许我走错了路。有人知道这里出了什么问题吗?

如果您需要有关函数数值(x,y,z)的更多信息,那么我已经在此处编写了它的定义

def rho(x,y,z,M = 5e10,a = 4,b =0.8):

    R = np.sqrt(x**2+y**2)
    rho = ((b**2*M)/(4*np.pi))*(a*R**2+(a+3*np.sqrt(z**2+b**2))*(a+np.sqrt(z**2+b**2))**2)\
          /((R**2+(a+np.sqrt(z**2+b**2))**2)**(2.5)*(z**2+b**2)**(1.5))
    return rho

def numerical(x, y, z, s=0.01):

    integrand = lambda xx, yy, zz: -G*rho(xx,yy,zz,M,a,b)/(np.sqrt((xx-      x)**2+(yy-y)**2+(zz-z)**2+s**2))      
    phi =   nquad(integrand, ranges = [(-np.inf, np.inf), (-np.inf, np.inf), (-np.inf, np.inf)], opts = {'epsrel' : 1e-1})[0]
    return phi

它涉及调用另一个函数rho(x,y,z,...),然后在所有空间上执行积分。

这里也是完整的回溯...


TypeError                                 Traceback (most recent call last)
<ipython-input-62-cb38a0d34db9> in <module>()
     11 X, Y = np.meshgrid(x, y)
     12 Z1 = analytic(X, Y)
---> 13 Z2 = numeric(X, Y)

<ipython-input-62-cb38a0d34db9> in numeric(x, y)
      1 def numeric(x,y):
----> 2     return numerical_phi_MN(x, y, 0)
      3 
      4 def analytic(x,y):
      5     R = np.sqrt(x**2+y**2)

<ipython-input-43-c7e02143837e> in numerical_phi_MN(x, y, z, s)
     14 
     15     integrand = lambda xx, yy, zz: -G*rho_MN(xx,yy,zz,M,a,b)/(np.sqrt((xx-x)**2+(yy-y)**2+(zz-z)**2+s**2))
---> 16     phi =   nquad(integrand, ranges = [(-np.inf, np.inf), (-np.inf, np.inf), (-np.inf, np.inf)], opts = {'epsrel' : 1e-1})[0]
     17 
     18     return phi

/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in nquad(func, ranges, args, opts, full_output)
    712     else:
    713         opts = [opt if callable(opt) else _OptFunc(opt) for opt in opts]
--> 714     return _NQuad(func, ranges, opts, full_output).integrate(*args)
    715 
    716 

/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in integrate(self, *args, **kwargs)
    767             f = partial(self.integrate, depth=depth+1)
    768         quad_r = quad(f, low, high, args=args, full_output=self.full_output,
--> 769                       **opt)
    770         value = quad_r[0]
    771         abserr = quad_r[1]

/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in quad(func, a, b, args, full_output, epsabs, epsrel, limit, points, weight, wvar, wopts, maxp1, limlst)
    321     if (weight is None):
    322         retval = _quad(func, a, b, args, full_output, epsabs, epsrel, limit,
--> 323                        points)
    324     else:
    325         retval = _quad_weight(func, a, b, args, full_output, epsabs, epsrel,

/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in _quad(func, a, b, args, full_output, epsabs, epsrel, limit, points)
    388             return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
    389         else:
--> 390             return _quadpack._qagie(func,bound,infbounds,args,full_output,epsabs,epsrel,limit)
    391     else:
    392         if infbounds != 0:

/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in integrate(self, *args, **kwargs)
    767             f = partial(self.integrate, depth=depth+1)
    768         quad_r = quad(f, low, high, args=args, full_output=self.full_output,
--> 769                       **opt)
    770         value = quad_r[0]
    771         abserr = quad_r[1]

/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in quad(func, a, b, args, full_output, epsabs, epsrel, limit, points, weight, wvar, wopts, maxp1, limlst)
    321     if (weight is None):
    322         retval = _quad(func, a, b, args, full_output, epsabs, epsrel, limit,
--> 323                        points)
    324     else:
    325         retval = _quad_weight(func, a, b, args, full_output, epsabs, epsrel,

/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in _quad(func, a, b, args, full_output, epsabs, epsrel, limit, points)
    388             return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
    389         else:
--> 390             return _quadpack._qagie(func,bound,infbounds,args,full_output,epsabs,epsrel,limit)
    391     else:
    392         if infbounds != 0:

/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in integrate(self, *args, **kwargs)
    767             f = partial(self.integrate, depth=depth+1)
    768         quad_r = quad(f, low, high, args=args, full_output=self.full_output,
--> 769                       **opt)
    770         value = quad_r[0]
    771         abserr = quad_r[1]

/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in quad(func, a, b, args, full_output, epsabs, epsrel, limit, points, weight, wvar, wopts, maxp1, limlst)
    321     if (weight is None):
    322         retval = _quad(func, a, b, args, full_output, epsabs, epsrel, limit,
--> 323                        points)
    324     else:
    325         retval = _quad_weight(func, a, b, args, full_output, epsabs, epsrel,

/opt/python-2.7.14/lib/python2.7/site-packages/scipy/integrate/quadpack.pyc in _quad(func, a, b, args, full_output, epsabs, epsrel, limit, points)
    388             return _quadpack._qagse(func,a,b,args,full_output,epsabs,epsrel,limit)
    389         else:
--> 390             return _quadpack._qagie(func,bound,infbounds,args,full_output,epsabs,epsrel,limit)
    391     else:
    392         if infbounds != 0:

TypeError: only size-1 arrays can be converted to Python scalars

非常感谢

1 个答案:

答案 0 :(得分:1)

问题在于scipy.integrate.nquad只能集成一个(n维)函数。因此,它将始终返回单个值,而不是逐个元素地应用于多维矢量。

您可以通过使用numpy.vectorize使函数向量化来解决此问题。但是,请注意文档中所说的内容:

  

提供矢量化功能主要是为了方便,而不是为了   性能。实现本质上是一个for循环。

使用此代码(以及G = 1M = 1rho_MN = rho),它可以运行(尽管需要很长时间,但会在完成时通知您):

def numerical_plane(x, y):
    return np.vectorize(numerical)(x, y, 0)