Vincentran commited on
Commit
357f2cf
Β·
verified Β·
1 Parent(s): 625b0fe

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +182 -38
src/streamlit_app.py CHANGED
@@ -1,40 +1,184 @@
1
- import altair as alt
2
- import numpy as np
3
- import pandas as pd
4
  import streamlit as st
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
- """
7
- # Welcome to Streamlit!
8
-
9
- Edit `/streamlit_app.py` to customize this app to your heart's desire :heart:.
10
- If you have any questions, checkout our [documentation](https://docs.streamlit.io) and [community
11
- forums](https://discuss.streamlit.io).
12
-
13
- In the meantime, below is an example of what you can do with just a few lines of code:
14
- """
15
-
16
- num_points = st.slider("Number of points in spiral", 1, 10000, 1100)
17
- num_turns = st.slider("Number of turns in spiral", 1, 300, 31)
18
-
19
- indices = np.linspace(0, 1, num_points)
20
- theta = 2 * np.pi * num_turns * indices
21
- radius = indices
22
-
23
- x = radius * np.cos(theta)
24
- y = radius * np.sin(theta)
25
-
26
- df = pd.DataFrame({
27
- "x": x,
28
- "y": y,
29
- "idx": indices,
30
- "rand": np.random.randn(num_points),
31
- })
32
-
33
- st.altair_chart(alt.Chart(df, height=700, width=700)
34
- .mark_point(filled=True)
35
- .encode(
36
- x=alt.X("x", axis=None),
37
- y=alt.Y("y", axis=None),
38
- color=alt.Color("idx", legend=None, scale=alt.Scale()),
39
- size=alt.Size("rand", legend=None, scale=alt.Scale(range=[1, 150])),
40
- ))
 
 
 
 
1
  import streamlit as st
