使用 python 中的 "bokeh" 库更新绘图时拟合曲线
Fitting a curve while updating a plot using the "bokeh" library in python
我已经编写了一段代码来使用 bokeh 库可视化数据。我定义了一个简单的数据框 df 为:
Y1 Y2 x_val
0 3.01 0.99 0
1 5.10 3.05 1
2 6.99 7.29 2
3 8.02 13.41 3
4 10.81 20.31 4
并使用以下代码,我可以交互式地绘制 x_val 与 Y1 和 Y2 的关系图。
import pandas as pd
from bokeh.io import curdoc
from bokeh.layouts import row, widgetbox
from bokeh.models import ColumnDataSource, Select
from bokeh.plotting import figure
dc = {'x_val':[0,1,2,3,4], 'Y1':[3.01, 5.10, 6.99, 8.02, 10.81],
'Y2':[0.99, 3.05, 7.29, 13.41, 20.31]}
df = pd.DataFrame(dc)
source = ColumnDataSource(data={'x': df['x_val'], 'y': df['Y1'], 'y2':df['Y2']})
plot = figure(x_axis_label = 'x', y_axis_label = 'f(x)')
plot.circle('x', 'y', source=source)
def update_plot(attr, old, new):
y = y_select.value
new_data = {'x': df['x_val'], 'y': df[y]}
source.data = new_data
y_select = Select(options=['Y1', 'Y2'],value='Y1',title='y-axis data')
y_select.on_change('value', update_plot)
# Create layout and add to current document
layout = row(widgetbox(y_select), plot)
# Add layout to current document
curdoc().add_root(layout)
现在,每当我更新绘图时,我都想在数据上拟合一条曲线,即,当我选择绘制 x_val 与 Y1 的关系时,也会绘制相关的拟合曲线,对于其他情况,即 x_val 与 Y2。为此,我将上面的代码扩展为如下一段:
import pandas as pd
import numpy as np
from bokeh.io import curdoc
from bokeh.layouts import row, widgetbox
from bokeh.models import ColumnDataSource, Select
from bokeh.plotting import figure
from scipy.optimize import curve_fit
def fit_func(xdata, ydata):
def func(x,a,c):
return a*(x**2)+a*x+c
y = func(xdata, 1, 1)
popt, pcov = curve_fit(func, xdata, ydata)
new_x = np.arange(0,10,2)
new_y = func(new_x,*popt)
return (new_x, new_y)
dc = {'x_val':[0,1,2,3,4], 'Y1':[3.01, 5.10, 6.99, 8.02, 10.81],
'Y2':[0.99, 3.05, 7.29, 13.41, 20.31]}
df = pd.DataFrame(dc)
dfit = pd.DataFrame({'x': fit_func(df['x_val'].values, df['Y1'].values)[0],
'y': fit_func(df['x_val'].values, df['Y1'].values)[1]})
source = ColumnDataSource(data={'x': df['x_val'], 'y': df['Y1'], 'y2':df['Y2']})
source_f = ColumnDataSource(data={'x': dfit['x'], 'y': dfit['y']})
plot = figure(x_axis_label = 'x', y_axis_label = 'f(x)')
plot.circle('x', 'y', source=source)
plot.line('x', 'y', source=source_f)
def update_plot(attr, old, new):
y = y_select.value
new_data = {'x': df['x_val'], 'y': df[y]}
source.data = new_data
answ = fit_func(df['x_val'].values, df[y].values)
new_fit = pd.DataFrame({'x': fit_func(df['x_val'].values, df['Y1'].values)[0],
'y': fit_func(df['x_val'].values, df['Y1'].values)[1]})
source_f.data = new_fit
y_select = Select(options=['Y1', 'Y2'],value='Y1',title='y-axis data')
y_select.on_change('value', update_plot)
# Create layout and add to current document
layout = row(widgetbox(y_select), plot)
# Add layout to current document
curdoc().add_root(layout)
这次更新图是看不到拟合曲线的
我的问题。
另一个问题是:是否有任何优雅的方法可以仅在我们更新绘图时拟合曲线?
谢谢!
考虑到 Alex 的评论,我把我的问题的解决方案放在这里:
import pandas as pd
import numpy as np
from bokeh.io import curdoc
from bokeh.layouts import row, widgetbox
from bokeh.models import ColumnDataSource, Select
from bokeh.plotting import figure
from scipy.optimize import curve_fit
def fit_func(xdata, ydata):
def func(x,a,c):
return a*(x**2)+a*x+c
y = func(xdata, 1, 1)
popt, pcov = curve_fit(func, xdata, ydata)
new_x = np.arange(0,10,2)
new_y = func(new_x,*popt)
return (new_x, new_y)
dc = {'x_val':[0,1,2,3,4], 'Y1':[3.01, 5.10, 6.99, 8.02, 10.81],
'Y2':[0.99, 3.05, 7.29, 13.41, 20.31]}
df = pd.DataFrame(dc)
source = ColumnDataSource(data={'x': df['x_val'], 'y': df['Y1'], 'y2':df['Y2']})
xf, yf = fit_func(df['x_val'].values, df['Y1'].values)
source_f = ColumnDataSource(data={'x': xf, 'y': yf})
plot = figure(x_axis_label = 'x', y_axis_label = 'f(x)')
plot.circle('x', 'y', source=source)
plot.line('x', 'y', source=source_f)
def update_plot(attr, old, new):
y = y_select.value
new_data = {'x': df['x_val'], 'y': df[y]}
source.data = new_data
answ = fit_func(df['x_val'].values, df[y].values)
new_fit = {'x':answ[0], 'y':answ[1]}
source_f.data = new_fit
y_select = Select(options=['Y1', 'Y2'],value='Y1',title='y-axis data')
y_select.on_change('value', update_plot)
layout = row(widgetbox(y_select), plot)
curdoc().add_root(layout)
我已经编写了一段代码来使用 bokeh 库可视化数据。我定义了一个简单的数据框 df 为:
Y1 Y2 x_val
0 3.01 0.99 0
1 5.10 3.05 1
2 6.99 7.29 2
3 8.02 13.41 3
4 10.81 20.31 4
并使用以下代码,我可以交互式地绘制 x_val 与 Y1 和 Y2 的关系图。
import pandas as pd
from bokeh.io import curdoc
from bokeh.layouts import row, widgetbox
from bokeh.models import ColumnDataSource, Select
from bokeh.plotting import figure
dc = {'x_val':[0,1,2,3,4], 'Y1':[3.01, 5.10, 6.99, 8.02, 10.81],
'Y2':[0.99, 3.05, 7.29, 13.41, 20.31]}
df = pd.DataFrame(dc)
source = ColumnDataSource(data={'x': df['x_val'], 'y': df['Y1'], 'y2':df['Y2']})
plot = figure(x_axis_label = 'x', y_axis_label = 'f(x)')
plot.circle('x', 'y', source=source)
def update_plot(attr, old, new):
y = y_select.value
new_data = {'x': df['x_val'], 'y': df[y]}
source.data = new_data
y_select = Select(options=['Y1', 'Y2'],value='Y1',title='y-axis data')
y_select.on_change('value', update_plot)
# Create layout and add to current document
layout = row(widgetbox(y_select), plot)
# Add layout to current document
curdoc().add_root(layout)
现在,每当我更新绘图时,我都想在数据上拟合一条曲线,即,当我选择绘制 x_val 与 Y1 的关系时,也会绘制相关的拟合曲线,对于其他情况,即 x_val 与 Y2。为此,我将上面的代码扩展为如下一段:
import pandas as pd
import numpy as np
from bokeh.io import curdoc
from bokeh.layouts import row, widgetbox
from bokeh.models import ColumnDataSource, Select
from bokeh.plotting import figure
from scipy.optimize import curve_fit
def fit_func(xdata, ydata):
def func(x,a,c):
return a*(x**2)+a*x+c
y = func(xdata, 1, 1)
popt, pcov = curve_fit(func, xdata, ydata)
new_x = np.arange(0,10,2)
new_y = func(new_x,*popt)
return (new_x, new_y)
dc = {'x_val':[0,1,2,3,4], 'Y1':[3.01, 5.10, 6.99, 8.02, 10.81],
'Y2':[0.99, 3.05, 7.29, 13.41, 20.31]}
df = pd.DataFrame(dc)
dfit = pd.DataFrame({'x': fit_func(df['x_val'].values, df['Y1'].values)[0],
'y': fit_func(df['x_val'].values, df['Y1'].values)[1]})
source = ColumnDataSource(data={'x': df['x_val'], 'y': df['Y1'], 'y2':df['Y2']})
source_f = ColumnDataSource(data={'x': dfit['x'], 'y': dfit['y']})
plot = figure(x_axis_label = 'x', y_axis_label = 'f(x)')
plot.circle('x', 'y', source=source)
plot.line('x', 'y', source=source_f)
def update_plot(attr, old, new):
y = y_select.value
new_data = {'x': df['x_val'], 'y': df[y]}
source.data = new_data
answ = fit_func(df['x_val'].values, df[y].values)
new_fit = pd.DataFrame({'x': fit_func(df['x_val'].values, df['Y1'].values)[0],
'y': fit_func(df['x_val'].values, df['Y1'].values)[1]})
source_f.data = new_fit
y_select = Select(options=['Y1', 'Y2'],value='Y1',title='y-axis data')
y_select.on_change('value', update_plot)
# Create layout and add to current document
layout = row(widgetbox(y_select), plot)
# Add layout to current document
curdoc().add_root(layout)
这次更新图是看不到拟合曲线的 我的问题。 另一个问题是:是否有任何优雅的方法可以仅在我们更新绘图时拟合曲线?
谢谢!
考虑到 Alex 的评论,我把我的问题的解决方案放在这里:
import pandas as pd
import numpy as np
from bokeh.io import curdoc
from bokeh.layouts import row, widgetbox
from bokeh.models import ColumnDataSource, Select
from bokeh.plotting import figure
from scipy.optimize import curve_fit
def fit_func(xdata, ydata):
def func(x,a,c):
return a*(x**2)+a*x+c
y = func(xdata, 1, 1)
popt, pcov = curve_fit(func, xdata, ydata)
new_x = np.arange(0,10,2)
new_y = func(new_x,*popt)
return (new_x, new_y)
dc = {'x_val':[0,1,2,3,4], 'Y1':[3.01, 5.10, 6.99, 8.02, 10.81],
'Y2':[0.99, 3.05, 7.29, 13.41, 20.31]}
df = pd.DataFrame(dc)
source = ColumnDataSource(data={'x': df['x_val'], 'y': df['Y1'], 'y2':df['Y2']})
xf, yf = fit_func(df['x_val'].values, df['Y1'].values)
source_f = ColumnDataSource(data={'x': xf, 'y': yf})
plot = figure(x_axis_label = 'x', y_axis_label = 'f(x)')
plot.circle('x', 'y', source=source)
plot.line('x', 'y', source=source_f)
def update_plot(attr, old, new):
y = y_select.value
new_data = {'x': df['x_val'], 'y': df[y]}
source.data = new_data
answ = fit_func(df['x_val'].values, df[y].values)
new_fit = {'x':answ[0], 'y':answ[1]}
source_f.data = new_fit
y_select = Select(options=['Y1', 'Y2'],value='Y1',title='y-axis data')
y_select.on_change('value', update_plot)
layout = row(widgetbox(y_select), plot)
curdoc().add_root(layout)