python-3.x - Plotly Dash-单击时将注释添加到散点图

标签 python-3.x plotly plotly-dash

我在虚线处有一个散点图,其中包含一些单击回调。我想在单击某个点时显示该点的注释。对于单击的任何点,注释应保持可见。有人知道这是否可能吗?我应该如何处理?我的最初搜索没有产生任何具体的例子或线索。

import json
from textwrap import dedent as d
import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import random

userSeq = []


app = dash.Dash(__name__)

styles = {
    'pre': {
        'border': 'thin lightgrey solid',
        'overflowX': 'scroll'
    }
}

app.layout = html.Div([
    dcc.Graph(
        id='basic-interactions',
        figure={
            'data': [
                {
                    'x': [random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100)],
                    'y': [random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100)],
                    'text': ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],
                    #'customdata': ['c.a', 'c.b', 'c.c', 'c.d'],
                    'name': 'Trace 1',
                    'mode': 'markers+text', 
                    'marker': {'size': 12},
                    'textposition': 'bottom'
                }

            ]
        }
    ),

    html.Div(className='row', children=[

        html.Div([
            dcc.Markdown(d("""
                **Click Data**

                Click on points in the graph.
            """)),
            html.Pre(id='click-data', style=styles['pre']),
        ], className='three columns'),

    ])
])



@app.callback(
    Output('click-data', 'children'),
    [Input('basic-interactions', 'clickData')])
def display_click_data(clickData):
    if clickData != None:
        userSeq.append(clickData['points'][0]['x'])
        print(userSeq)
    return json.dumps(clickData, indent=2)


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

最佳答案

也许有点矫over过正,但是您可以执行以下操作:在破折号回调中重新定义散点图注释的样式。

据我所知,唯一的方法是重新定义Figure组件的dcc.Graph

import json
from textwrap import dedent as d
import dash
import plotly.graph_objs as go
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import random

# NOTE: this variable will be shared across users!
userSeq = []

x_coords = [random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100)]
y_coords = [random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100), random.randint(0, 100)]


app = dash.Dash(__name__)

styles = {
    'pre': {
        'border': 'thin lightgrey solid',
        'overflowX': 'scroll'
    }
}


app.layout = html.Div([
    dcc.Graph(
        id='basic-interactions',
        figure={
            'data': [
                {
                    'x': x_coords,
                    'y': y_coords,
                    'text': ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],
                    #'customdata': ['c.a', 'c.b', 'c.c', 'c.d'],
                    'name': 'Trace 1',
                    'mode': 'markers+text',
                    'marker': {'size': 12},
                    'textposition': 'bottom'
                }

            ],
        },
    ),

    html.Div(className='row', children=[

        html.Div([
            dcc.Markdown(d("""
                **Click Data**

                Click on points in the graph.
            """)),
            html.Pre(id='click-data', style=styles['pre']),
        ], className='three columns'),

    ])
])


@app.callback(
    output=Output('click-data', 'children'),
    inputs=[Input('basic-interactions', 'clickData')])
def display_click_data(clickData):
    if clickData is not None:
        point = clickData['points'][0]
        userSeq.append({'x': point['x'], 'y': point['y']})
        print(userSeq)
    return json.dumps(clickData, indent=2)


@app.callback(
    Output('basic-interactions', 'figure'),
    [Input('basic-interactions', 'clickData')])
def update_annotation_style(clickData):
    """Redefine Figure with an updated style for the scatter plot annotations."""
    data = go.Data([
        go.Scatter(
            x=x_coords,
            y=y_coords,
            text=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],
            name='Trace 1',
            mode='markers+text',
            marker={'size': 12},
            textposition='bottom',
        )
    ])
    annotations = []
    for point in userSeq:
        annotation = {
            'x': point['x'],
            'y': point['y'],
            'xref': 'x',
            'yref': 'y',
            'text': '({}; {})'.format(point['x'], point['y']),
            'align': 'center',
            'ay': -15,
            'opacity': 0,
            'bgcolor': 'yellow',
        }
        annotations.append(annotation)

    if clickData is None:
        layout = go.Layout(annotations=annotations)
    else:
        updated_annotations = list(map(lambda ann: {**ann, 'opacity': 1.0}, annotations))
        layout = go.Layout(annotations=updated_annotations)
    figure = go.Figure(data=data, layout=layout)
    return figure


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


但是,我的实现中存在一个错误:注解会为所有单击的点显示,当前点除外(因此,单击两个点后它们就会开始显示)。

我认为此问题是由两个破折号的运行顺序引起的:具有Output('basic-interactions', 'figure')的回调应第二次运行。

请记住,在您的应用程序中userSeq在用户之间共享,因此,如果user A单击散点图中的3个点,user B单击散点图中的2个点,他们都将看到5个注释。

关于python-3.x - Plotly Dash-单击时将注释添加到散点图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48818350/

相关文章:

python - Python中的for循环并从文件中读取输入

python - LabelEncoder 和 zip python 的问题

python - 将 Plotly 与 pycharm 一起使用

python - 一页上的多个 plotly plots 没有子图

python - 无法在python中导入破折号

python - 根据列值对行进行条件样式设置

javascript - 嵌套函数,PHP 中的一级函数

python-3.x - Scikit-learn 对于 MLR 的正确性?

r - 在R中的plotly饼图中使用自定义图标

python - Dash 数据表下载到 Excel