Spaces:
Sleeping
Sleeping
Commit
•
3308a7e
1
Parent(s):
99159f5
Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,81 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import pandas as pd
|
3 |
+
import numpy as np
|
4 |
+
import plotly.express as px
|
5 |
+
import datetime as dt
|
6 |
+
|
7 |
+
#### TITLE/PAGE
|
8 |
+
st.set_page_config(layout="wide", page_icon="⚽", page_title="FPL Stats")
|
9 |
+
st.title("⚽ FPL Lab")
|
10 |
+
st.caption("A live dashboard of the top 200 Premiere League players across all positions. Metrics plotted include Cost, Points Earned, Form, Selection Rate, etc. Use the Position Analysis tab to pick cheap/high value players.")
|
11 |
+
st.toast('Includes all data through W5', icon='⚽')
|
12 |
+
|
13 |
+
|
14 |
+
#### DATA PROCESSING
|
15 |
+
df = pd.read_csv('week5_fpl.csv')
|
16 |
+
df.fillna(0, inplace=True)
|
17 |
+
pattern = r'(.+)\r\n(.{3})(.+)'
|
18 |
+
df[['name', 'team', 'position']] = df['Player'].str.extract(pattern)
|
19 |
+
df = df.rename(columns={'Seelection Rate': 'Selection Rate',})
|
20 |
+
df[['Cost (M)','Form','Points Earned']] = df[['Cost (M)','Form','Points Earned']].astype(float)
|
21 |
+
df['P/C'] = df['Points Earned'] / df['Cost (M)']
|
22 |
+
df[['Status','Player','name','team','position']] = df[['Status','Player','name','team','position']].astype(str)
|
23 |
+
df['Selection Rate'] = df['Selection Rate'].str.rstrip('%').astype('float')
|
24 |
+
|
25 |
+
#### SIDEBAR
|
26 |
+
with st.sidebar:
|
27 |
+
st.title("Player Search")
|
28 |
+
options = st.multiselect(
|
29 |
+
'Choose Position',
|
30 |
+
['FWD','MID','DEF','GKP'])
|
31 |
+
price = st.slider(
|
32 |
+
"Pick a price range:",
|
33 |
+
min_value=0,
|
34 |
+
max_value=20,
|
35 |
+
value=(0, 15))
|
36 |
+
st.write("Price Range: $",price)
|
37 |
+
new_df = df[df['position'].isin(options)]
|
38 |
+
new_df = new_df[(new_df['Cost (M)'] >= price[0]) & (new_df['Cost (M)'] <= price[1])]
|
39 |
+
new_df = new_df.rename(columns={'Points Earned': 'Points',})
|
40 |
+
st.dataframe(new_df[['name','position','Points','Cost (M)','P/C']],hide_index=True)
|
41 |
+
|
42 |
+
#### TABS
|
43 |
+
tab1, tab2,tab3 = st.tabs(["Position Analysis", "Total Metrics","Player Utility"])
|
44 |
+
with tab1:
|
45 |
+
st.caption("These plots look at points earned and cost of the players. We want players closer to the bottom right of the graphs meaning they earn points but are cheap.")
|
46 |
+
position_scatter_fig = px.scatter(df, y="Cost (M)", x="Points Earned", color="Form", template="plotly_dark", facet_col="position",hover_data=['name','team','position','Form'])
|
47 |
+
position_scatter_fig.update_xaxes(showgrid=False,showline=False)
|
48 |
+
position_scatter_fig.update_yaxes(showgrid=False)
|
49 |
+
st.plotly_chart(position_scatter_fig, use_container_width=True)
|
50 |
+
|
51 |
+
heatmap_fig = px.density_heatmap(df, x="Points Earned", y="Cost (M)",template="plotly_dark",facet_col="position")
|
52 |
+
heatmap_fig.update_xaxes(showgrid=False,showline=False)
|
53 |
+
heatmap_fig.update_yaxes(showgrid=False)
|
54 |
+
st.plotly_chart(heatmap_fig, use_container_width=True)
|
55 |
+
|
56 |
+
with tab2:
|
57 |
+
st.caption("Here we have a consolidated scatter plot of the data on the other page, and a look at team point contributions ")
|
58 |
+
summary_fig = px.scatter(df, x="Cost (M)", y="Points Earned", size="Selection Rate", color="Form",hover_data=['name','team','position','Form'], template="plotly_dark", title="Player Cost vs Points Earned (sized by selection rate and colored by form)",size_max=12) #text="name",
|
59 |
+
summary_fig.update_xaxes(showgrid=False,showline=False)
|
60 |
+
summary_fig.update_yaxes(showgrid=False)
|
61 |
+
st.plotly_chart(summary_fig, use_container_width=True)
|
62 |
+
|
63 |
+
fig_bar = px.bar(df, x="team", y="Points Earned",template="plotly_dark", color='Cost (M)', title="Points Contributed and Cost by Team",hover_data=['name','team','position','Form']) #color_continuous_scale='YlOrRd'
|
64 |
+
fig_bar.update_layout(barmode='stack', xaxis={'categoryorder':'total descending'})
|
65 |
+
fig_bar.update_xaxes(showgrid=False,showline=False)
|
66 |
+
fig_bar.update_yaxes(showgrid=False)
|
67 |
+
st.plotly_chart(fig_bar, use_container_width=True)
|
68 |
+
|
69 |
+
|
70 |
+
with tab3:
|
71 |
+
st.caption("We introduce a new features here to measure player utility. This is calculated by dividing points earned by cost referred to as P/C. Outliers in these plots could indicate high utility players for your roster.")
|
72 |
+
utility_scatter = px.scatter(df, x="Form", y="P/C", color="Cost (M)",hover_data=['name','team','position','Form'], template="plotly_dark", title="Player Utility vs Form, colored by cost",size_max=12) #text="name",
|
73 |
+
utility_scatter.update_xaxes(showgrid=False,showline=False)
|
74 |
+
utility_scatter.update_yaxes(showgrid=False)
|
75 |
+
st.plotly_chart(utility_scatter, use_container_width=True)
|
76 |
+
|
77 |
+
utility_bar = px.violin(df, x="position", y="P/C", points='all', color='position',hover_data=['name','team','position','Form'], template="plotly_dark", title="Utility Distribution Across Positions") #text="name",
|
78 |
+
utility_bar.update_xaxes(showgrid=False,showline=False)
|
79 |
+
utility_bar.update_yaxes(showgrid=False)
|
80 |
+
st.plotly_chart(utility_bar, use_container_width=True)
|
81 |
+
|