CSDI-Weather / pages /3_Humidity.py
OttoYu's picture
Demo Application.
35e0c07 verified
raw
history blame
6.28 kB
import streamlit as st
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
import folium
from folium import LinearColormap
import requests
from datetime import datetime, timedelta
from streamlit_folium import st_folium
# Set page layout to wide
st.set_page_config(layout="wide", page_title="Real-Time Relative Humidity Data Dashboard")
# Function to load data
@st.cache_data(ttl=300) # Cache data to avoid reloading every time
def load_data():
with st.spinner("Loading data..."):
response = requests.get("https://csdi.vercel.app/weather/rhum")
data = response.json()
features = data['features']
df = pd.json_normalize(features)
df.rename(columns={
'properties.Relative Humidity(percent)': 'Relative Humidity (%)',
'properties.Automatic Weather Station': 'Station Name',
'geometry.coordinates': 'Coordinates'
}, inplace=True)
return df
# Check if the data has been loaded before
if 'last_run' not in st.session_state or (datetime.now() - st.session_state.last_run) > timedelta(minutes=5):
st.session_state.df = load_data()
st.session_state.last_run = datetime.now()
# Data
df = st.session_state.df
# Compute statistics
humidity_data = df['Relative Humidity (%)']
avg_humidity = humidity_data.mean()
max_humidity = humidity_data.max()
min_humidity = humidity_data.min()
std_humidity = humidity_data.std()
# Create three columns
col1, col2, col3 = st.columns([1.65, 2, 1.15])
# Column 1: Histogram and statistics
with col1:
# Define colors for gradient
color_scale = ['#58a0db', '#0033cc']
# Create histogram
fig = px.histogram(df, x='Relative Humidity (%)', nbins=20,
labels={'Relative Humidity (%)': 'Relative Humidity (%)'},
title='Relative Humidity Histogram',
color_discrete_sequence=color_scale)
# Add average line
fig.add_shape(
go.layout.Shape(
type="line",
x0=avg_humidity,
y0=0,
x1=avg_humidity,
y1=df['Relative Humidity (%)'].value_counts().max(),
line=dict(color="red", width=2, dash="dash"),
)
)
# Update layout
fig.update_layout(
xaxis_title='Relative Humidity (%)',
yaxis_title='Count',
title='Relative Humidity Distribution',
bargap=0.2,
title_font_size=20,
xaxis_title_font_size=14,
yaxis_title_font_size=14,
height=350,
shapes=[{
'type': 'rect',
'x0': min_humidity,
'x1': max_humidity,
'y0': 0,
'y1': df['Relative Humidity (%)'].value_counts().max(),
'fillcolor': 'rgba(0, 100, 255, 0.2)',
'line': {
'color': 'rgba(0, 100, 255, 0.2)',
'width': 0
},
'opacity': 0.1
}]
)
# Add annotations
fig.add_annotation(
x=avg_humidity,
y=df['Relative Humidity (%)'].value_counts().max() * 0.9,
text=f"Average: {avg_humidity:.2f}%",
showarrow=True,
arrowhead=1
)
st.plotly_chart(fig, use_container_width=True)
# Display statistics
col_1, col_2 = st.columns([1, 1])
with col_1:
st.metric(label="Average R.Humidity (%)", value=f"{avg_humidity:.2f}")
st.metric(label="Minimum R.Humidity (%)", value=f"{min_humidity:.2f}")
with col_2:
st.metric(label="Maximum R.Humidity (%)", value=f"{max_humidity:.2f}")
st.metric(label="Std. Dev (%)", value=f"{std_humidity:.2f}")
# Function to convert humidity to color based on gradient
def humidity_to_color(humidity, min_humidity, max_humidity):
norm_humidity = (humidity - min_humidity) / (max_humidity - min_humidity)
if norm_humidity < 0.5:
r = int(173 + (0 - 173) * (2 * norm_humidity))
g = int(216 + (0 - 216) * (2 * norm_humidity))
b = int(230 + (255 - 230) * (2 * norm_humidity))
else:
r = int(0 + (0 - 0) * (2 * (norm_humidity - 0.5)))
g = int(0 + (0 - 0) * (2 * (norm_humidity - 0.5)))
b = int(255 + (0 - 255) * (2 * (norm_humidity - 0.5)))
return f'rgb({r}, {g}, {b})'
# Column 2: Map
with col2:
with st.spinner("Loading map..."):
m = folium.Map(location=[22.3547, 114.1483], zoom_start=11, tiles='CartoDB positron')
min_humidity = df['Relative Humidity (%)'].min()
max_humidity = df['Relative Humidity (%)'].max()
colormap = LinearColormap(
colors=['#58a0db', 'blue'],
index=[min_humidity, max_humidity],
vmin=min_humidity,
vmax=max_humidity,
caption='Relative Humidity (%)'
)
colormap.add_to(m)
for _, row in df.iterrows():
humidity = row['Relative Humidity (%)']
color = humidity_to_color(humidity, min_humidity, max_humidity)
folium.Marker(
location=[row['Coordinates'][1], row['Coordinates'][0]],
popup=f"<p style='font-size: 12px; background-color: white; padding: 5px; border-radius: 5px;'>{row['Station Name']}: {humidity:.1f}%</p>",
icon=folium.DivIcon(
html=f'<div style="font-size: 10pt; color: {color}; padding: 2px; border-radius: 5px;">'
f'<strong>{humidity:.1f}%</strong></div>'
)
).add_to(m)
st_folium(m, width=500, height=600)
# Column 3: Data Table
with col3:
st.markdown(
"""
<style>
.dataframe-container {
height: 600px;
overflow-y: auto;
}
.dataframe th, .dataframe td {
text-align: left;
padding: 8px;
}
</style>
""",
unsafe_allow_html=True
)
# Rename column for display
df_display = df[['Station Name', 'Relative Humidity (%)']].rename(columns={'Relative Humidity (%)': 'R.Humidity'})
st.dataframe(df_display, height=600)
# Refresh Button
if st.button("Refresh Data"):
with st.spinner("Refreshing data..."):
st.session_state.df = load_data()
st.session_state.last_run = datetime.now()
st.experimental_rerun()