Home > Software design >  sympy matplolib piecewise TypeError?
sympy matplolib piecewise TypeError?

Time:03-15

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

  • Related