previous is good
Browse files
app.py
CHANGED
|
@@ -88,7 +88,6 @@ def get_data():
|
|
| 88 |
df["created_at"] = pd.to_datetime(df["created_at"])
|
| 89 |
|
| 90 |
# 2. FIX: Remove Timezone Information (Make it Naive)
|
| 91 |
-
# This solves the "Invalid comparison between Europe/Paris and Timestamp" error
|
| 92 |
if pd.api.types.is_datetime64_any_dtype(df["created_at"]):
|
| 93 |
if df["created_at"].dt.tz is not None:
|
| 94 |
df["created_at"] = df["created_at"].dt.tz_localize(None)
|
|
@@ -175,7 +174,26 @@ if not entities:
|
|
| 175 |
|
| 176 |
# --- Continue only if data exists ---
|
| 177 |
if not filtered_df.empty:
|
| 178 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 179 |
|
| 180 |
if group_by_score_type:
|
| 181 |
score_cols = ["entity_score", "title_score", "overall_score"]
|
|
@@ -235,7 +253,6 @@ if not filtered_df.empty:
|
|
| 235 |
labels={"date": "Date", "score": "Score", "label": "Legend"},
|
| 236 |
title=T[LANG]["scores_over_time"]
|
| 237 |
)
|
| 238 |
-
# FIX: Ensure markers are shown even for single/few data points
|
| 239 |
fig.update_traces(mode="lines+markers")
|
| 240 |
|
| 241 |
else:
|
|
@@ -285,7 +302,6 @@ if not filtered_df.empty:
|
|
| 285 |
labels={"date": "Date", score_type: "Score", "label": "Legend"},
|
| 286 |
title=T[LANG]["avg_over_time"].format(score_type.replace("_", " ").title())
|
| 287 |
)
|
| 288 |
-
# FIX: Ensure markers are shown even for single/few data points
|
| 289 |
fig.update_traces(mode="lines+markers")
|
| 290 |
|
| 291 |
# Grid lines at every integer, thicker at -5 and 5
|
|
|
|
| 88 |
df["created_at"] = pd.to_datetime(df["created_at"])
|
| 89 |
|
| 90 |
# 2. FIX: Remove Timezone Information (Make it Naive)
|
|
|
|
| 91 |
if pd.api.types.is_datetime64_any_dtype(df["created_at"]):
|
| 92 |
if df["created_at"].dt.tz is not None:
|
| 93 |
df["created_at"] = df["created_at"].dt.tz_localize(None)
|
|
|
|
| 174 |
|
| 175 |
# --- Continue only if data exists ---
|
| 176 |
if not filtered_df.empty:
|
| 177 |
+
|
| 178 |
+
# --- START: Smart Date Binning Logic (Max ~20 Dots) ---
|
| 179 |
+
min_date = filtered_df["created_at"].min()
|
| 180 |
+
max_date = filtered_df["created_at"].max()
|
| 181 |
+
|
| 182 |
+
# Calculate total days in the range
|
| 183 |
+
days_span = (max_date - min_date).days + 1
|
| 184 |
+
|
| 185 |
+
if days_span <= 20:
|
| 186 |
+
# If range is small, use Daily
|
| 187 |
+
freq = "D"
|
| 188 |
+
else:
|
| 189 |
+
# If range is large, calculate step size to result in ~20 dots
|
| 190 |
+
# e.g., 60 days / 20 = 3 days per dot -> freq="3D"
|
| 191 |
+
step = int(days_span / 20)
|
| 192 |
+
step = max(1, step) # Ensure at least 1
|
| 193 |
+
freq = f"{step}D"
|
| 194 |
+
|
| 195 |
+
filtered_df["date"] = filtered_df["created_at"].dt.floor(freq)
|
| 196 |
+
# --- END: Smart Date Binning Logic ---
|
| 197 |
|
| 198 |
if group_by_score_type:
|
| 199 |
score_cols = ["entity_score", "title_score", "overall_score"]
|
|
|
|
| 253 |
labels={"date": "Date", "score": "Score", "label": "Legend"},
|
| 254 |
title=T[LANG]["scores_over_time"]
|
| 255 |
)
|
|
|
|
| 256 |
fig.update_traces(mode="lines+markers")
|
| 257 |
|
| 258 |
else:
|
|
|
|
| 302 |
labels={"date": "Date", score_type: "Score", "label": "Legend"},
|
| 303 |
title=T[LANG]["avg_over_time"].format(score_type.replace("_", " ").title())
|
| 304 |
)
|
|
|
|
| 305 |
fig.update_traces(mode="lines+markers")
|
| 306 |
|
| 307 |
# Grid lines at every integer, thicker at -5 and 5
|