Найти - Пользователи
Полная версия: Ошибка TypeError
Начало » Python для новичков » Ошибка TypeError
1
vbmisha
Здравствуйте.
Являюсь новичком в Python'е… Пытаюсь построить график, но вылезает ошибка, не пойму, как ее устранить… Надеюсь на Вашу помощь.
 import pylab
from mpl_toolkits.mplot3d import Axes3D
import scipy.integrate as integrate
import numpy as np
from numpy import exp, sqrt, cos
a = 1.4
H = 10
def makeData():
    x = np.arange(0, 200, 2)
    y = np.arange(0, 100, 2)
    xgrid, ygrid = np.meshgrid(x, y)
    zgrid = integrate.quad(lambda k:2*(sqrt(k**2+a**2)*exp(-H*(k**2+a**2))*cos(xgrid*a*sqrt(k**2+a**2))*cos(ygrid*k*sqrt(k**2+a**2))),0, np.inf)
    return xgrid, ygrid, zgrid
x, y, z = makeData()
fig = pylab.figure()
axes = Axes3D(fig)
axes.plot_surface(x, y, z)
pylab.show()

Ошибка:
 TypeError: only size-1 arrays can be converted to Python scalars

Помогите построить график.
uf4JaiD5
Так?

 #!/usr/bin/python3
import pylab
from mpl_toolkits.mplot3d import Axes3D
import scipy.integrate as integrate
import numpy as np
from numpy import exp, sqrt, cos
a = 1.4
H = 10
def f(x,y):
    return integrate.quad(lambda k:2*(sqrt(k**2+a**2)*exp(-H*(k**2+a**2))*cos(x*a*sqrt(k**2+a**2))*cos(y*k*sqrt(k**2+a**2))),0, np.inf)
def makeData():
    x = np.arange(0, 200, 2)
    y = np.arange(0, 100, 2)
    xgrid, ygrid = np.meshgrid(x, y)
    zgrid = np.array([f(x,y)[0] for x,y in zip(np.ravel(xgrid), np.ravel(ygrid))]).reshape(xgrid.shape)
    return xgrid, ygrid, zgrid
x, y, z = makeData()
fig = pylab.figure()
axes = Axes3D(fig)
axes.plot_surface(x, y, z)
pylab.show()
vbmisha
Да. Супер. Спасибо.
Правда, сначала ошибку выдал:
 <Figure size 640x480 with 1 Axes>
Но я не растерялся и добавил строчку:
 %matplotlib inline
Хотя график отличается от Mathematica… но это уже другой вопрос.
Еще раз больше спасибо.
Кстати, если не сложно, могли бы расшифровать одну строчку, она мне до конца не понятна:
 zgrid = np.array([f(x,y)[0] for x,y in zip(np.ravel(xgrid), np.ravel(ygrid))]).reshape(xgrid.shape)
uf4JaiD5
%matplotlib inline
jupyter?

Немного изменил код:
 #!/usr/bin/python3
import pylab
from mpl_toolkits.mplot3d import Axes3D
import scipy.integrate as integrate
import numpy as np
from numpy import exp, sqrt, cos
a = 1.4
H = 10
def f(x,y):
    return integrate.quad(lambda k:2*(sqrt(k**2+a**2)*exp(-H*(k**2+a**2))*cos(x*a*sqrt(k**2+a**2))*cos(y*k*sqrt(k**2+a**2))),0, np.inf)[0]
def makeData():
    x = np.arange(0, 200, 2)
    y = np.arange(0, 100, 2)
    xgrid, ygrid = np.meshgrid(x, y)
    zgrid = np.array([f(x,y) for x,y in zip(np.ravel(xgrid), np.ravel(ygrid))]).reshape(xgrid.shape)
    return xgrid, ygrid, zgrid
x, y, z = makeData()
fig = pylab.figure()
axes = Axes3D(fig)
axes.plot_surface(x, y, z)
pylab.show()

могли бы расшифровать

