Python 3.x Plotly Dash-单击点时将注释添加到散点图
我在dash中有一个散点图,有一些点击回调。我希望在单击某个点时显示该点的注释。对于已单击的任何点,注释都应保持可见。是否有人知道这是可能的;我应该如何处理这个问题?我最初的搜索没有找到任何具体的例子或线索Python 3.x Plotly Dash-单击点时将注释添加到散点图,python-3.x,plotly,plotly-dash,Python 3.x,Plotly,Plotly Dash,我在dash中有一个散点图,有一些点击回调。我希望在单击某个点时显示该点的注释。对于已单击的任何点,注释都应保持可见。是否有人知道这是可能的;我应该如何处理这个问题?我最初的搜索没有找到任何具体的例子或线索 import json from textwrap import dedent as d import dash from dash.dependencies import Input, Output import dash_core_components as dcc import das
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)
也许这有点过头了,但下面是您可以做的:在短划线回调中重新定义散点图注释的样式 据我所知,唯一的方法是重新定义
dcc.Graph
组件的Figure
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)
不过,我的实现中存在一个bug:除了当前点之外,所有单击的点都会显示注释(因此当您单击两个点时,注释开始显示)
我认为这个问题是由两个破折号回调的运行顺序引起的:带有输出('basic-interactions','figure')
的回调应该第二个运行
请记住,在您的应用程序中,userSeq
是跨用户共享的,因此如果user A
单击散点图中的3个点,user B
单击散点图中的2个点,他们都将看到5个注释