在破折号中,如何在选择单选按钮时使用回调来更新图形?

In dash, how do I use a callback to update a graph when a radio button is selected?

我是 dash 的新手,在查找有关在回调中使用数据帧的示例时遇到问题。我创建了一个每周单选按钮和一个每月单选按钮。

选择每月单选按钮后,我希望图表从 df_monthly 中提取数据,其中每个条形图都是每月的工资总额。当每周单选按钮被选中时,我希望看到图表每周填充每个条形图,这将是数据框中的每一行,因为我每周获得一次报酬。

我不确定哪里出错了,但我一直收到一条错误消息 TypeError: update_fig() takes 0 positional arguments but 1 was given

图表填充时没有数据,如下图所示。感谢您对此事的任何帮助。

import dash
import dash_core_components as dcc 
import dash_html_components as html 
import plotly.plotly as py
import plotly.graph_objs as go
import sqlite3
import pandas as pd
from functools import reduce
import datetime

conn = sqlite3.connect('paychecks.db')

df_ct = pd.read_sql('SELECT * FROM CheckTotal',conn)
df_earn = pd.read_sql('SELECT * FROM Earnings', conn)
df_whold = pd.read_sql('SELECT * FROM Withholdings', conn)

data_frames = [df_ct, df_earn, df_whold]
df_paystub = reduce(lambda  left,right: pd.merge(left,right,on=['Date'], how='outer'), data_frames)

def date_extraction(df):
    df['Date'] = pd.to_datetime(df['Date'])
    df['Year'] = df['Date'].dt.strftime('%Y')
    df['Month'] = df['Date'].dt.strftime('%B')
    df['Day'] = df['Date'].dt.strftime('%d')
    return df

date_extraction(df_paystub)

df_monthly = df_paystub.groupby(['Month']).sum()

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.css.append_css({'external_url': 'https://codepen.io/amyoshino/pen/jzXypZ.css'})

app.layout = html.Div(children=[

    html.Div([
        html.Div([
            dcc.RadioItems(
                        id='data-view',
                        options=[
                            {'label': 'Weekly', 'value': 'Weekly'},
                            {'label': 'Monthly', 'value': 'Monthly'},
                        ],
                        value='',
                        labelStyle={'display': 'inline-block'}
                    ),
        ], className = 'two columns'),

        html.Div([    
            dcc.Dropdown(
                id='year-dropdown',
                options=[
                        {'label': i, 'value': i} for i in df_paystub['Year'].unique()
                ],
                placeholder="Select a year",
            ),
        ], className='five columns'),

        html.Div([    
            dcc.Dropdown(
                id='month-dropdown',
                options=[
                  {'label': i, 'value': i} for i in df_paystub['Month'].unique()
                ],
                placeholder="Select a month(s)",
                multi=True,
            ),
        ], className='five columns'),
    ], className  = 'row'),


    # HTML ROW CREATED IN DASH
    html.Div([
        # HTML COLUMN CREATED IN DASH
        html.Div([
            # PLOTLY BAR GRAPH        
            dcc.Graph(
                id='pay',
            )
        ], className  = 'six columns'),

        # HTML COLUMN CREATED IN DASH
        html.Div([
            # PLOTLY LINE GRAPH
            dcc.Graph(
                id='hours',
                figure={
                    'data': [
                        go.Scatter(
                            x = df_earn['Date'],
                            y = df_earn['RegHours'],
                            mode = 'lines',
                            name = 'Regular Hours',
                        ),
                        go.Scatter(
                            x = df_earn['Date'],
                            y = df_earn['OtHours'],
                            mode = 'lines',
                            name = 'Overtime Hours',
                        )
                    ]
                }
            )
        ], className='six columns')
    ], className='row')
], className='ten columns offset-by-one')

@app.callback(dash.dependencies.Output('pay', 'figure'),
              [dash.dependencies.Input('data-view', 'value')])

def update_fig():
    figure={
        'data': [
            go.Bar(
                x = df_monthly['Month'],
                y = df_monthly['CheckTotal'],
                name = 'Take Home Pay',
            ),
                go.Bar(
                x = df_monthly['Month'],
                y = df_monthly['EarnTotal'],
                name = 'Earnings',
            )
        ],
        'layout': go.Layout(
            title = 'Take Home Pay vs. Earnings',
            barmode = 'group',
            yaxis = dict(title = 'Pay (U.S. Dollars)'),
            xaxis = dict(title = 'Date Paid')
        )
    }
    return figure

if __name__ == "__main__":
    app.run_server(debug=True)

嗨@prime90,欢迎来到达世币。

看一眼你的回调签名,update_fig() 函数似乎需要接受你给它的 Input(使用 dash.dependencies.Input)。

回调正在发送此 Input 您指定的应用中的更改。所以它沿着你给你的函数 update_fig()#data-viewvalue 发送,它目前不接受任何变量,导致错误消息。

只需更新您的函数签名并添加几个布尔变量即可消除错误并获得潜在功能:


def update_fig(dataview_value):
    # define your weekly OR monthly dataframe 
    # you'll need to supply df_weekly similarly to df_monthly
    # though DO NOT modify these, see note below!
    df = df_weekly if dataview == 'weekly' else df_monthly
    dfkey = 'Week' if 'week' in df.columns else 'Month' # eh, worth a shot!
    figure={
        'data': [
            go.Bar(
                x = df[dfkey],
                y = df['CheckTotal'],
                name = 'Take Home Pay',
            ),
                go.Bar(
                x = df[dfkey],
                y = df['EarnTotal'],
                name = 'Earnings',
            )
        ],
        'layout': go.Layout(
            title = 'Take Home Pay vs. Earnings',
            barmode = 'group',
            yaxis = dict(title = 'Pay (U.S. Dollars)'),
            xaxis = dict(title = 'Date Paid')
        )
    }
    return figure

正如上面评论中所写,您需要进行某种类型的事先操作才能创建 df_weekly,就像您当前的 df_monthly.

此外,我编写的代码片段假设 df 列被命名为 "Week" 和 "Month"——显然需要更新这些。

Dash 中的数据操作:

确保您阅读了 data sharing docs,因为它们强调了如何 数据永远不应被修改超出范围

希望对您有所帮助:-)