71803418e5
Shelly device management app with mDNS/subnet discovery, inventory, configuration, and mass operations for Gen1/Gen2+ devices. Includes .gitignore excluding runtime data (device DB, user config), AI conversation history, build artifacts, and common Python/OS patterns.
253 lines
6.4 KiB
Python
253 lines
6.4 KiB
Python
import streamlit as st
|
|
import altair as alt
|
|
import vega_datasets
|
|
|
|
|
|
full_df = vega_datasets.data("seattle_weather")
|
|
|
|
st.set_page_config(
|
|
# Title and icon for the browser's tab bar:
|
|
page_title="Seattle Weather",
|
|
page_icon=":mostly_sunny:",
|
|
# Make the content take up the width of the page:
|
|
layout="wide",
|
|
)
|
|
|
|
|
|
"""
|
|
# Seattle Weather
|
|
|
|
Let's explore the [classic Seattle Weather
|
|
dataset](https://altair-viz.github.io/case_studies/exploring-weather.html)!
|
|
"""
|
|
|
|
"" # Add a little vertical space. Same as st.write("").
|
|
""
|
|
|
|
"""
|
|
## 2015 Summary
|
|
"""
|
|
|
|
""
|
|
|
|
df_2015 = full_df[full_df["date"].dt.year == 2015]
|
|
df_2014 = full_df[full_df["date"].dt.year == 2014]
|
|
|
|
max_temp_2015 = df_2015["temp_max"].max()
|
|
max_temp_2014 = df_2014["temp_max"].max()
|
|
|
|
min_temp_2015 = df_2015["temp_min"].min()
|
|
min_temp_2014 = df_2014["temp_min"].min()
|
|
|
|
max_wind_2015 = df_2015["wind"].max()
|
|
max_wind_2014 = df_2014["wind"].max()
|
|
|
|
min_wind_2015 = df_2015["wind"].min()
|
|
min_wind_2014 = df_2014["wind"].min()
|
|
|
|
max_prec_2015 = df_2015["precipitation"].max()
|
|
max_prec_2014 = df_2014["precipitation"].max()
|
|
|
|
min_prec_2015 = df_2015["precipitation"].min()
|
|
min_prec_2014 = df_2014["precipitation"].min()
|
|
|
|
|
|
with st.container(horizontal=True, gap="medium"):
|
|
cols = st.columns(2, gap="medium", width=300)
|
|
|
|
with cols[0]:
|
|
st.metric(
|
|
"Max temperature",
|
|
f"{max_temp_2015:0.1f}C",
|
|
delta=f"{max_temp_2015 - max_temp_2014:0.1f}C",
|
|
width="content",
|
|
)
|
|
|
|
with cols[1]:
|
|
st.metric(
|
|
"Min temperature",
|
|
f"{min_temp_2015:0.1f}C",
|
|
delta=f"{min_temp_2015 - min_temp_2014:0.1f}C",
|
|
width="content",
|
|
)
|
|
|
|
cols = st.columns(2, gap="medium", width=300)
|
|
|
|
with cols[0]:
|
|
st.metric(
|
|
"Max precipitation",
|
|
f"{max_prec_2015:0.1f}mm",
|
|
delta=f"{max_prec_2015 - max_prec_2014:0.1f}mm",
|
|
width="content",
|
|
)
|
|
|
|
with cols[1]:
|
|
st.metric(
|
|
"Min precipitation",
|
|
f"{min_prec_2015:0.1f}mm",
|
|
delta=f"{min_prec_2015 - min_prec_2014:0.1f}mm",
|
|
width="content",
|
|
)
|
|
|
|
cols = st.columns(2, gap="medium", width=300)
|
|
|
|
with cols[0]:
|
|
st.metric(
|
|
"Max wind",
|
|
f"{max_wind_2015:0.1f}m/s",
|
|
delta=f"{max_wind_2015 - max_wind_2014:0.1f}m/s",
|
|
width="content",
|
|
)
|
|
|
|
with cols[1]:
|
|
st.metric(
|
|
"Min wind",
|
|
f"{min_wind_2015:0.1f}m/s",
|
|
delta=f"{min_wind_2015 - min_wind_2014:0.1f}m/s",
|
|
width="content",
|
|
)
|
|
|
|
weather_icons = {
|
|
"sun": "sunny",
|
|
"snow": "weather_snowy",
|
|
"rain": "rainy",
|
|
"fog": "foggy",
|
|
"drizzle": "rainy",
|
|
}
|
|
|
|
cols = st.columns(2, gap="large")
|
|
|
|
with cols[0]:
|
|
weather_name = (
|
|
full_df["weather"].value_counts().head(1).reset_index()["weather"][0]
|
|
)
|
|
st.metric(
|
|
"Most common weather",
|
|
f":material/{weather_icons[weather_name]}: {weather_name.upper()}",
|
|
)
|
|
|
|
with cols[1]:
|
|
weather_name = (
|
|
full_df["weather"].value_counts().tail(1).reset_index()["weather"][0]
|
|
)
|
|
st.metric(
|
|
"Least common weather",
|
|
f":material/{weather_icons[weather_name]}: {weather_name.upper()}",
|
|
)
|
|
|
|
""
|
|
""
|
|
|
|
"""
|
|
## Compare different years
|
|
"""
|
|
|
|
YEARS = full_df["date"].dt.year.unique()
|
|
selected_years = st.pills(
|
|
"Years to compare", YEARS, default=YEARS, selection_mode="multi"
|
|
)
|
|
|
|
if not selected_years:
|
|
st.warning("You must select at least 1 year.", icon=":material/warning:")
|
|
|
|
df = full_df[full_df["date"].dt.year.isin(selected_years)]
|
|
|
|
cols = st.columns([3, 1])
|
|
|
|
with cols[0].container(border=True, height="stretch"):
|
|
"### 🌡️ Temperature"
|
|
|
|
st.altair_chart(
|
|
alt.Chart(df)
|
|
.mark_bar(width=1)
|
|
.encode(
|
|
alt.X("monthdate(date):T").title("date"),
|
|
alt.Y("temp_max:Q").title("temperature range (C)"),
|
|
alt.Y2("temp_min:Q"),
|
|
alt.Color("year(date):N").title("year"),
|
|
alt.XOffset("year(date):N"),
|
|
tooltip=[
|
|
alt.Tooltip("monthdate(date):T", title="Date"),
|
|
alt.Tooltip("temp_max:Q", title="Max Temp (C)"),
|
|
alt.Tooltip("temp_min:Q", title="Min Temp (C)"),
|
|
alt.Tooltip("year(date):N", title="Year"),
|
|
],
|
|
)
|
|
.configure_legend(orient="bottom")
|
|
)
|
|
|
|
with cols[1].container(border=True, height="stretch"):
|
|
"### Weather distribution"
|
|
|
|
st.altair_chart(
|
|
alt.Chart(df)
|
|
.mark_arc()
|
|
.encode(
|
|
alt.Theta("count()"),
|
|
alt.Color("weather:N"),
|
|
)
|
|
.configure_legend(orient="bottom")
|
|
)
|
|
|
|
|
|
cols = st.columns(2)
|
|
|
|
with cols[0].container(border=True, height="stretch"):
|
|
"### 💨 Wind"
|
|
|
|
# Prepare data for st.line_chart - pivot by year
|
|
wind_df = df.copy()
|
|
wind_df["month_day"] = wind_df["date"].dt.strftime("%m-%d")
|
|
wind_df["year"] = wind_df["date"].dt.year
|
|
|
|
# Calculate 14-day rolling average per year
|
|
wind_pivot = wind_df.pivot_table(
|
|
index="month_day",
|
|
columns="year",
|
|
values="wind",
|
|
aggfunc="mean"
|
|
).sort_index()
|
|
|
|
st.line_chart(wind_pivot, height=300)
|
|
|
|
with cols[1].container(border=True, height="stretch"):
|
|
"### 🌧️ Precipitation"
|
|
|
|
st.altair_chart(
|
|
alt.Chart(df)
|
|
.mark_bar()
|
|
.encode(
|
|
alt.X("month(date):O").title("month"),
|
|
alt.Y("sum(precipitation):Q").title("precipitation (mm)"),
|
|
alt.Color("year(date):N").title("year"),
|
|
tooltip=[
|
|
alt.Tooltip("month(date):O", title="Month"),
|
|
alt.Tooltip("sum(precipitation):Q", title="Precipitation (mm)"),
|
|
alt.Tooltip("year(date):N", title="Year"),
|
|
],
|
|
)
|
|
.configure_legend(orient="bottom")
|
|
)
|
|
|
|
cols = st.columns(2)
|
|
|
|
with cols[0].container(border=True, height="stretch"):
|
|
"### Monthly weather breakdown"
|
|
""
|
|
|
|
st.altair_chart(
|
|
alt.Chart(df)
|
|
.mark_bar()
|
|
.encode(
|
|
alt.X("month(date):O", title="month"),
|
|
alt.Y("count():Q", title="days").stack("normalize"),
|
|
alt.Color("weather:N"),
|
|
)
|
|
.configure_legend(orient="bottom")
|
|
)
|
|
|
|
with cols[1].container(border=True, height="stretch"):
|
|
"### Raw data"
|
|
|
|
st.dataframe(df)
|