matplotlib TypeError? Please tell me the difference.
i want to use plt.plot
OK
from sympy import *
from sympy.plotting import plot
var('x')
def main():
p=Piecewise((0, x < 2), (2 * x - 4, x <= 4), (12 - 2 * x, x <= 6), (2 * x - 12, x <= 12), (36 - 2 * x, x <= 18),
(2 * x - 36, x <= 36))
plot(p)
if __name__ == '__main__':
main()
Error.why?
from sympy import *
import matplotlib.pyplot as plt
var('x')
def main():
p=Piecewise((0, x < 2), (2 * x - 4, x <= 4), (12 - 2 * x, x <= 6), (2 * x - 12, x <= 12), (36 - 2 * x, x <= 18),
(2 * x - 36, x <= 36))
plt.plot(p)
# plt.show()
if __name__ == '__main__':
main()
raise TypeError("can't convert expression to float") TypeError: can't convert expression to float
(ref)
Sympy issues with plotting a piecewise function
sympy piecewise:How can I plot a piecewise function using matplotlib?
CodePudding user response:
In [182]: x
Out[182]: x
In [183]: p = Piecewise(
...: (0, x < 2),
...: (2 * x - 4, x <= 4),
...: (12 - 2 * x, x <= 6),
...: (2 * x - 12, x <= 12),
...: (36 - 2 * x, x <= 18),
...: (2 * x - 36, x <= 36),
...: )
In [184]: type(p)
Out[184]: Piecewise
In [185]: float(p)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Input In [185], in <module>
----> 1 float(p)
File /usr/local/lib/python3.8/dist-packages/sympy/core/expr.py:359, in Expr.__float__(self)
357 if result.is_number and result.as_real_imag()[1]:
358 raise TypeError("can't convert complex to float")
--> 359 raise TypeError("can't convert expression to float")
TypeError: can't convert expression to float
You can evaluate p
at an x
value:
In [186]: p.subs(x, 12.3)
Out[186]: 11.4000000000000
or list of values:
In [189]: alist = [p.subs(x,i) for i in np.arange(0,10)]
In [190]: alist
Out[190]: [0, 0, 0, 2, 4, 2, 0, 2, 4, 6]
but you can't simply throw it at matplotlib
and expect it to do the same.
CodePudding user response:
Matplotlib expects arrays of points rather than symbolic expressions. SymPy's plot
function is designed to handle that conversion for you. If you want to use matplotlib's plot function then you need to make arrays of x and y values rather than hand it an expression. The efficient way to do that is with lambdify
:
In [1]: import sympy as sym
In [2]: import matplotlib.pyplot as plt
In [3]: import numpy as np
In [4]: x = sym.symbols('x')
In [6]: p = sym.Piecewise((0, x < 2), (2 * x - 4, x <= 4), (12 - 2 * x, x <= 6), (2 * x - 12, x <= 12), (36 - 2 * x, x <= 18), (2 * x - 36, x <= 36))
In [8]: sym.pprint(p)
⎧ 0 for x < 2
⎪
⎪2⋅x - 4 for x ≤ 4
⎪
⎪12 - 2⋅x for x ≤ 6
⎨
⎪2⋅x - 12 for x ≤ 12
⎪
⎪36 - 2⋅x for x ≤ 18
⎪
⎩2⋅x - 36 for x ≤ 36
In [9]: xvals = np.linspace(0, 36, 100)
In [11]: f = sym.lambdify(x, p)
In [12]: yvals = f(xvals)
In [13]: plt.plot(xvals, yvals)
Out[13]: [<matplotlib.lines.Line2D at 0x7f64940c13a0>]
In [14]: plt.show()
https://docs.sympy.org/latest/modules/utilities/lambdify.html#sympy.utilities.lambdify.lambdify