代码之家  ›  专栏  ›  技术社区  ›  Amin Kiany

使用python中的“bokeh”库更新绘图时拟合曲线

  •  1
  • Amin Kiany  · 技术社区  · 7 年前

          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
    

    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\u val与Y1时,也会绘制相关的拟合曲线,对于另一种情况也是如此,即x\u 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)
    

    这一次,如果我更新图,我看不到拟合曲线 我的问题。

    谢谢

    1 回复  |  直到 7 年前
        1
  •  0
  •   Amin Kiany    7 年前

    考虑到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)