lyimo commited on
Commit
5c12924
·
verified ·
1 Parent(s): 331380c

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +227 -0
app.py ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import numpy as np
4
+ import plotly.express as px
5
+ import folium
6
+ from streamlit_folium import st_folium
7
+
8
+ # ----------------------------------------------------
9
+ # 1. Load data
10
+ # ----------------------------------------------------
11
+ @st.cache_data
12
+ def load_data():
13
+ # Load daily and monthly CSV from local files (or a URL if needed)
14
+ daily_df = pd.read_csv("daily_data_2013_2024.csv", parse_dates=["date"])
15
+ monthly_df = pd.read_csv("monthly_data_2013_2024.csv")
16
+
17
+ # If monthly_df also needs a 'date' column for plotting (like first day of month), you can create:
18
+ # monthly_df["date"] = pd.to_datetime(monthly_df["year"].astype(str) + "-" + monthly_df["month"].astype(str) + "-01")
19
+
20
+ return daily_df, monthly_df
21
+
22
+ daily_data, monthly_data = load_data()
23
+
24
+ # Pre-define your location dictionary so we can map lat/lon
25
+ LOCATIONS = {
26
+ "Karagwe": {"lat": -1.7718, "lon": 30.9876},
27
+ "Masasi": {"lat": -10.7167, "lon": 38.8000},
28
+ "Igunga": {"lat": -4.2833, "lon": 33.8833}
29
+ }
30
+
31
+ # ----------------------------------------------------
32
+ # 2. Streamlit UI Layout
33
+ # ----------------------------------------------------
34
+ st.title("Malaria & Dengue Outbreak Analysis (2013–2024)")
35
+
36
+ st.sidebar.header("Filters & Options")
37
+
38
+ # Choose disease type to focus on
39
+ disease_choice = st.sidebar.radio("Select Disease", ["Malaria", "Dengue"])
40
+
41
+ # Choose data granularity
42
+ data_choice = st.sidebar.radio("Data Granularity", ["Monthly", "Daily"])
43
+
44
+ # Let user filter location(s)
45
+ location_list = list(LOCATIONS.keys())
46
+ selected_locations = st.sidebar.multiselect("Select Location(s)", location_list, default=location_list)
47
+
48
+ # For monthly data, let user select a year range
49
+ if data_choice == "Monthly":
50
+ year_min = int(monthly_data["year"].min())
51
+ year_max = int(monthly_data["year"].max())
52
+ year_range = st.sidebar.slider("Select Year Range",
53
+ min_value=year_min,
54
+ max_value=year_max,
55
+ value=(year_min, year_max))
56
+ # For daily data, let user select a date range
57
+ else:
58
+ date_min = daily_data["date"].min()
59
+ date_max = daily_data["date"].max()
60
+ date_range = st.sidebar.date_input("Select Date Range",
61
+ [date_min, date_max],
62
+ min_value=date_min,
63
+ max_value=date_max)
64
+
65
+ # ----------------------------------------------------
66
+ # 3. Filter data based on user input
67
+ # ----------------------------------------------------
68
+ if data_choice == "Monthly":
69
+ # Subset monthly data for selected locations
70
+ df = monthly_data[monthly_data["location"].isin(selected_locations)].copy()
71
+ # Filter year range
72
+ df = df[(df["year"] >= year_range[0]) & (df["year"] <= year_range[1])]
73
+
74
+ # Create a "date" column for monthly plotting (1st of each month)
75
+ # This can help create a time-series for Plotly
76
+ df["date"] = pd.to_datetime(df["year"].astype(str) + "-" + df["month"].astype(str) + "-01")
77
+
78
+ else:
79
+ # Subset daily data
80
+ df = daily_data[daily_data["location"].isin(selected_locations)].copy()
81
+ # Filter date range
82
+ df = df[(df["date"] >= pd.to_datetime(date_range[0])) & (df["date"] <= pd.to_datetime(date_range[1]))]
83
+
84
+ # ----------------------------------------------------
85
+ # 4. Interactive Plotly Time-Series
86
+ # ----------------------------------------------------
87
+ st.subheader(f"{data_choice} {disease_choice} Risk & Climate Parameters")
88
+
89
+ # Decide which columns are relevant
90
+ risk_col = "malaria_risk" if disease_choice == "Malaria" else "dengue_risk"
91
+
92
+ if data_choice == "Monthly":
93
+ # We'll plot a line chart of risk, temperature, and rainfall vs. date
94
+ fig = px.line(df, x="date", y=risk_col, color="location",
95
+ title=f"{disease_choice} Risk Over Time ({data_choice})")
96
+ fig.update_layout(yaxis_title="Risk (0–1)")
97
+
98
+ st.plotly_chart(fig, use_container_width=True)
99
+
100
+ # Optionally plot temperature / rainfall on another figure
101
+ col1, col2 = st.columns(2)
102
+ with col1:
103
+ fig_temp = px.line(df, x="date", y="temp_avg", color="location",
104
+ title="Average Temperature (°C)")
105
+ st.plotly_chart(fig_temp, use_container_width=True)
106
+ with col2:
107
+ # 'monthly_rainfall_mm' is total monthly rainfall
108
+ fig_rain = px.line(df, x="date", y="monthly_rainfall_mm", color="location",
109
+ title="Monthly Rainfall (mm)")
110
+ st.plotly_chart(fig_rain, use_container_width=True)
111
+
112
+ # Show outbreak flags if focusing on monthly
113
+ if disease_choice == "Malaria":
114
+ flag_col = "malaria_outbreak"
115
+ else:
116
+ flag_col = "dengue_outbreak"
117
+
118
+ outbreak_months = df[df[flag_col] == True]
119
+ if not outbreak_months.empty:
120
+ st.write(f"**Months with likely {disease_choice} outbreak:**")
121
+ st.dataframe(outbreak_months[["location","year","month","temp_avg","humidity","monthly_rainfall_mm",flag_col]])
122
+ else:
123
+ st.write(f"No months meet the {disease_choice} outbreak criteria in this selection.")
124
+
125
+ else:
126
+ # For daily data, plot daily risk
127
+ fig = px.line(df, x="date", y=risk_col, color="location",
128
+ title=f"{disease_choice} Daily Risk Over Time (2013–2024)")
129
+ fig.update_layout(yaxis_title="Risk (0–1)")
130
+ st.plotly_chart(fig, use_container_width=True)
131
+
132
+ # Similarly, temperature & daily rainfall
133
+ col1, col2 = st.columns(2)
134
+ with col1:
135
+ fig_temp = px.line(df, x="date", y="temp_avg", color="location",
136
+ title="Daily Avg Temperature (°C)")
137
+ st.plotly_chart(fig_temp, use_container_width=True)
138
+ with col2:
139
+ fig_rain = px.line(df, x="date", y="daily_rainfall_mm", color="location",
140
+ title="Daily Rainfall (mm)")
141
+ st.plotly_chart(fig_rain, use_container_width=True)
142
+
143
+ # ----------------------------------------------------
144
+ # 5. Correlation Heatmap
145
+ # ----------------------------------------------------
146
+ st.subheader(f"Correlation Heatmap - {data_choice} Data")
147
+
148
+ # We'll pick relevant numeric columns
149
+ if data_choice == "Monthly":
150
+ subset_cols = ["temp_avg", "humidity", "monthly_rainfall_mm", "malaria_risk", "dengue_risk"]
151
+ else:
152
+ subset_cols = ["temp_avg", "humidity", "daily_rainfall_mm", "malaria_risk", "dengue_risk"]
153
+
154
+ corr_df = df[subset_cols].corr()
155
+ fig_corr = px.imshow(corr_df, text_auto=True, aspect="auto",
156
+ title="Correlation Matrix of Weather & Risk")
157
+ st.plotly_chart(fig_corr, use_container_width=True)
158
+
159
+ # ----------------------------------------------------
160
+ # 6. Interactive Map (Folium)
161
+ # ----------------------------------------------------
162
+ st.subheader("Interactive Map")
163
+ st.markdown(
164
+ """
165
+ **Note**: We only have 3 locations. Each marker popup shows some aggregated
166
+ stats for the displayed data range.
167
+ """
168
+ )
169
+
170
+ # Create a base map centered roughly in Tanzania
171
+ m = folium.Map(location=[-6.0, 35.0], zoom_start=6)
172
+
173
+ # We'll show monthly or daily aggregates in the popups
174
+ if data_choice == "Monthly":
175
+ # For each location, let's gather monthly avg for the current df
176
+ # Then we can show a simple summary in the popup
177
+ for loc in selected_locations:
178
+ loc_info = LOCATIONS[loc]
179
+ loc_df = df[df["location"] == loc]
180
+
181
+ if loc_df.empty:
182
+ continue
183
+ # Basic stats: average risk, average rainfall, etc
184
+ avg_risk = loc_df[risk_col].mean()
185
+ avg_temp = loc_df["temp_avg"].mean()
186
+ avg_rain = loc_df["monthly_rainfall_mm"].mean()
187
+
188
+ # Build popup HTML
189
+ popup_html = f"""
190
+ <b>{loc}</b><br/>
191
+ Disease: {disease_choice}<br/>
192
+ Avg Risk (in selection): {avg_risk:.2f}<br/>
193
+ Avg Temp (°C): {avg_temp:.2f}<br/>
194
+ Avg Rainfall (mm): {avg_rain:.2f}<br/>
195
+ """
196
+ folium.Marker(
197
+ location=[loc_info["lat"], loc_info["lon"]],
198
+ popup=popup_html,
199
+ tooltip=f"{loc} ({disease_choice})"
200
+ ).add_to(m)
201
+ else:
202
+ # Daily data
203
+ for loc in selected_locations:
204
+ loc_info = LOCATIONS[loc]
205
+ loc_df = df[df["location"] == loc]
206
+
207
+ if loc_df.empty:
208
+ continue
209
+ avg_risk = loc_df[risk_col].mean()
210
+ avg_temp = loc_df["temp_avg"].mean()
211
+ avg_rain = loc_df["daily_rainfall_mm"].mean()
212
+
213
+ popup_html = f"""
214
+ <b>{loc}</b><br/>
215
+ Disease: {disease_choice}<br/>
216
+ Avg Risk (in selection): {avg_risk:.2f}<br/>
217
+ Avg Temp (°C): {avg_temp:.2f}<br/>
218
+ Avg Rain (mm/day): {avg_rain:.2f}<br/>
219
+ """
220
+ folium.Marker(
221
+ location=[loc_info["lat"], loc_info["lon"]],
222
+ popup=popup_html,
223
+ tooltip=f"{loc} ({disease_choice})"
224
+ ).add_to(m)
225
+
226
+ # Render Folium map in Streamlit
227
+ st_data = st_folium(m, width=700, height=500)