Spaces:
Runtime error
Runtime error
import panel as pn | |
import json | |
from collections import Counter | |
import numpy as np | |
import pandas as pd | |
import altair as alt | |
import operator | |
import warnings | |
warnings.filterwarnings('ignore') | |
pn.extension('vega') | |
# loading the events data | |
events={} | |
nations = ['Italy','England','Germany','France','Spain','European_Championship','World_Cup'] | |
for nation in nations: | |
with open('events/events_%s.json' %nation) as json_data: | |
events[nation] = json.load(json_data) | |
# loading the match data | |
matches={} | |
nations = ['Italy','England','Germany','France','Spain','European_Championship','World_Cup'] | |
for nation in nations: | |
with open('matches/matches_%s.json' %nation) as json_data: | |
matches[nation] = json.load(json_data) | |
# loading the players data | |
players={} | |
with open('players.json') as json_data: | |
players = json.load(json_data) | |
# loading the competitions data | |
competitions={} | |
with open('competitions.json') as json_data: | |
competitions = json.load(json_data) | |
ev_all_nations = [] | |
for nation in nations: | |
for i in range(len(events[nation])): | |
ev_all_nations.append(events[nation][i]['eventName']) | |
count = Counter(ev_all_nations) | |
total = len(ev_all_nations) | |
counter = {event: int((count / total) * 100) for event, count in count.items()} | |
sorted_counter = sorted(counter.items(), key=operator.itemgetter(1), reverse=False) | |
data = pd.DataFrame(sorted_counter, columns=['Event', 'Percentage']) | |
brush = alt.selection_interval(encodings=['y']) | |
max_value = data['Percentage'].max() | |
tick_values = list(range(0, int(max_value) + 10, 10)) | |
bars = alt.Chart(data).mark_bar().encode( | |
y=alt.Y('Event:N', title=None, sort='-x'), | |
x=alt.X('Percentage:Q', title='events(%)', axis=alt.Axis(values=tick_values)), | |
color=alt.condition(brush, alt.Color('Event:N', legend=None), alt.value('lightgray')) | |
).add_selection( | |
brush | |
) | |
average_rule = alt.Chart(data).mark_rule(color='firebrick', strokeWidth=2).encode( | |
x='mean(Percentage):Q' | |
).transform_filter( | |
brush | |
) | |
average_text = alt.Chart(data).mark_text( | |
dx=5, dy=-5, color='firebrick', align='left', fontWeight='bold' | |
).encode( | |
x=alt.X('mean(Percentage):Q', aggregate='mean'), | |
text=alt.Text('mean(Percentage):Q', aggregate='mean', format='.1f') | |
).transform_filter( | |
brush | |
) | |
chart1 = alt.layer(bars, average_rule, average_text).properties( | |
width=600, | |
height=500, | |
title='Events Distribution' | |
) | |
# Display the combined chart | |
chart1 | |
match_id = 2576335 | |
a_match = [] | |
for nation in nations: | |
for ev in events[nation]: | |
if ev['matchId'] == match_id: | |
a_match.append(ev) | |
for nation in nations: | |
for match in matches[nation]: | |
if match['wyId'] == match_id: | |
match_f = match | |
df_a_match = pd.DataFrame(a_match) | |
background_data = pd.DataFrame({ | |
'x': [0], | |
'y': [0], | |
'x2': [100], | |
'y2': [100] | |
}) | |
# Create the background | |
background = alt.Chart(background_data).mark_rect( | |
color='#195905' | |
).encode( | |
x='x:Q', | |
y='y:Q', | |
x2='x2:Q', | |
y2='y2:Q' | |
) | |
#Define the center circle | |
center_circle = alt.Chart(pd.DataFrame({'x': [50], 'y': [50]})).mark_point( | |
size=12000, | |
color='white', | |
strokeWidth=3 | |
).encode( | |
x='x:Q', | |
y='y:Q' | |
) | |
# Create the border lines | |
border_lines_data = pd.DataFrame({ | |
'x': [1, 1, 99.5, 99.5, 1], | |
'y': [1, 99.5, 99.5, 1, 1], | |
'x2': [1, 99.5, 99.5, 1, 1], | |
'y2': [99.5, 99.5, 1, 1, 1] | |
}) | |
border_lines = alt.Chart(border_lines_data).mark_line( | |
color='white', | |
strokeWidth=3 | |
).encode( | |
x=alt.X('x:Q', scale=alt.Scale(domain=[1, 99.5])), | |
y=alt.Y('y:Q', scale=alt.Scale(domain=[1, 99.5])), | |
x2='x2:Q', | |
y2='y2:Q' | |
) | |
midline_data = pd.DataFrame({ | |
'x': [50, 50,], | |
'y': [1, 99, ] | |
}) | |
# Create the line using `mark_line` | |
midline = alt.Chart(midline_data).mark_line( | |
color='white', | |
strokeWidth=3 | |
).encode( | |
x='x:Q', | |
y='y:Q' | |
) | |
lines_data = pd.DataFrame({ | |
'x': [1, 17.5, 17.5, 1, 82.5, 82.5, 99,1,6.5,6.5,1, 99,93.5,93.5], | |
'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], | |
'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], | |
'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] | |
}) | |
lines = alt.Chart(lines_data).mark_line( | |
color='white', | |
strokeWidth=3 | |
).encode( | |
x='x:Q', | |
y='y:Q', | |
x2='x2:Q', | |
y2='y2:Q' | |
) | |
dot_positions = pd.DataFrame({ | |
'x': [12, 87], | |
'y': [50, 50] | |
}) | |
# Create the white dots | |
white_dots = alt.Chart(dot_positions).mark_point( | |
size=100, | |
color='white', | |
filled=True | |
).encode( | |
x='x:Q', | |
y='y:Q' | |
) | |
theta = np.linspace(0, np.pi, 100) | |
semicircle_x = 12 + 9.5 * np.cos(theta) | |
semicircle_y = 50 + 9.5 * np.sin(theta) | |
semicircle_data = pd.DataFrame({ | |
'x': semicircle_x, | |
'y': semicircle_y | |
}) | |
semicircle_data = semicircle_data[semicircle_data['x'] >= 17.5] | |
arc1 = alt.Chart(semicircle_data).mark_line( | |
color='white', | |
strokeWidth=3 | |
).encode( | |
x=alt.X('x', scale=alt.Scale(domain=[0, 100])), | |
y=alt.Y('y', scale=alt.Scale(domain=[0, 100])) | |
) | |
theta = np.linspace(0, np.pi, 100) | |
semicircle_x2 = 12 + 9.5 * np.cos(theta) | |
semicircle_y2 = 50 - 9.5 * np.sin(theta) | |
semicircle_data2 = pd.DataFrame({ | |
'x': semicircle_x2, | |
'y': semicircle_y2 | |
}) | |
semicircle_data2 = semicircle_data2[semicircle_data2['x'] >= 17.5] | |
arc2 = alt.Chart(semicircle_data2).mark_line( | |
color='white', | |
strokeWidth=3 | |
).encode( | |
x=alt.X('x', scale=alt.Scale(domain=[0, 100])), | |
y=alt.Y('y', scale=alt.Scale(domain=[0, 100])) | |
) | |
theta = np.linspace(0, np.pi, 100) | |
semicircle_x3 = 87 - 9.5 * np.cos(theta) | |
semicircle_y3 = 50 + 9.5 * np.sin(theta) | |
semicircle_data3 = pd.DataFrame({ | |
'x': semicircle_x3, | |
'y': semicircle_y3 | |
}) | |
semicircle_data3 = semicircle_data3[semicircle_data3['x'] <= 82.5] | |
arc3 = alt.Chart(semicircle_data3).mark_line( | |
color='white', | |
strokeWidth=3 | |
).encode( | |
x=alt.X('x', scale=alt.Scale(domain=[0, 100])), | |
y=alt.Y('y', scale=alt.Scale(domain=[0, 100])) | |
) | |
theta = np.linspace(0, np.pi, 100) | |
semicircle_x4 = 87 - 9.5 * np.cos(theta) | |
semicircle_y4 = 50 - 9.5 * np.sin(theta) | |
semicircle_data4 = pd.DataFrame({ | |
'x': semicircle_x4, | |
'y': semicircle_y4 | |
}) | |
semicircle_data4 = semicircle_data4[semicircle_data4['x'] <= 82.5] | |
arc4 = alt.Chart(semicircle_data4).mark_line( | |
color='white', | |
strokeWidth=3 | |
).encode( | |
x=alt.X('x', scale=alt.Scale(domain=[0, 100]), title=None ), | |
y=alt.Y('y', scale=alt.Scale(domain=[0, 100]), title=None) | |
) | |
df_a_match['x'] = [pos[0]['x'] for pos in df_a_match['positions']] | |
df_a_match['y'] = [pos[0]['y'] for pos in df_a_match['positions']] | |
df_a_match.drop('positions', axis=1, inplace=True) | |
df_a_match.drop('tags', axis=1, inplace=True) | |
# brush2 = alt.selection_interval( | |
# on="[mousedown[event.shiftKey], mouseup] > mousemove", | |
# translate="[mousedown[event.shiftKey], mouseup] > mousemove!", | |
# ) | |
brush2 = alt.selection(type='interval', encodings=['x', 'y']) | |
team_event = alt.Chart(df_a_match).mark_point( | |
size=50, | |
opacity=1, | |
filled=True | |
).encode( | |
x=alt.X('x:Q', axis=alt.Axis(labels=False, ticks=False, grid=False)), | |
y=alt.Y('y:Q', axis=alt.Axis(labels=False, ticks=False, grid=False)), | |
color=alt.condition(brush2, | |
alt.Color('teamId:N', legend=None, scale=alt.Scale(domain=list(df_a_match['teamId'].unique()), range=['black', 'cyan'])), | |
alt.value('lightgray')), | |
tooltip=['eventName:N', 'teamId:N', 'x:Q', 'y:Q'] | |
).add_selection( | |
brush2 | |
) | |
zoom = alt.selection_interval( | |
bind='scales', | |
on="[mousedown[!event.shiftKey], mouseup] > mousemove", | |
translate="[mousedown[!event.shiftKey], mouseup] > mousemove!", | |
) | |
soccer_pitch = alt.layer(background, border_lines, midline, lines, white_dots, arc1, arc2, arc3, arc4, center_circle, team_event).properties( | |
width=700, | |
height=440, | |
title="Lazio - Internazionale, 2 - 3" | |
) | |
soccer_pitch = soccer_pitch.add_selection( | |
zoom, | |
) | |
bars = alt.Chart(df_a_match).mark_bar().encode( | |
y=alt.Y('eventName:N', sort='-x', title=None), | |
x=alt.X('count():Q', title='frequency'), | |
color=alt.Color('eventName:N',legend=None) | |
).transform_filter( | |
brush2 | |
) | |
annotations_df = pd.DataFrame({ | |
'text': ['You can select part of the graph to see distributoon of events'], | |
'x': [0], | |
'y': [0] | |
}) | |
annotations_chart = alt.Chart(annotations_df).mark_text( | |
align='left', | |
baseline='middle', | |
fontSize=12, | |
fontStyle='italic' | |
).encode( | |
text='text:N' | |
).properties( | |
width=700, | |
height=20 | |
) | |
soccer_pitch_with_annotations = alt.vconcat( | |
soccer_pitch, | |
annotations_chart, | |
spacing=5 | |
) | |
combined_chart2 = alt.hconcat( | |
soccer_pitch_with_annotations, | |
bars, | |
spacing=10 | |
).resolve_scale( | |
color='independent' | |
) | |
chart1_panel = pn.pane.Vega(chart1, sizing_mode='stretch_width') | |
combined_chart2_panel = pn.pane.Vega(combined_chart2, sizing_mode='stretch_width') | |
dashboard = pn.Column( | |
"# My Interactive Dashboard", # 可以添加标题 | |
chart1_panel, | |
combined_chart2_panel | |
) | |
# 设置应用程序为可服务的 | |
dashboard.servable(title='Scientific Visualization Project') | |