Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -15,14 +15,14 @@ pn.extension('vega')
|
|
15 |
events={}
|
16 |
nations = ['Italy','England','Germany','France','Spain','European_Championship','World_Cup']
|
17 |
for nation in nations:
|
18 |
-
with open('
|
19 |
events[nation] = json.load(json_data)
|
20 |
|
21 |
# loading the match data
|
22 |
matches={}
|
23 |
nations = ['Italy','England','Germany','France','Spain','European_Championship','World_Cup']
|
24 |
for nation in nations:
|
25 |
-
with open('
|
26 |
matches[nation] = json.load(json_data)
|
27 |
|
28 |
# loading the players data
|
@@ -34,8 +34,7 @@ with open('players.json') as json_data:
|
|
34 |
competitions={}
|
35 |
with open('competitions.json') as json_data:
|
36 |
competitions = json.load(json_data)
|
37 |
-
|
38 |
-
ev_all_nations = []
|
39 |
for nation in nations:
|
40 |
for i in range(len(events[nation])):
|
41 |
ev_all_nations.append(events[nation][i]['eventName'])
|
@@ -85,70 +84,302 @@ chart1 = alt.layer(bars, average_rule, average_text).properties(
|
|
85 |
# Display the combined chart
|
86 |
chart1
|
87 |
|
88 |
-
|
|
|
89 |
for nation in nations:
|
90 |
for ev in events[nation]:
|
91 |
-
if ev['matchId']
|
92 |
-
|
93 |
-
|
94 |
-
|
|
|
|
|
|
|
|
|
|
|
95 |
|
96 |
-
|
97 |
-
'
|
|
|
|
|
|
|
98 |
})
|
99 |
|
100 |
-
|
101 |
-
|
102 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
103 |
|
104 |
|
105 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
106 |
|
107 |
-
click = alt.selection_single(encodings=['x'], nearest=True)
|
108 |
|
109 |
-
|
110 |
-
|
111 |
-
|
112 |
-
|
113 |
-
|
114 |
-
|
115 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
116 |
).add_selection(
|
117 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
118 |
)
|
119 |
|
120 |
-
|
121 |
-
|
122 |
-
|
123 |
-
x
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
124 |
)
|
125 |
|
126 |
-
|
127 |
-
|
|
|
|
|
128 |
)
|
129 |
|
130 |
-
chart2
|
131 |
|
132 |
-
|
133 |
-
|
134 |
-
|
135 |
spacing=10
|
136 |
).resolve_scale(
|
137 |
color='independent'
|
138 |
)
|
139 |
-
|
140 |
|
141 |
|
142 |
chart1_panel = pn.pane.Vega(chart1, sizing_mode='stretch_width')
|
143 |
-
|
144 |
-
combined_chart1_panel = pn.pane.Vega(combined_chart1, sizing_mode='stretch_width')
|
145 |
|
146 |
|
147 |
dashboard = pn.Column(
|
148 |
"# My Interactive Dashboard", # 可以添加标题
|
149 |
chart1_panel,
|
150 |
-
|
151 |
-
combined_chart1_panel
|
152 |
)
|
153 |
|
154 |
# 设置应用程序为可服务的
|
|
|
15 |
events={}
|
16 |
nations = ['Italy','England','Germany','France','Spain','European_Championship','World_Cup']
|
17 |
for nation in nations:
|
18 |
+
with open('./events_%s.json' %nation) as json_data:
|
19 |
events[nation] = json.load(json_data)
|
20 |
|
21 |
# loading the match data
|
22 |
matches={}
|
23 |
nations = ['Italy','England','Germany','France','Spain','European_Championship','World_Cup']
|
24 |
for nation in nations:
|
25 |
+
with open('./matches_%s.json' %nation) as json_data:
|
26 |
matches[nation] = json.load(json_data)
|
27 |
|
28 |
# loading the players data
|
|
|
34 |
competitions={}
|
35 |
with open('competitions.json') as json_data:
|
36 |
competitions = json.load(json_data)
|
37 |
+
ev_all_nations = []
|
|
|
38 |
for nation in nations:
|
39 |
for i in range(len(events[nation])):
|
40 |
ev_all_nations.append(events[nation][i]['eventName'])
|
|
|
84 |
# Display the combined chart
|
85 |
chart1
|
86 |
|
87 |
+
match_id = 2576335
|
88 |
+
a_match = []
|
89 |
for nation in nations:
|
90 |
for ev in events[nation]:
|
91 |
+
if ev['matchId'] == match_id:
|
92 |
+
a_match.append(ev)
|
93 |
+
|
94 |
+
for nation in nations:
|
95 |
+
for match in matches[nation]:
|
96 |
+
if match['wyId'] == match_id:
|
97 |
+
match_f = match
|
98 |
+
|
99 |
+
df_a_match = pd.DataFrame(a_match)
|
100 |
|
101 |
+
background_data = pd.DataFrame({
|
102 |
+
'x': [0],
|
103 |
+
'y': [0],
|
104 |
+
'x2': [100],
|
105 |
+
'y2': [100]
|
106 |
})
|
107 |
|
108 |
+
# Create the background
|
109 |
+
background = alt.Chart(background_data).mark_rect(
|
110 |
+
color='#195905'
|
111 |
+
).encode(
|
112 |
+
x='x:Q',
|
113 |
+
y='y:Q',
|
114 |
+
x2='x2:Q',
|
115 |
+
y2='y2:Q'
|
116 |
+
)
|
117 |
|
118 |
|
119 |
+
#Define the center circle
|
120 |
+
center_circle = alt.Chart(pd.DataFrame({'x': [50], 'y': [50]})).mark_point(
|
121 |
+
size=12000,
|
122 |
+
color='white',
|
123 |
+
strokeWidth=3
|
124 |
+
).encode(
|
125 |
+
x='x:Q',
|
126 |
+
y='y:Q'
|
127 |
+
)
|
128 |
|
|
|
129 |
|
130 |
+
# Create the border lines
|
131 |
+
border_lines_data = pd.DataFrame({
|
132 |
+
'x': [1, 1, 99.5, 99.5, 1],
|
133 |
+
'y': [1, 99.5, 99.5, 1, 1],
|
134 |
+
'x2': [1, 99.5, 99.5, 1, 1],
|
135 |
+
'y2': [99.5, 99.5, 1, 1, 1]
|
136 |
+
})
|
137 |
+
|
138 |
+
|
139 |
+
border_lines = alt.Chart(border_lines_data).mark_line(
|
140 |
+
color='white',
|
141 |
+
strokeWidth=3
|
142 |
+
).encode(
|
143 |
+
x=alt.X('x:Q', scale=alt.Scale(domain=[1, 99.5])),
|
144 |
+
y=alt.Y('y:Q', scale=alt.Scale(domain=[1, 99.5])),
|
145 |
+
x2='x2:Q',
|
146 |
+
y2='y2:Q'
|
147 |
+
)
|
148 |
+
|
149 |
+
midline_data = pd.DataFrame({
|
150 |
+
'x': [50, 50,],
|
151 |
+
'y': [1, 99, ]
|
152 |
+
})
|
153 |
+
|
154 |
+
# Create the line using `mark_line`
|
155 |
+
midline = alt.Chart(midline_data).mark_line(
|
156 |
+
color='white',
|
157 |
+
strokeWidth=3
|
158 |
+
).encode(
|
159 |
+
x='x:Q',
|
160 |
+
y='y:Q'
|
161 |
+
)
|
162 |
+
lines_data = pd.DataFrame({
|
163 |
+
'x': [1, 17.5, 17.5, 1, 82.5, 82.5, 99,1,6.5,6.5,1, 99,93.5,93.5],
|
164 |
+
'y': [21.3, 21.3, 77.7, 77.7, 21.3, 77.7, 77.7,37.5,37.5,62.5,62.5,37.5,37.5,62.5],
|
165 |
+
'x2': [17.5, 17.5, 1, 17.5, 99, 82.5, 82.5, 6.5,6.5,1,6.5,93.5,93.5,99],
|
166 |
+
'y2': [21.3, 77.7, 77.7, 77.7, 21.3, 21.3,77.7,37.5,62.5,62.5,62.5,37.5,62.5,62.5]
|
167 |
+
})
|
168 |
+
|
169 |
+
lines = alt.Chart(lines_data).mark_line(
|
170 |
+
color='white',
|
171 |
+
strokeWidth=3
|
172 |
+
).encode(
|
173 |
+
x='x:Q',
|
174 |
+
y='y:Q',
|
175 |
+
x2='x2:Q',
|
176 |
+
y2='y2:Q'
|
177 |
+
)
|
178 |
+
|
179 |
+
dot_positions = pd.DataFrame({
|
180 |
+
'x': [12, 87],
|
181 |
+
'y': [50, 50]
|
182 |
+
})
|
183 |
+
|
184 |
+
# Create the white dots
|
185 |
+
white_dots = alt.Chart(dot_positions).mark_point(
|
186 |
+
size=100,
|
187 |
+
color='white',
|
188 |
+
filled=True
|
189 |
+
).encode(
|
190 |
+
x='x:Q',
|
191 |
+
y='y:Q'
|
192 |
+
)
|
193 |
+
|
194 |
+
|
195 |
+
|
196 |
+
theta = np.linspace(0, np.pi, 100)
|
197 |
+
semicircle_x = 12 + 9.5 * np.cos(theta)
|
198 |
+
semicircle_y = 50 + 9.5 * np.sin(theta)
|
199 |
+
|
200 |
+
semicircle_data = pd.DataFrame({
|
201 |
+
'x': semicircle_x,
|
202 |
+
'y': semicircle_y
|
203 |
+
})
|
204 |
+
|
205 |
+
semicircle_data = semicircle_data[semicircle_data['x'] >= 17.5]
|
206 |
+
|
207 |
+
arc1 = alt.Chart(semicircle_data).mark_line(
|
208 |
+
color='white',
|
209 |
+
strokeWidth=3
|
210 |
+
).encode(
|
211 |
+
x=alt.X('x', scale=alt.Scale(domain=[0, 100])),
|
212 |
+
y=alt.Y('y', scale=alt.Scale(domain=[0, 100]))
|
213 |
+
)
|
214 |
+
|
215 |
+
|
216 |
+
|
217 |
+
theta = np.linspace(0, np.pi, 100)
|
218 |
+
semicircle_x2 = 12 + 9.5 * np.cos(theta)
|
219 |
+
semicircle_y2 = 50 - 9.5 * np.sin(theta)
|
220 |
+
|
221 |
+
semicircle_data2 = pd.DataFrame({
|
222 |
+
'x': semicircle_x2,
|
223 |
+
'y': semicircle_y2
|
224 |
+
})
|
225 |
+
|
226 |
+
|
227 |
+
semicircle_data2 = semicircle_data2[semicircle_data2['x'] >= 17.5]
|
228 |
+
|
229 |
+
|
230 |
+
arc2 = alt.Chart(semicircle_data2).mark_line(
|
231 |
+
color='white',
|
232 |
+
strokeWidth=3
|
233 |
+
).encode(
|
234 |
+
x=alt.X('x', scale=alt.Scale(domain=[0, 100])),
|
235 |
+
y=alt.Y('y', scale=alt.Scale(domain=[0, 100]))
|
236 |
+
)
|
237 |
+
|
238 |
+
|
239 |
+
theta = np.linspace(0, np.pi, 100)
|
240 |
+
semicircle_x3 = 87 - 9.5 * np.cos(theta)
|
241 |
+
semicircle_y3 = 50 + 9.5 * np.sin(theta)
|
242 |
+
|
243 |
+
|
244 |
+
semicircle_data3 = pd.DataFrame({
|
245 |
+
'x': semicircle_x3,
|
246 |
+
'y': semicircle_y3
|
247 |
+
})
|
248 |
+
|
249 |
+
|
250 |
+
semicircle_data3 = semicircle_data3[semicircle_data3['x'] <= 82.5]
|
251 |
+
|
252 |
+
|
253 |
+
arc3 = alt.Chart(semicircle_data3).mark_line(
|
254 |
+
color='white',
|
255 |
+
strokeWidth=3
|
256 |
+
).encode(
|
257 |
+
x=alt.X('x', scale=alt.Scale(domain=[0, 100])),
|
258 |
+
y=alt.Y('y', scale=alt.Scale(domain=[0, 100]))
|
259 |
+
)
|
260 |
+
|
261 |
+
|
262 |
+
|
263 |
+
theta = np.linspace(0, np.pi, 100)
|
264 |
+
semicircle_x4 = 87 - 9.5 * np.cos(theta)
|
265 |
+
semicircle_y4 = 50 - 9.5 * np.sin(theta)
|
266 |
+
|
267 |
+
semicircle_data4 = pd.DataFrame({
|
268 |
+
'x': semicircle_x4,
|
269 |
+
'y': semicircle_y4
|
270 |
+
})
|
271 |
+
|
272 |
+
semicircle_data4 = semicircle_data4[semicircle_data4['x'] <= 82.5]
|
273 |
+
|
274 |
+
arc4 = alt.Chart(semicircle_data4).mark_line(
|
275 |
+
color='white',
|
276 |
+
strokeWidth=3
|
277 |
+
).encode(
|
278 |
+
x=alt.X('x', scale=alt.Scale(domain=[0, 100]), title=None ),
|
279 |
+
y=alt.Y('y', scale=alt.Scale(domain=[0, 100]), title=None)
|
280 |
+
)
|
281 |
+
|
282 |
+
|
283 |
+
df_a_match['x'] = [pos[0]['x'] for pos in df_a_match['positions']]
|
284 |
+
df_a_match['y'] = [pos[0]['y'] for pos in df_a_match['positions']]
|
285 |
+
|
286 |
+
|
287 |
+
# brush2 = alt.selection_interval(
|
288 |
+
# on="[mousedown[event.shiftKey], mouseup] > mousemove",
|
289 |
+
# translate="[mousedown[event.shiftKey], mouseup] > mousemove!",
|
290 |
+
# )
|
291 |
+
|
292 |
+
brush2 = alt.selection(type='interval', encodings=['x', 'y'])
|
293 |
+
|
294 |
+
team_event = alt.Chart(df_a_match).mark_point(
|
295 |
+
size=50,
|
296 |
+
opacity=1,
|
297 |
+
filled=True
|
298 |
+
).encode(
|
299 |
+
x=alt.X('x:Q', axis=alt.Axis(labels=False, ticks=False, grid=False)),
|
300 |
+
y=alt.Y('y:Q', axis=alt.Axis(labels=False, ticks=False, grid=False)),
|
301 |
+
color=alt.condition(brush2,
|
302 |
+
alt.Color('teamId:N', legend=None, scale=alt.Scale(domain=list(df_a_match['teamId'].unique()), range=['black', 'cyan'])),
|
303 |
+
alt.value('lightgray')),
|
304 |
+
tooltip=['eventName:N', 'teamId:N', 'x:Q', 'y:Q']
|
305 |
).add_selection(
|
306 |
+
brush2
|
307 |
+
)
|
308 |
+
|
309 |
+
|
310 |
+
zoom = alt.selection_interval(
|
311 |
+
bind='scales',
|
312 |
+
on="[mousedown[!event.shiftKey], mouseup] > mousemove",
|
313 |
+
translate="[mousedown[!event.shiftKey], mouseup] > mousemove!",
|
314 |
+
)
|
315 |
+
|
316 |
+
|
317 |
+
|
318 |
+
soccer_pitch = alt.layer(background, border_lines, midline, lines, white_dots, arc1, arc2, arc3, arc4, center_circle, team_event).properties(
|
319 |
+
width=700,
|
320 |
+
height=440,
|
321 |
+
title="Lazio - Internazionale, 2 - 3"
|
322 |
+
)
|
323 |
+
|
324 |
+
|
325 |
+
soccer_pitch = soccer_pitch.add_selection(
|
326 |
+
zoom,
|
327 |
+
)
|
328 |
+
|
329 |
+
|
330 |
+
|
331 |
+
bars = alt.Chart(df_a_match).mark_bar().encode(
|
332 |
+
y=alt.Y('eventName:N', sort='-x', title=None),
|
333 |
+
x=alt.X('count():Q', title='frequency'),
|
334 |
+
color=alt.Color('eventName:N',legend=None)
|
335 |
+
).transform_filter(
|
336 |
+
brush2
|
337 |
)
|
338 |
|
339 |
+
|
340 |
+
annotations_df = pd.DataFrame({
|
341 |
+
'text': ['You can select part of the graph to see distributoon of events'],
|
342 |
+
'x': [0],
|
343 |
+
'y': [0]
|
344 |
+
})
|
345 |
+
|
346 |
+
annotations_chart = alt.Chart(annotations_df).mark_text(
|
347 |
+
align='left',
|
348 |
+
baseline='middle',
|
349 |
+
fontSize=12,
|
350 |
+
fontStyle='italic'
|
351 |
+
).encode(
|
352 |
+
text='text:N'
|
353 |
+
).properties(
|
354 |
+
width=700,
|
355 |
+
height=20
|
356 |
)
|
357 |
|
358 |
+
soccer_pitch_with_annotations = alt.vconcat(
|
359 |
+
soccer_pitch,
|
360 |
+
annotations_chart,
|
361 |
+
spacing=5
|
362 |
)
|
363 |
|
|
|
364 |
|
365 |
+
combined_chart2 = alt.hconcat(
|
366 |
+
soccer_pitch_with_annotations,
|
367 |
+
bars,
|
368 |
spacing=10
|
369 |
).resolve_scale(
|
370 |
color='independent'
|
371 |
)
|
372 |
+
|
373 |
|
374 |
|
375 |
chart1_panel = pn.pane.Vega(chart1, sizing_mode='stretch_width')
|
376 |
+
combined_chart1_panel = pn.pane.Vega(combined_chart2, sizing_mode='stretch_width')
|
|
|
377 |
|
378 |
|
379 |
dashboard = pn.Column(
|
380 |
"# My Interactive Dashboard", # 可以添加标题
|
381 |
chart1_panel,
|
382 |
+
combined_chart2_panel
|
|
|
383 |
)
|
384 |
|
385 |
# 设置应用程序为可服务的
|