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