Dash コールバック関数

Dash は開発者がPythonを使用して動的でレスポンシブなユーザーインターフェースを作成することを可能にします。

Dash の核心的な機能の一つはコールバック関数(Callback)であり、ユーザーの入力や操作に応じてユーザーインターフェースをリアルタイムに更新できるようにします。

コールバック関数は、Dash におけるユーザーインタラクションを処理するための中核的なメカニズムであり、ユーザーがアプリケーションと対話する際に、アプリケーションのレイアウトやデータを動的に更新することを可能にします。簡単に言うと、コールバック関数はPython関数であり、特定の入力が変化したときにトリガーされ、その入力の変化に基づいて出力を更新します。

典型的な Dash コールバック関数は、以下のいくつかの部分で構成されています。

  1. 入力(Input):どのコンポーネントの属性変化がコールバック関数をトリガーするかを指定します。
  2. 出力(Output):コールバック関数の実行後、どのコンポーネントの属性が更新されるかを指定します。
  3. 状態(State):オプションのパラメータで、コールバックをトリガーしないがコールバック内で使用する必要があるデータを渡すために使用します。
  4. コールバック関数本体:入力を処理して出力を生成するための実際のロジックコードが含まれます。

コールバック関数の基本構造

@app.callback(
    Output(component_id='output-component', component_property='output-property'),
    Input(component_id='input-component', component_property='input-property')
)
def update_output(input_value):
    # 根据输入值计算输出值
    return output_value
  1. Output:

    • コールバック関数の出力先を指定します。

    • component_id:ターゲットコンポーネントのID。

    • component_property:ターゲットコンポーネントの属性(例:children、valueなど)。

  2. Input:

    • コールバック関数の入力元を指定します。

    • component_id:入力コンポーネントのID。

    • component_property:入力コンポーネントの属性(例:value、n_clicksなど)。

  3. コールバック関数:

    • 入力値を受け取り、計算して出力値を返します。

    • 関数名はカスタマイズ可能です(例:update_output)。

例

次の例は、入力ボックスの値に基づいてテキスト内容を動的に更新する方法を示しています。

例

from dash import Dash, html, dcc, Input, Output

# 创建 Dash 应用
app = Dash(__name__)

# 定义布局
app.layout = html.Div([
    dcc.Input(id='input', type='text', placeholder='请输入内容...'),
    html.Div(id='output')
])

# 定义回调函数
@app.callback(
    Output('output', 'children'),
    Input('input', 'value')
)
def update_output(input_value):
    return f'あなたは入力しました: {input_value}'

# 运行应用
if __name__ == '__main__':
    app.run_server(debug=True)

次の例は、ドロップダウンメニューの選択に基づいてグラフを動的に更新する方法を示しています。

例

from dash import Dash, html, dcc, Input, Output
import plotly.express as px
import pandas as pd

# 创建 Dash 应用
app = Dash(__name__)

# 示例数据
df = pd.DataFrame({
    '城市': ['北京', '上海', '广州', '深圳'],
    '人口': [2171, 2424, 1490, 1303]
})

# 定义布局
app.layout = html.Div([
    dcc.Dropdown(
        id='dropdown',
        options=[{'label': city, 'value': city} for city in df['城市']],
        value='北京'  # 默认值
    ),
    dcc.Graph(id='graph')
])

# 定义回调函数
@app.callback(
    Output('graph', 'figure'),
    Input('dropdown', 'value')
)
def update_graph(selected_city):
    filtered_df = df[df['城市'] == selected_city]
    fig = px.bar(filtered_df, x='城市', y='人口', title=f'{selected_city} 人口数据')
    return fig

# 运行应用
if __name__ == '__main__':
    app.run_server(debug=True)

上記のコードを実行すると、ドロップダウンメニューで都市を選択すると、グラフが動的に更新されてその都市の人口データが表示されます。

次の例では、ユーザーが数値を入力すると、その数値の2乗が表示されます。

例

from dash import Dash, html, dcc, Input, Output

# 创建 Dash 应用
app = Dash(__name__)

# 定义布局
app.layout = html.Div([
    html.H1("计算平方"),  # 标题
    dcc.Input(
        id='number-input',  # 入力ボックスのID
        type='number',  # 入力ボックスのタイプは数値
        placeholder='请输入一个数字...',  # 入力ボックスのプレースホルダーテキスト
        value=''  # 初期値は空
    ),
    html.Div(id='output')  # 結果を表示するための Div
])

# 定义回调函数
@app.callback(
    Output('output', 'children'),  # id が 'output' の Div の children 属性に出力
    Input('number-input', 'value')  # 入力は、id が 'number-input' の入力ボックスの value 属性から取得されます。
)
def calculate_square(number):
    if number is None or number == '':  # 入力が空の場合
        return '请输入一个数字。'
    try:
        number = float(number)  # 入力値を浮動小数点数に変換
        square = number ** 2  # 计算平方
        return f'{number} の平方は: {square}'  # 返回结果
    except ValueError:  # 入力が数値でない場合
        return 有効な数値を入力してください。

