sympy matplotlib 分段类型错误?

sympy matplolib piecewise TypeError?

matplotlib 类型错误?请告诉我区别。

我想用plt.plot

好的

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()

引发 TypeError(“无法将表达式转换为浮点数”) 类型错误:无法将表达式转换为浮点数

(参考)

Sympy issues with plotting a piecewise function

sympy piecewise:How can I plot a piecewise function using matplotlib?

(20220315)

import sympy as sym
import matplotlib.pyplot as plt
import numpy as np
x = sym.symbols('x')
p = sym.Piecewise((      0,x<= 2),
                  ( 2*x- 4,x<= 4),
                  (-2*x+12,x<= 6),
                  ( 2*x-12,x<=12),
                  (-2*x+36,x<=18),
                  ( 2*x-36,x<=36)
                 )
xvals = np.linspace(0, 36, 100)
f = sym.lambdify(x, p)
yvals = f(xvals)
plt.plot(xvals, yvals)
# plt.savefig('myPoly.png', dpi=200)
plt.show()
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

您可以在 x 值处评估 p

In [186]: p.subs(x, 12.3)
Out[186]: 11.4000000000000

或值列表:

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]

但您不能简单地将它扔到 matplotlib 并期望它做同样的事情。

Matplotlib 需要点数组而不是符号表达式。 SymPy 的 plot 函数旨在为您处理该转换。如果你想使用 matplotlib 的 plot 函数,那么你需要制作 x 和 y 值的数组而不是给它一个表达式。这样做的有效方法是 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