#python #plotly #visualization #plotly-dash
Вопрос:
У меня есть приложение dash с двумя ползунками, тремя раскрывающимися списками — имя пробной версии, идентификатор капсулы и ось y, а также диаграмма рассеяния.
- Два ползунка сверху предназначены для визуализации элемента времени, а второй ползунок используется для перемещения, где точки диаграммы рассеяния будут обновляться в соответствии с точками на втором ползунке.
- Два выпадающих списка находятся в цепочке обратного вызова, т. е. Выбор имени пробной версии автоматически создаст соответствующий идентификатор капсулы.
- В соответствии с тем, что перемещается на втором слайдере, первый слайдер (вверху) сможет увеличивать масштаб точек. (см. 3-е изображение)
- Обратный вызов для среднего графика/ползунка не отображается для большинства идентификаторов капсул (первое изображение), но для некоторых капсул ползунок отображается как второе изображение. Я бы хотел, чтобы все капсулы могли это сделать, но, похоже, не могу найти проблему. Любая помощь будет очень признательна! 🙂
import pandas as pd
import plotly.express as px # (version 4.7.0)
import plotly.graph_objects as go
import numpy as np
import openpyxl
import dash # (version 1.12.0) pip install dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
from dash.exceptions import PreventUpdate
app = dash.Dash(__name__)
server = app.server
df = pd.read_excel("Book2.xlsx")
df = df.replace(-1, 0)
print(df)
df['Time_since_ingestion'] = ((df['Wallclock'] - df['Time_Ingested'])/np.timedelta64(1, 'm')).round(2)
trial = df['trial_name'].unique()
trial_names = sorted(list(trial))
trial_names_1 = [{'label': k, 'value': k} for k in sorted(trial)]
trial_names_all = trial_names_1
def slider_fig(df):
return px.scatter(
df.groupby("Wallclock", as_index=False).size(), x="Wallclock", y="size"
).update_layout(
xaxis={"rangeslider": {"visible": True}, "title":None},
height=300,
yaxis={"tickmode": "array", "tickvals": [], "title": None},
margin={"l": 0, "r": 0, "t": 0, "b": 0},
)
app.layout = html.Div([
dcc.Dropdown(id="trial_select",
options=[{'label': s, 'value': s} for s in sorted(df.trial_name.unique())],
optionHeight=25,
clearable=False,
placeholder='Please select trial name...',
value='',
style={'width': "50%"},
),
dcc.Dropdown(id="capsule_select",
options=[],
value=[],
optionHeight=25,
multi=True,
placeholder='Please select...',
style={'width': "50%"}
),
dcc.Dropdown(id='y-axis_select',
options=[
{'label': 'TSI', 'value': 'TSI'},
{'label': 'VOCR_100', 'value': 'VOCR_100'},
], value="VOCR_100",
style={'width': "30%"}),
dcc.Graph(
id="slider",
figure=slider_fig(df),
),
dcc.Graph(id="the_graph",
figure=slider_fig(df)
),
])
# -----------------------------------------------------------
# Populate the options of capsule dropdown based on the trial name dropdown
@app.callback(
Output('capsule_select', 'options'),
Input('trial_select', 'value'))
def set_trial_name_options(trial_name_chosen):
dff = df[df.trial_name == trial_name_chosen]
print(dff)
return [{'label': c, 'value': c} for c in sorted(dff['Capsule_ID'].unique())]
# Populate initial values of capsule ID dropdown
@app.callback(
Output('capsule_select', 'value'),
Input('capsule_select', 'options'))
def set_trial_name_value(capsule_option):
print(capsule_option)
return [x['value'] for x in capsule_option]
@app.callback(
# Output('chart', 'figure'),
Output('the_graph', 'figure'),
Output('slider', 'figure'),
Input('capsule_select', 'value'),
Input('trial_select', 'value'),
Input('y-axis_select', 'value'),
Input('slider', 'relayoutData'),
State('slider', 'figure')
)
def update_graph(selected_capsule, selected_trial, selected_y, slider, sfig):
if selected_capsule == '':
return dash.no_update
else:
dff = df[(df['trial_name'] == selected_trial) amp; (df['Capsule_ID'].isin(selected_capsule))]
if slider and "xaxis.range" in slider.keys():
dff = dff.loc[dff["Wallclock"].between(*slider["xaxis.range"])]
else:
# update slider based on selected capsules
sfig = slider_fig(dff)
fig = px.scatter(
data_frame=dff,
x="TSI",
y=selected_y,
hover_data=["TSI", "GET", "ICJ", "Excretion"],
color="Time_since_ingestion",
opacity = 0.5
)
fig.update_traces(textposition='top center')
return fig, sfig
if __name__ == '__main__':
app.run_server(debug=True, port=3000)