Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ def main() -> None:
st.page_link("pages/data_explorer.py", label="Data Explorer", icon="📊")
st.page_link("pages/modeling.py", label="Modeling", icon="🧠")
st.page_link("pages/prediction.py", label="Prediction", icon="🔮")
st.page_link("pages/time_series.py", label="Time Series", icon="📈")
st.page_link("pages/report.py", label="Report", icon="📄")


Expand Down
4 changes: 4 additions & 0 deletions pages/data_explorer.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ def main() -> None:
st.session_state["data"] = data_utils.convert_dtypes(
st.session_state["data"]
)
st.session_state["datetime_cols"] = eda.detect_datetime_columns(
st.session_state["data"]
)
st.success(f"{name} loaded!")

with st.expander("Help"):
Expand All @@ -59,6 +62,7 @@ def main() -> None:
df = data_utils.load_data(uploaded_file)
df = data_utils.convert_dtypes(df)
st.session_state["data"] = df
st.session_state["datetime_cols"] = eda.detect_datetime_columns(df)
st.success("File loaded successfully!")
except ValueError as exc:
st.error(f"Failed to load file: {exc}")
Expand Down
67 changes: 67 additions & 0 deletions pages/time_series.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from __future__ import annotations

from pathlib import Path
import tempfile

import pandas as pd
import streamlit as st

from utils import ui, viz

st.set_page_config(page_title="Time Series", layout="wide")


def main() -> None:
"""Render the time series analysis page."""
ui.apply_branding()
st.title("Time Series Analysis")

df = st.session_state.get("data")
if df is None or df.empty:
st.info("No dataset available. Load data on the Data Explorer page.")
return

datetime_cols = st.session_state.get("datetime_cols") or []
if not datetime_cols:
st.info("No datetime columns detected in the dataset.")
return

with st.sidebar:
time_col = st.selectbox("Datetime Column", datetime_cols, key="ts_time")
numeric_cols = df.select_dtypes(include="number").columns.tolist()
value_col = st.selectbox("Value Column", numeric_cols, key="ts_value")
export_fmt = st.selectbox("Export Format", ["png", "jpg"], key="ts_fmt")
period = st.number_input(
"Seasonal Period", min_value=2, value=2, step=1, key="ts_period"
)

if st.button("Generate Plots"):
ts_fig = viz.time_series_plot(df, time_col, value_col, title="Time Series")
st.plotly_chart(ts_fig, use_container_width=True)
with tempfile.NamedTemporaryFile(suffix=f".{export_fmt}") as tmp:
viz.export_figure(ts_fig, Path(tmp.name))
tmp.seek(0)
st.download_button(
"Download Time Series",
data=tmp.read(),
file_name=f"time_series.{export_fmt}",
mime=f"image/{export_fmt}",
)

dec_fig = viz.decomposition_plot(
df.set_index(time_col)[value_col], period=period, title="Decomposition"
)
st.pyplot(dec_fig)
with tempfile.NamedTemporaryFile(suffix=f".{export_fmt}") as tmp:
viz.export_figure(dec_fig, Path(tmp.name))
tmp.seek(0)
st.download_button(
"Download Decomposition",
data=tmp.read(),
file_name=f"decomposition.{export_fmt}",
mime=f"image/{export_fmt}",
)


if __name__ == "__main__":
main()
25 changes: 25 additions & 0 deletions tests/test_pages.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"pages.modeling",
"pages.prediction",
"pages.report",
"pages.time_series",
]

@pytest.mark.parametrize("mod_name", PAGES)
Expand Down Expand Up @@ -65,3 +66,27 @@ def test_modeling_page_widgets_exist():
assert "Train Models" in content
assert "export_model" in content


def test_time_series_page_runs(monkeypatch):
import streamlit as st
from pages import time_series

df = pd.DataFrame(
{
"date": pd.date_range("2021-01-01", periods=5, freq="D"),
"value": range(5),
}
)
st.session_state.clear()
st.session_state["data"] = df
st.session_state["datetime_cols"] = ["date"]
monkeypatch.setattr(time_series.ui, "apply_branding", lambda: None)
time_series.main()


def test_time_series_page_contents():
with open("pages/time_series.py", "r", encoding="utf-8") as f:
content = f.read()
assert "time_series_plot" in content
assert "decomposition_plot" in content