# 运行应用
if __name__ == '__main__':
    app.run_server(debug=True)  # 启动应用,debug=True 表示开启调试模式

コードの説明:

1、レイアウト部分:

  • 使用html.H1タイトル「计算平方」を作成します。

  • 使用dcc.Input数値入力ボックスを作成し、idためにnumber-input、タイプはnumber。

  • 使用html.Div結果を表示するための領域を作成し、idためにoutput。

2、コールバック関数:

  • 使用@app.callbackデコレータでコールバック関数を定義します。

  • 入力はnumber-input入力ボックスのvalue属性です。

  • 出力はoutputDiv のchildren属性です。

  • コールバック関数内では:

    • 入力が空かどうかを確認します。

    • 入力を浮動小数点数に変換して2乗を計算します。

    • フォーマットされた結果を返します。

3、アプリケーションの実行:使用してapp.run_server(debug=True)アプリケーションを起動し、debug=Trueデバッグモードを有効にすることを示し、実行結果は以下のように表示されます。


コールバック関数の動作原理

1. 入力と出力のバインド

Dash では、コールバック関数の入力と出力はInputとOutputオブジェクトによって指定されます。Inputオブジェクトは、どのコンポーネントのどの属性の変化がコールバック関数をトリガーするかを指定し、Outputオブジェクトは、コールバック関数の実行後にどのコンポーネントのどの属性が更新されるかを指定します。

2. コールバック関数のトリガー

ユーザーがインターフェース上で操作(テキスト入力、ボタンのクリックなど)を行うと、関連するコンポーネントの属性が変化します。Dash はこれらの変化を検出し、バインドされたコールバック関数を自動的に呼び出します。

3. コールバック関数の実行

コールバック関数の実行時、Dash は入力属性の現在の値をパラメータとしてコールバック関数に渡します。コールバック関数はこれらの入力値に基づいて計算または処理を行い、出力属性の新しい値を返します。Dash は自動的に返された値を指定されたコンポーネントの属性に更新します。


コールバック関数の高度な使い方

1. 複数の入力と出力

1つのコールバック関数は複数の入力と出力を持つことができます。例:

例

@app.callback(
    [Output('output-div-1', 'children'),
     Output('output-div-2', 'children')],
    [Input('input-1', 'value'),
     Input('input-2', 'value')]
)
def update_outputs(input1, input2):
    return f'Input 1: {input1}', f'Input 2: {input2}'

この例では、コールバック関数update_outputsには2つの入力と2つの出力があります。input-1或input-2の値が変化すると、コールバック関数がトリガーされ、2つの出力コンポーネントのchildren属性が更新されます。

2. 状態(State)の使用

場合によっては、コールバックをトリガーしないデータをコールバック関数内で使用する必要があるかもしれません。この場合、使用できるのはStateオブジェクトです。StateオブジェクトはInputオブジェクトに似ていますが、コールバック関数をトリガーしません。

例

@app.callback(
    Output('output-div', 'children'),
    [Input('submit-button', 'n_clicks')],
    [State('input-text', 'value')]
)
def update_output(n_clicks, input_value):
    if n_clicks is None:
        return 'No clicks yet'
    return f'Button clicked {n_clicks} times. Input: {input_value}'

この例では、n_clicksはコールバックをトリガーする入力であり、input_valueはコールバック関数内で使用される状態です。ボタンがクリックされたときのみコールバック関数がトリガーされますが、コールバック関数内では入力ボックスの現在の値を使用できます。

3. コールバック関数の重複実行を防ぐ

状況によっては、コールバック関数が頻繁にトリガーされ、パフォーマンスの問題を引き起こす可能性があります。これを回避するには、dash.no_updateを使用して不要な更新を防ぐことができます。

例

@app.callback(
    Output('output-div', 'children'),
    [Input('input-text', 'value')]
)
def update_output(input_value):
    if not input_value:
        return dash.no_update
    return f'You have entered: {input_value}'

この例では、入力ボックスの値が空の場合、コールバック関数は出力コンポーネントを更新しません。


よくある問題と解決方法

1. コールバック関数がトリガーされない

コールバック関数が期待どおりにトリガーされない場合、次のいずれかの原因が考えられます:

  • 入力または出力IDの不一致:確認InputとOutput内のコンポーネントIDとレイアウト内のIDが一致していることを確認してください。
  • 属性名の誤り:確認InputとOutput内の属性名が正しいことを確認してください。
  • コールバック関数が未登録:コールバック関数がアプリケーションに正しく登録されていることを確認してください。

2. コールバック関数の実行が遅い

コールバック関数の実行が遅い場合は、以下の最適化方法を検討できます:

  • コールバック関数の計算量を減らす:コールバック関数内で複雑な計算を行わないようにしてください。
  • キャッシュを使用する:繰り返しの計算結果には、キャッシュを使用して計算時間を短縮できます。
  • 非同期コールバック:長時間実行されるタスクには、非同期コールバックを使用してメインスレッドのブロックを回避できます。
その他の拡張