Update app.py
Browse files
app.py
CHANGED
@@ -1,67 +1,108 @@
|
|
1 |
import gradio as gr
|
2 |
import pandas as pd
|
|
|
3 |
|
4 |
# Ссылки на CSV-файлы
|
5 |
URL_DASHA = "https://raw.githubusercontent.com/fruitpicker01/Storage_Dasha_2025/main/messages.csv"
|
6 |
URL_LERA = "https://raw.githubusercontent.com/fruitpicker01/Storage_Lera_2025/main/messages.csv"
|
7 |
URL_SVETA = "https://raw.githubusercontent.com/fruitpicker01/Storage_Sveta_2025/main/messages.csv"
|
8 |
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
#
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
|
|
|
|
28 |
|
29 |
-
#
|
30 |
-
|
31 |
-
|
32 |
-
|
|
|
|
|
|
|
33 |
|
34 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
total_count = dasha_count + lera_count + sveta_count
|
36 |
-
|
37 |
-
#
|
38 |
-
#
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
|
43 |
-
|
44 |
-
|
45 |
-
|
46 |
-
# Формируем
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
56 |
|
57 |
# Создаём интерфейс Gradio
|
58 |
with gr.Blocks() as demo:
|
59 |
-
gr.Markdown("<h2>Подсчёт уникальных
|
60 |
btn = gr.Button("Обновить данные и показать результат")
|
61 |
-
|
|
|
62 |
|
63 |
-
btn.click(fn=process_data, outputs=
|
64 |
|
65 |
-
# Запуск приложения (автоматически в Spaces он обычно дергает demo.launch())
|
66 |
if __name__ == "__main__":
|
67 |
demo.launch()
|
|
|
1 |
import gradio as gr
|
2 |
import pandas as pd
|
3 |
+
import plotly.express as px
|
4 |
|
5 |
# Ссылки на CSV-файлы
|
6 |
URL_DASHA = "https://raw.githubusercontent.com/fruitpicker01/Storage_Dasha_2025/main/messages.csv"
|
7 |
URL_LERA = "https://raw.githubusercontent.com/fruitpicker01/Storage_Lera_2025/main/messages.csv"
|
8 |
URL_SVETA = "https://raw.githubusercontent.com/fruitpicker01/Storage_Sveta_2025/main/messages.csv"
|
9 |
|
10 |
+
# Функция для чтения данных, подсчёта уникальных SMS и подготовки данных для графиков
|
11 |
+
def read_and_process_data(url, user_name):
|
12 |
+
df = pd.read_csv(url, na_values=["Не выбрано"])
|
13 |
+
|
14 |
+
# Оставляем только нужные столбцы (если какие-то отсутствуют — пропускаем аккуратно)
|
15 |
+
cols = ["gender", "generation", "industry", "opf", "timestamp"]
|
16 |
+
df = df[[col for col in cols if col in df.columns]].copy()
|
17 |
+
|
18 |
+
# Убираем дубликаты по gender, generation, industry, opf
|
19 |
+
df_unique = df.drop_duplicates(subset=["gender", "generation", "industry", "opf"])
|
20 |
+
|
21 |
+
# Считаем абсолютное количество уникальных SMS
|
22 |
+
unique_count = len(df_unique)
|
23 |
+
|
24 |
+
# Готовим столбец date
|
25 |
+
if "timestamp" in df_unique.columns:
|
26 |
+
# Переводим timestamp в datetime
|
27 |
+
df_unique["timestamp"] = pd.to_numeric(df_unique["timestamp"], errors='coerce')
|
28 |
+
df_unique["date"] = pd.to_datetime(df_unique["timestamp"], unit="s", origin="unix", errors='coerce').dt.date
|
29 |
+
else:
|
30 |
+
df_unique["date"] = pd.NaT
|
31 |
|
32 |
+
# Группируем по дате, считаем, сколько уникальных SMS приходится на каждую дату
|
33 |
+
# (снова нужно учесть комбинацию gender, generation, industry, opf)
|
34 |
+
# Но т.к. мы уже отфильтровали уникальные, достаточно просто groupby date
|
35 |
+
df_daily = df_unique.groupby("date").size().reset_index(name="count")
|
36 |
+
df_daily["user"] = user_name # чтобы потом можно было объединить данные для всех
|
37 |
+
|
38 |
+
return unique_count, df_daily
|
39 |
|
40 |
+
def process_data():
|
41 |
+
# Считываем и обрабатываем все три репозитория
|
42 |
+
dasha_count, dasha_daily = read_and_process_data(URL_DASHA, "Даша")
|
43 |
+
lera_count, lera_daily = read_and_process_data(URL_LERA, "Лера")
|
44 |
+
sveta_count, sveta_daily = read_and_process_data(URL_SVETA, "Света")
|
45 |
+
|
46 |
+
# Суммарные значения
|
47 |
total_count = dasha_count + lera_count + sveta_count
|
48 |
+
|
49 |
+
# Считаем % (округлим до целого)
|
50 |
+
# Каждое хранилище: процент относительно 117
|
51 |
+
dasha_percent = round((dasha_count / 117) * 100) if 117 else 0
|
52 |
+
lera_percent = round((lera_count / 117) * 100) if 117 else 0
|
53 |
+
sveta_percent = round((sveta_count / 117) * 100) if 117 else 0
|
54 |
+
|
55 |
+
# Суммарный % от 702
|
56 |
+
total_percent = round((total_count / 702) * 100) if 702 else 0
|
57 |
+
|
58 |
+
# Формируем HTML с "прогресс-барами"
|
59 |
+
# Простейшая полоска: ширина = процент, внутри пишем "X SMS (Y%)"
|
60 |
+
def get_progress_bar(label, abs_val, pct):
|
61 |
+
return f"""
|
62 |
+
<div style='margin-bottom: 1em;'>
|
63 |
+
<div><strong>{label}</strong></div>
|
64 |
+
<div style='width: 100%; background-color: #ddd; text-align: left;'>
|
65 |
+
<div style='width: {pct}%; background-color: #4CAF50; padding: 5px 0;'>
|
66 |
+
{abs_val} SMS ({pct}%)
|
67 |
+
</div>
|
68 |
+
</div>
|
69 |
+
</div>
|
70 |
+
"""
|
71 |
+
|
72 |
+
bars_html = (
|
73 |
+
get_progress_bar("Даша", dasha_count, dasha_percent) +
|
74 |
+
get_progress_bar("Лера", lera_count, lera_percent) +
|
75 |
+
get_progress_bar("Света", sveta_count, sveta_percent) +
|
76 |
+
get_progress_bar("Всего", total_count, total_percent)
|
77 |
+
)
|
78 |
+
|
79 |
+
# Делаем один общий DataFrame для построения графика:
|
80 |
+
daily_all = pd.concat([dasha_daily, lera_daily, sveta_daily], ignore_index=True)
|
81 |
+
# Уберём строки, где date может быть NaT (если timestamp некорректный)
|
82 |
+
daily_all = daily_all.dropna(subset=["date"])
|
83 |
+
|
84 |
+
# Построим столбчатую диаграмму, показывающую, кто в какой день сколько сохранил SMS
|
85 |
+
# (уникальных по комбинации gender, generation, industry, opf)
|
86 |
+
fig = px.bar(
|
87 |
+
daily_all,
|
88 |
+
x="date",
|
89 |
+
y="count",
|
90 |
+
color="user",
|
91 |
+
title="Количество уникальных SMS по датам",
|
92 |
+
labels={"date": "Дата", "count": "Количество SMS", "user": "Пользователь"},
|
93 |
+
barmode="group"
|
94 |
+
)
|
95 |
+
|
96 |
+
return bars_html, fig
|
97 |
|
98 |
# Создаём интерфейс Gradio
|
99 |
with gr.Blocks() as demo:
|
100 |
+
gr.Markdown("<h2>Подсчёт уникальных SMS для Даши, Леры и Светы</h2>")
|
101 |
btn = gr.Button("Обновить данные и показать результат")
|
102 |
+
html_output = gr.HTML(label="Прогресс-бары (Количество SMS и %)")
|
103 |
+
plot_output = gr.Plot(label="График количества уникальных SMS по датам")
|
104 |
|
105 |
+
btn.click(fn=process_data, outputs=[html_output, plot_output])
|
106 |
|
|
|
107 |
if __name__ == "__main__":
|
108 |
demo.launch()
|