在 Python 中绘制分段线性插值代码需要帮助
Need help on plotting this piecewise linear interpolation code in Python
我正在尝试使用简单的线性函数拉格朗日插值多项式插值数据。我已经设法获得了所需的方程式,但是,我无法弄清楚如何分段绘制它。我确实知道使用 sympy 并不是最好的前进方式,但我是菜鸟,我想看看我的方程式如何。
如何在 matplotlib 中绘制它而不需要在最后手动输入方程式?
import numpy as np
import matplotlib.pyplot as plt
import sympy as sym
x = sym.Symbol('x')
year = np.arange(1960,2020,10)
pop = [179323,203302,226542,249633,281422,308746]
def lgn(a,b): #this ideally should be taking a value of x where you'd like to interpolate.
result = []
for i in range(1,len(a)):
L0 = (x - a[i])/(a[i-1] - a[i])
L1 = (x - a[i-1])/(a[i] - a[i-1])
temp = (L0 * b[i-1]) + (L1 * b[i])
result.append(temp)
return result
lgn(year,pop) #result gives a list of linear equations between each year value.
[23979*x/10 - 4520561,
2324*x - 4374978,
23091*x/10 - 4345476,
31789*x/10 - 6076378,
13662*x/5 - 5183378]
#plotting for each interval. this is what I am trying to code.
x1 = np.linspace(year[0],year[1],10)
y1 = 23979 * x1/10 - 4520561
x2 = np.linspace(year[1],year[2],10)
y2 = 2324*x2 - 4374978
x3 = np.linspace(year[2],year[3],10)
y3 = 23091*x3/10 - 4345476
x4 = np.linspace(year[3],year[4],10)
y4 = 31789*x4/10 - 6076378
x5 = np.linspace(year[4],year[5],10)
y5 = 13662*x5/5 - 5183378
plt.plot(year,pop,'ro',x1,y1,x2,y2,x3,y3,x4,y4,x5,y5 )
使用 expr.subs(x, 123).evalf()
将 sympy 表达式转换为数值。请注意,这仅适用于替换单个值。要使用数组,sym.lambdify()
可以将表达式转换为理解 numpy 数组的函数,然后可以将其用于绘图。
这是一些示例代码:
import numpy as np
import matplotlib.pyplot as plt
import sympy as sym
def lgn(a, b):
result = []
for i in range(1, len(a)):
L0 = (x - a[i]) / (a[i - 1] - a[i])
L1 = (x - a[i - 1]) / (a[i] - a[i - 1])
temp = (L0 * b[i - 1]) + (L1 * b[i])
result.append(temp)
return result
x = sym.Symbol('x')
year = np.arange(1960, 2020, 10)
pop = [179323, 203302, 226542, 249633, 281422, 308746]
equations = lgn(year, pop)
for i in range(1, len(year)):
xi = np.linspace(year[i - 1], year[i], 10)
yi_np = sym.lambdify(x, equations[i - 1])
yi = yi_np(xi)
plt.plot(xi, yi)
plt.plot(year, pop, 'ro')
plt.show()
这是使用 sympy 的方法 Piecewise
:
import numpy as np
import matplotlib.pyplot as plt
import sympy as sym
def line_2points(a0, b0, a1, b1):
L0 = (x - a1) / (a0 - a1)
L1 = (x - a0) / (a1 - a0)
return L0 * b0 + L1 * b1
x = sym.Symbol('x')
year = np.arange(1960, 2020, 10)
pop = [179323, 203302, 226542, 249633, 281422, 308746]
eq = 0
for i in range(1, len(year)):
eq = sym.Piecewise( (line_2points(year[i-1], pop[i-1], year[i], pop[i]), (x >= year[i-1] ) & (x <= year[i] ) ),
(eq, True) )
# sym.plot(eq, (x, year[0], year[-1])) # this also works, but the visualization is much harder to customize
eq_np = sym.lambdify(x, eq)
xs = np.linspace(year[0], year[-1], 200)
plt.plot(xs, eq_np(xs))
plt.plot(year, pop, 'ro')
plt.show()
我正在尝试使用简单的线性函数拉格朗日插值多项式插值数据。我已经设法获得了所需的方程式,但是,我无法弄清楚如何分段绘制它。我确实知道使用 sympy 并不是最好的前进方式,但我是菜鸟,我想看看我的方程式如何。
如何在 matplotlib 中绘制它而不需要在最后手动输入方程式?
import numpy as np
import matplotlib.pyplot as plt
import sympy as sym
x = sym.Symbol('x')
year = np.arange(1960,2020,10)
pop = [179323,203302,226542,249633,281422,308746]
def lgn(a,b): #this ideally should be taking a value of x where you'd like to interpolate.
result = []
for i in range(1,len(a)):
L0 = (x - a[i])/(a[i-1] - a[i])
L1 = (x - a[i-1])/(a[i] - a[i-1])
temp = (L0 * b[i-1]) + (L1 * b[i])
result.append(temp)
return result
lgn(year,pop) #result gives a list of linear equations between each year value.
[23979*x/10 - 4520561,
2324*x - 4374978,
23091*x/10 - 4345476,
31789*x/10 - 6076378,
13662*x/5 - 5183378]
#plotting for each interval. this is what I am trying to code.
x1 = np.linspace(year[0],year[1],10)
y1 = 23979 * x1/10 - 4520561
x2 = np.linspace(year[1],year[2],10)
y2 = 2324*x2 - 4374978
x3 = np.linspace(year[2],year[3],10)
y3 = 23091*x3/10 - 4345476
x4 = np.linspace(year[3],year[4],10)
y4 = 31789*x4/10 - 6076378
x5 = np.linspace(year[4],year[5],10)
y5 = 13662*x5/5 - 5183378
plt.plot(year,pop,'ro',x1,y1,x2,y2,x3,y3,x4,y4,x5,y5 )
使用 expr.subs(x, 123).evalf()
将 sympy 表达式转换为数值。请注意,这仅适用于替换单个值。要使用数组,sym.lambdify()
可以将表达式转换为理解 numpy 数组的函数,然后可以将其用于绘图。
这是一些示例代码:
import numpy as np
import matplotlib.pyplot as plt
import sympy as sym
def lgn(a, b):
result = []
for i in range(1, len(a)):
L0 = (x - a[i]) / (a[i - 1] - a[i])
L1 = (x - a[i - 1]) / (a[i] - a[i - 1])
temp = (L0 * b[i - 1]) + (L1 * b[i])
result.append(temp)
return result
x = sym.Symbol('x')
year = np.arange(1960, 2020, 10)
pop = [179323, 203302, 226542, 249633, 281422, 308746]
equations = lgn(year, pop)
for i in range(1, len(year)):
xi = np.linspace(year[i - 1], year[i], 10)
yi_np = sym.lambdify(x, equations[i - 1])
yi = yi_np(xi)
plt.plot(xi, yi)
plt.plot(year, pop, 'ro')
plt.show()
这是使用 sympy 的方法 Piecewise
:
import numpy as np
import matplotlib.pyplot as plt
import sympy as sym
def line_2points(a0, b0, a1, b1):
L0 = (x - a1) / (a0 - a1)
L1 = (x - a0) / (a1 - a0)
return L0 * b0 + L1 * b1
x = sym.Symbol('x')
year = np.arange(1960, 2020, 10)
pop = [179323, 203302, 226542, 249633, 281422, 308746]
eq = 0
for i in range(1, len(year)):
eq = sym.Piecewise( (line_2points(year[i-1], pop[i-1], year[i], pop[i]), (x >= year[i-1] ) & (x <= year[i] ) ),
(eq, True) )
# sym.plot(eq, (x, year[0], year[-1])) # this also works, but the visualization is much harder to customize
eq_np = sym.lambdify(x, eq)
xs = np.linspace(year[0], year[-1], 200)
plt.plot(xs, eq_np(xs))
plt.plot(year, pop, 'ro')
plt.show()