[0] в конце return integrate.quad(...
потому что integrate.quad возвращет не одно значение, а кортеж из двух. значение интеграла там идёт первым (под индексом 0).
 >>> integrate.quad(lambda x:x,0,4)
(8.0, 8.881784197001252e-14)
раньше это стояло после f(x,y), но лучше тут

 x = np.arange(0, 200, 2)
создаёт массив чисел из интервала [0;200) с шагом 2.
https://docs.scipy.org/doc/numpy/reference/generated/numpy.arange.html?highlight=arange#numpy.arange

для наглядности пусть будет
 >>> x = np.arange(0, 10, 4)
>>> print(x)
[0 4 8]
>>> y = np.arange(1, 10, 5)
>>> print(y)
[1 6]


 xgrid, ygrid = np.meshgrid(x, y)
создаёт двумерные массивы xgrid и ygrid. такие, что перебирая попарно их элементы мы получим все координаты сетки.
https://docs.scipy.org/doc/numpy/reference/generated/numpy.meshgrid.html?highlight=meshgrid#numpy.meshgrid

 >>> print(xgrid)
[[0 4 8]
 [0 4 8]]
>>> print(ygrid)
[[1 1 1]
 [6 6 6]]

 zgrid = np.array([f(x,y) for x,y in zip(np.ravel(xgrid), np.ravel(ygrid))]).reshape(xgrid.shape)

 [f(x,y) for x,y in zip(np.ravel(xgrid), np.ravel(ygrid))]
по частям:

np.ravel превращает двумерный массив в одномерный
https://docs.scipy.org/doc/numpy/reference/generated/numpy.ravel.html?highlight=ravel#numpy.ravel

 for x,y in zip(array1, array2)
будет брать по одному элементу из array1 и array2 и присваивать эти значения переменным x и y.
т.е. этот цикл перебирает всю сетку
https://docs.python.org/3/library/functions.html#zip

итого
 [f(x,y) for x,y in ..]
создаст список, состоящий из f(x,y) для всех x,y из цикла
т.е. тут мы посчитаем значения интеграла для всех точек сетки

но т.к. для построения графика через plot_surface нам нужен не список (list), а 2-d array типа xgrid, то дальше мы преобразуем список
https://matplotlib.org/tutorials/toolkits/mplot3d.html?highlight=plot_surface#mpl_toolkits.mplot3d.Axes3D.plot_surface

 np.array(список).reshape(xgrid.shape)
превращает список в numpy.array, затем делает его двумерным как xgrid (reshape).
https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.reshape.html?highlight=reshape#numpy.ndarray.reshape
vbmisha
uf4JaiD5
jupyter?
Да. Anaconda.
Спасибо за подробную инструкцию. Теперь в принципе все понятно.
Единственное уточнение…
 ... .reshape(xgrid.shape)
сюда мы можем подставить ygrid вместо xgrid, так как нам важно только какой это массив, и в нашем случаии .shape возвращает тип массива, правильно?
Можно даже так написать, для примера:
 np.array(список).reshape((2,2))
uf4JaiD5
vbmisha
Спасибо за подробную инструкцию.
Пожалуйста.

vbmisha
сюда мы можем подставить ygrid вместо xgrid, так как нам важно только какой это массив, и в нашем случаии .shape возвращает тип массива, правильно?
Да. Возвращает размерность массива.
https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.shape.html#numpy.ndarray.shape

vbmisha
Можно даже так написать, для примера:
Да. Только там не (2,2).
vbmisha
Здравствуйте.
Нужна помощь…
 import scipy.integrate as integrate
import numpy as np
from numpy import exp, sqrt, cos
from mpmath import*
a = 1.4
H = 10
def opts0():
    return {'limit':1000}
def f(x,y):
    return integrate.nquad(lambda m,k:0.5*(k*exp(-H*k)*cos(a*(m+x)*sqrt(k))*besselj(0,k*sqrt(m**2+y**2))),[[0, np.inf],[-x,np.inf]],opts=[opts0, opts0, {}, {}],full_output=True)[0]
 f(1,1)
Опытным путем было выяснено, если x является положительным числом выдается ошибка. При других значениях x, т.е. отрицательные числа или 0, то все отрабатывает нормально.
Ошибка:
 TypeError: must be real number, not mpc
Пытался выяснить в интернете по этой ошибке, ничего. Такое ощущение, что такой ошибки никогда ни у кого не было. Особенно смущает mpc, что это такое…

Предыстория. Почему выбрал integrate.nquad, потому что с начало использовал integrate.dblquad, но при его использовании выдаются ошибки:
 C:\Users\all\Anaconda3\lib\site-packages\scipy\integrate\quadpack.py:385: IntegrationWarning: The integral is probably divergent, or slowly convergent.
  warnings.warn(msg, IntegrationWarning)
C:\Users\all\Anaconda3\lib\site-packages\scipy\integrate\quadpack.py:385: IntegrationWarning: The algorithm does not converge.  Roundoff error is detected
  in the extrapolation table.  It is assumed that the requested tolerance
  cannot be achieved, and that the returned result (if full_output = 1) is 
  the best which can be obtained.
  warnings.warn(msg, IntegrationWarning)
C:\Users\all\Anaconda3\lib\site-packages\scipy\integrate\quadpack.py:385: IntegrationWarning: The maximum number of subdivisions (50) has been achieved.
  If increasing the limit yields no improvement it is advised to analyze 
  the integrand in order to determine the difficulties.  If the position of a 
  local difficulty can be determined (singularity, discontinuity) one will 
  probably gain from splitting up the interval and calling the integrator 
  on the subranges.  Perhaps a special-purpose integrator should be used.
  warnings.warn(msg, IntegrationWarning)
Избавиться от них не представляется возможным, народ пишет, что альтернатива integrate.nquad, в результате начал его использовать, а здесь такой косяк…
Может у кого есть мысли, как еще можно вычислить двойной интеграл.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB