问题
Appreciate any help on this task!
I'm trying to have this dash app take slider input value to change a variable through a function and then change the marker colour variable only.
The code is written in python and uses plotly-dash and plotly and as well as pandas numpy and mapbox.
The top part of the code is getting the data into the right format. It has traffic data which is being processed to product a heatmap that shows congestion over time on a map. The dataframe DF is for volume of traffic, and the dataframe HF was created so the slider would work (i added a column numbered 0 to number of columns to use with the slider) - the function datatime should choose the volumes based on the time and the detector ID.
I originally created this functionality with javascript as shown here - https://jsbin.com/detejef/edit?html,js,output
I've been working at this code for awhile. Very close to finally getting a prototype but have this one snag - the variable of time doesn't update properly and reupdate the map with the detector changes...
I just need marker dictionary sub function colour to change with the slider value changing in conjunction with the functions I've created. The function works by itself.
This is an update to the code.
# data wrangling
xls = pd.ExcelFile('FreewayFDSData.xlsx') # this loads the data only once saving memory
df = pd.read_excel(xls, 'Volume', parse_dates=True, index_col="Time")
df = df.T
df2 = pd.read_excel(xls, 'Occupancy', parse_dates=True, index_col="Time")
df2 = df2.T
df3 = pd.read_excel(xls, 'Speed', parse_dates=True, index_col="Time")
df3 = df3.T
Detectors = list(df.columns)
mf = pd.read_excel('FreewayFDSData.xlsx', 'Coordinates', index_col="Short Name")
# return df, df2, df3, Detectors, mf
# input slider value then output into data frame filter for slider time volume value
# timeslider arrangement
def heatmap(SVO):
# creates heatmap data for map
SVO['Period'] = np.arange(len(SVO))
mintime = SVO['Period'].min()
maxtime = SVO['Period'].max()
return mintime, maxtime
mintime, maxtime = heatmap(df)
hf = df.reset_index().set_index('Period')
df2['Period'] = np.arange(len(df2))
hf2 = df2.reset_index().set_index('Period')
df3['Period'] = np.arange(len(df3))
hf3 = df.reset_index().set_index('Period')
# Marker
def datatime(t,hf):
heat = hf.filter(items=[t], axis=0).T.drop("index")
return heat[t]
This is the app section with only the useful parts included.
.....
html.Div([
dcc.RadioItems(
id='tdatam',
options=[{'label': i, 'value': i} for i in ['Volume', 'Speed', 'Occupancy']],
value='Volume',
labelStyle={'display': 'inline-block'}
),
],
style={'width': '48%', 'display': 'inline-block'}),
html.Div([
....
],
style={'width': '50%', 'display': 'inline-block'}),
dcc.Graph(id='graph'),
html.P("", id="popupAnnotation", className="popupAnnotation"),
dcc.Slider(
id="Slider",
marks={i: 'Hour {}'.format(i) for i in range(0, 24)},
min=mintime / 4,
max=maxtime / 4,
step=.01,
value=9,
)
], style={"padding-bottom": '50px', "padding-right": '50px', "padding-left": '50px', "padding-top": '50px'}),
....
App functions/ callbacks
@app.callback(
Output('graph', 'figure'),
[Input('Slider', 'value'),
Input('tdatam', 'value')]
)
def update_map(time, tdata):
#use state
zoom = 10.0
latInitial = -37.8136
lonInitial = 144.9631
bearing = 0
#when time function is updated from slider it is failing
#Trying to create either a new time variable to create a test for time slider or alternatively a new function for updating time
if tdata == "Volume":
return go.Figure(
data=Data([
Scattermapbox(
lat=mf.Y,
lon=mf.X,
mode='markers',
hoverinfo="text",
text=["Monash Freeway", "Western Link",
"Eastern Link",
"Melbourne CBD", "Swan Street"],
# opacity=0.5,
marker=Marker(size=15,
color=datatime(time,hf),
colorscale='Viridis',
opacity=.8,
showscale=True,
cmax=2500,
cmin=700
),
),
]),
layout=Layout(
autosize=True,
height=750,
margin=Margin(l=0, r=0, t=0, b=0),
showlegend=False,
mapbox=dict(
accesstoken=mapbox_access_token,
center=dict(
lat=latInitial, # -37.8136
lon=lonInitial # 144.9631
),
style='dark',
bearing=bearing,
zoom=zoom
),........
)
]
)
)
Example data (anonamized)
Lat/Long/Name
Short Name Y X
A -37.883416 145.090084
B -37.883378 145.090038
C -37.882968 145.089531
D -37.882931 145.089484
Data input
Row Labels 00:00 - 00:15 00:15 - 00:30 00:30 - 00:45 00:45 - 01:00 01:00 - 01:15 01:15 - 01:30 01:30 - 01:45 01:45 - 02:00 02:00 - 02:15 02:15 - 02:30 02:30 - 02:45 02:45 - 03:00 03:00 - 03:15 03:15 - 03:30 03:30 - 03:45 03:45 - 04:00 04:00 - 04:15 04:15 - 04:30 04:30 - 04:45 04:45 - 05:00 05:00 - 05:15 05:15 - 05:30 05:30 - 05:45 05:45 - 06:00 06:00 - 06:15 06:15 - 06:30 06:30 - 06:45 06:45 - 07:00 07:00 - 07:15 07:15 - 07:30 07:30 - 07:45 07:45 - 08:00 08:00 - 08:15 08:15 - 08:30 08:30 - 08:45 08:45 - 09:00 09:00 - 09:15 09:15 - 09:30 09:30 - 09:45 09:45 - 10:00 10:00 - 10:15 10:15 - 10:30 10:30 - 10:45 10:45 - 11:00 11:00 - 11:15 11:15 - 11:30 11:30 - 11:45 11:45 - 12:00 12:00 - 12:15 12:15 - 12:30 12:30 - 12:45 12:45 - 13:00 13:00 - 13:15 13:15 - 13:30 13:30 - 13:45 13:45 - 14:00 14:00 - 14:15 14:15 - 14:30 14:30 - 14:45 14:45 - 15:00 15:00 - 15:15 15:15 - 15:30 15:30 - 15:45 15:45 - 16:00 16:00 - 16:15 16:15 - 16:30 16:30 - 16:45 16:45 - 17:00 17:00 - 17:15 17:15 - 17:30 17:30 - 17:45 17:45 - 18:00 18:00 - 18:15 18:15 - 18:30 18:30 - 18:45 18:45 - 19:00 19:00 - 19:15 19:15 - 19:30 19:30 - 19:45 19:45 - 20:00 20:00 - 20:15 20:15 - 20:30 20:30 - 20:45 20:45 - 21:00 21:00 - 21:15 21:15 - 21:30 21:30 - 21:45 21:45 - 22:00 22:00 - 22:15 22:15 - 22:30 22:30 - 22:45 22:45 - 23:00 23:00 - 23:15 23:15 - 23:30 23:30 - 23:45 23:45 - 24:00
A 88 116 84 68 76 56 56 48 72 48 76 40 76 44 36 76 76 116 124 176 236 352 440 624 1016 1172 1260 1280 1304 1312 1252 1344 1324 1336 1212 1148 1132 1120 1084 996 924 1040 952 900 900 1116 1136 1044 1144 1152 1224 1088 1132 1184 1208 1120 1240 1196 1116 1264 1196 1240 1308 1192 1164 1096 1080 1160 1112 1244 1244 1184 1232 996 1108 876 864 776 644 520 684 724 632 620 680 724 516 504 432 396 264 252 272 256 100 144
B 88 116 76 68 76 56 56 48 68 48 76 48 80 44 32 76 76 108 120 180 240 340 456 624 1088 1268 1352 1384 1412 1376 1356 1372 1400 1436 1296 1240 1200 1256 1120 1028 1008 1072 980 944 932 1148 1192 1040 1188 1220 1292 1140 1116 1268 1292 1172 1272 1236 1216 1280 1248 1280 1388 1244 1224 1076 1096 1148 1108 1256 1356 1308 1236 992 1100 880 872 768 640 520 680 720 636 620 660 716 512 504 428 396 260 244 272 252 100 136
C 84 108 68 68 72 56 56 36 60 48 76 44 72 48 32 68 76 108 124 176 240 340 436 604 1036 1168 1280 1372 1204 1304 1268 1228 1280 1312 1164 1076 1156 1108 924 960 864 944 896 840 840 1068 1052 1036 1128 1164 1136 1084 1052 1136 1072 1056 1136 1160 1088 1224 1180 1228 1264 1204 1044 1008 1076 1128 1112 1252 1188 1180 1156 1000 1096 860 868 736 600 520 680 704 624 616 684 720 500 504 408 392 252 236 264 240 96 144
D 92 108 68 68 72 56 56 40 64 48 76 44 72 48 32 72 76 112 132 184 240 340 436 608 1040 1156 1280 1336 1196 1336 1316 1272 1344 1332 1144 1140 1176 1128 924 948 888 956 892 848 868 1036 1064 1036 1108 1192 1120 1080 1044 1152 1068 1040 1140 1180 1104 1232 1164 1280 1256 1196 1052 1016 1084 1128 1116 1252 1192 1168 1160 1000 1076 868 872 744 620 524 680 716 628 628 680 716 500 500 412 388 256 244 260 244 96 144
The key issue I have determined is that HF is not being pulled into the function after the initial call. I am not sure why - it should work just as the time value on the slider changes. The function itself clearly works though - it is definitely that HF is not being brought into def update_map.
回答1:
The issue here was the slider was inputing values like 9.19 which has no column to filter too.
The way i solved this issue was too implement a floor using numpy array through the datetime function. this meant it only used values that were full number integers.
来源:https://stackoverflow.com/questions/56034833/input-data-from-slider-to-change-marker-colour