2
+ import pandas as pd
3
+ import plotly.express as px
4
+ import requests
5
+ import numpy as np
6
+
7
+ st.set_page_config(
8
+ page_title="Global Technology Education Dashboard",
9
+ page_icon="πŸŽ“",
10
+ layout="wide"
11
+ )
12
+
13
+ API_URL = "https://data360api.worldbank.org/data360/data?DATABASE_ID=WB_EDSTATS&INDICATOR=WB_EDSTATS_UIS_FOSGP_5T8_F500600700&skip=0"
14
+
15
+ @st.cache_data(ttl=86400)
16
+ def load_data():
17
+ response = requests.get(API_URL, timeout=30)
18
+ response.raise_for_status()
19
+
20
+ data = response.json()
21
+
22
+ df = pd.DataFrame(data["value"])
23
+
24
+ df["OBS_VALUE"] = pd.to_numeric(df["OBS_VALUE"], errors="coerce")
25
+ df["TIME_PERIOD"] = pd.to_numeric(df["TIME_PERIOD"], errors="coerce")
26
+
27
+ df = df.dropna(subset=["OBS_VALUE", "TIME_PERIOD"])
28
+
29
+ return df
30
+
31
+ df = load_data()
32
+
33
+ st.title("πŸŽ“ Global Technology Education Dashboard")
34
+ st.caption("Source: World Bank Education Statistics (Auto Updated)")
35
+
36
+ # Sidebar
37
+ st.sidebar.header("Filters")
38
+
39
+ countries = sorted(df["REF_AREA"].dropna().unique())
40
+
41
+ selected_countries = st.sidebar.multiselect(
42
+ "Select Countries",
43
+ countries,
44
+ default=["VNM"] if "VNM" in countries else countries[:3]
45
+ )
46
+
47
+ year_range = st.sidebar.slider(
48
+ "Year Range",
49
+ int(df["TIME_PERIOD"].min()),
50
+ int(df["TIME_PERIOD"].max()),
51
+ (
52
+ int(df["TIME_PERIOD"].min()),
53
+ int(df["TIME_PERIOD"].max())
54
+ )
55
+ )
56
+
57
+ filtered_df = df[
58
+ (df["TIME_PERIOD"] >= year_range[0]) &
59
+ (df["TIME_PERIOD"] <= year_range[1])
60
+ ]
61
+
62
+ # KPI Section
63
+ latest_year = filtered_df["TIME_PERIOD"].max()
64
+
65
+ latest_df = filtered_df[
66
+ filtered_df["TIME_PERIOD"] == latest_year
67
+ ]
68
+
69
+ global_avg = latest_df["OBS_VALUE"].mean()
70
+
71
+ top_country = latest_df.loc[
72
+ latest_df["OBS_VALUE"].idxmax()
73
+ ]
74
+
75
+ col1, col2, col3, col4 = st.columns(4)
76
+
77
+ col1.metric(
78
+ "Countries",
79
+ latest_df["REF_AREA"].nunique()
80
+ )
81
+
82
+ col2.metric(
83
+ "Latest Year",
84
+ int(latest_year)
85
+ )
86
+
87
+ col3.metric(
88
+ "Global Average",
89
+ f"{global_avg:.2f}"
90
+ )
91
+
92
+ col4.metric(
93
+ "Top Country",
94
+ top_country["REF_AREA"]
95
+ )
96
+
97
+ st.divider()
98
+
99
+ # Global Trend
100
+ st.subheader("πŸ“ˆ Global Trend")
101
+
102
+ global_trend = (
103
+ filtered_df
104
+ .groupby("TIME_PERIOD")["OBS_VALUE"]
105
+ .mean()
106
+ .reset_index()
107
+ )
108
+
109
+ fig_trend = px.line(
110
+ global_trend,
111
+ x="TIME_PERIOD",
112
+ y="OBS_VALUE",
113
+ markers=True,
114
+ title="Average Technology Education Indicator Over Time"
115
+ )
116
+
117
+ st.plotly_chart(fig_trend, use_container_width=True)
118
+
119
+ # Country Comparison
120
+ st.subheader("🌎 Country Comparison")
121
+
122
+ compare_df = filtered_df[
123
+ filtered_df["REF_AREA"].isin(selected_countries)
124
+ ]
125
+
126
+ fig_compare = px.line(
127
+ compare_df,
128
+ x="TIME_PERIOD",
129
+ y="OBS_VALUE",
130
+ color="REF_AREA",
131
+ markers=True
132
+ )
133
+
134
+ st.plotly_chart(fig_compare, use_container_width=True)
135
+
136
+ # Top Countries
137
+ st.subheader("πŸ† Top 20 Countries")
138
+
139
+ top20 = (
140
+ latest_df
141
+ .sort_values("OBS_VALUE", ascending=False)
142
+ .head(20)
143
+ )
144
+
145
+ fig_top = px.bar(
146
+ top20,
147
+ x="OBS_VALUE",
148
+ y="REF_AREA",
149
+ orientation="h"
150
+ )
151
+
152
+ st.plotly_chart(fig_top, use_container_width=True)
153
+
154
+ # Distribution
155
+ st.subheader("πŸ“Š Distribution")
156
+
157
+ fig_hist = px.histogram(
158
+ latest_df,
159
+ x="OBS_VALUE",
160
+ nbins=30
161
+ )
162
+
163
+ st.plotly_chart(fig_hist, use_container_width=True)
164
+
165
+ # Data Explorer
166
+ st.subheader("πŸ“‹ Data Explorer")
167
+
168
+ st.dataframe(
169
+ filtered_df.sort_values(
170
+ ["TIME_PERIOD", "REF_AREA"],
171
+ ascending=[False, True]
172
+ ),
173
+ use_container_width=True
174
+ )
175
+
176
+ # Download CSV
177
+ csv = filtered_df.to_csv(index=False)
178
 
179
+ st.download_button(
180
+ label="⬇ Download CSV",
181
+ data=csv,
182
+ file_name="technology_education_dashboard.csv",
183
+ mime="text/csv"
184
+ )