/
Chaizee
/
ZenithCode_Incident-LLM-analytics
Обзор
Документация
Войти
/
Chaizee
/
ZenithCode_Incident-LLM-analytics
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
ui
src/ui.py
129 строк
5 KB
unknown
Вывод UI результатов в отдельный модуль
09 июн 2026, 03:10
09 июн 2026, 03:10
580712b
Код
Авторство
О чём код?
from __future__ import annotations from typing import Any import pandas as pd import plotly.express as px import streamlit as st _REQUIRED_CHART_COLUMNS = {"municipality", "problem_count", "mean_severity"} def _format_number(value: Any, digits: int = 1) -> str: try: number = float(value) except (TypeError, ValueError): return "—" if number.is_integer(): return f"{int(number):,}".replace(",", " ") return f"{number:.{digits}f}".replace(".", ",") def render_summary(text_summary: str | None) -> None: st.subheader("Справка для руководства") st.caption("Краткая выжимка по наиболее заметным проблемам и зонам внимания.") summary = (text_summary or "").strip() if not summary: st.info("Справка пока не сформирована.") return with st.container(border=True): st.markdown("**Executive summary**") st.write(summary) def render_charts(df: pd.DataFrame | None) -> None: st.subheader("Аналитика по муниципалитетам") st.caption("Сравнение количества проблемных обращений и средней тяжести по ТОП муниципалитетов.") if df is None or df.empty: st.warning("Нет данных для построения графиков.") return missing = _REQUIRED_CHART_COLUMNS.difference(df.columns) if missing: st.warning(f"Для графиков не хватает столбцов: {', '.join(sorted(missing))}.") return chart_df = df.copy() chart_df["problem_count"] = pd.to_numeric(chart_df["problem_count"], errors="coerce").fillna(0) chart_df["mean_severity"] = pd.to_numeric(chart_df["mean_severity"], errors="coerce").fillna(0) chart_df = chart_df.sort_values(["problem_count", "mean_severity"], ascending=False) total_problems = int(chart_df["problem_count"].sum()) avg_severity = chart_df["mean_severity"].mean() leader = str(chart_df.iloc[0]["municipality"]) if not chart_df.empty else "—" with st.container(border=True): col_total, col_avg, col_leader = st.columns(3) col_total.metric("Проблем в ТОП", _format_number(total_problems)) col_avg.metric("Средняя тяжесть", _format_number(avg_severity, digits=2)) col_leader.metric("Лидер по проблемам", leader) tab_count, tab_severity, tab_data = st.tabs([ "Количество проблем", "Средняя тяжесть", "Данные", ]) with tab_count: sorted_for_bar = chart_df.sort_values("problem_count", ascending=True) fig = px.bar( sorted_for_bar, x="problem_count", y="municipality", orientation="h", text="problem_count", labels={ "problem_count": "Проблемных обращений", "municipality": "Муниципалитет", "mean_severity": "Средняя тяжесть", }, hover_data={"mean_severity": ":.2f", "municipality": False}, ) fig.update_traces(textposition="outside", cliponaxis=False) fig.update_layout( height=max(360, len(chart_df) * 46), margin=dict(l=0, r=42, t=18, b=0), xaxis_title="Проблемных обращений", yaxis_title=None, showlegend=False, ) st.plotly_chart(fig, use_container_width=True) with tab_severity: sorted_for_severity = chart_df.sort_values("mean_severity", ascending=True) fig = px.bar( sorted_for_severity, x="mean_severity", y="municipality", orientation="h", text=sorted_for_severity["mean_severity"].round(2), labels={ "mean_severity": "Средняя тяжесть", "municipality": "Муниципалитет", "problem_count": "Проблемных обращений", }, hover_data={"problem_count": True, "municipality": False}, ) fig.update_traces(textposition="outside", cliponaxis=False) fig.update_layout( height=max(360, len(chart_df) * 46), margin=dict(l=0, r=42, t=18, b=0), xaxis_title="Средняя тяжесть", yaxis_title=None, showlegend=False, ) st.plotly_chart(fig, use_container_width=True) with tab_data: display_df = chart_df.rename( columns={ "municipality": "Муниципалитет", "problem_count": "Проблемных обращений", "mean_severity": "Средняя тяжесть", } ) st.dataframe(display_df, use_container_width=True, hide_index=True)