Skip to content

Commit 10f8046

Browse files
committed
feat: Improve DescriptiveStatsAction to display statistics in a summary table with enhanced formatting and additional metrics
1 parent 33758f9 commit 10f8046

1 file changed

Lines changed: 26 additions & 22 deletions

File tree

dvue/actions.py

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,26 +1250,25 @@ def _on_create(evt):
12501250

12511251

12521252
class DescriptiveStatsAction(PlotAction):
1253-
"""Display per-series descriptive statistics in a Panel table.
1253+
"""Display per-series descriptive statistics in a summary table.
12541254
1255-
Computes for each selected series (after active transforms are applied):
1256-
count, first/last timestamp, min, max, mean, std, skew,
1257-
percentiles (5 / 25 / 50 / 75 / 95), and cumulative sum.
1258-
1259-
Reuses :class:`PlotAction`'s threaded callback for progress-bar and
1260-
tab management; only :meth:`render` is overridden.
1255+
Shows a Tabulator with one row per selected series containing:
1256+
count, date range (start/end), 5-number summary (min, p25, p50, p75, max),
1257+
mean, std, skew, and sum. Transforms are applied via
1258+
``_process_curve_data`` before computing statistics so the numbers match
1259+
what the user sees on the plot.
12611260
"""
12621261

12631262
def get_tab_label(self, tab_count: int) -> str:
12641263
return f"S{tab_count}"
12651264

12661265
def render(self, df, refs_and_data, manager):
12671266
rows = []
1267+
12681268
for row, ref, data in refs_and_data:
12691269
if data is None or (hasattr(data, "empty") and data.empty):
12701270
continue
12711271
try:
1272-
# Apply active transforms so stats reflect what the user sees on the plot.
12731272
time_range = getattr(manager, "time_range", None)
12741273
if hasattr(manager, "_process_curve_data"):
12751274
data = manager._process_curve_data(data, row, time_range)
@@ -1282,34 +1281,39 @@ def render(self, df, refs_and_data, manager):
12821281
rows.append({
12831282
"series": name,
12841283
"count": int(len(s)),
1285-
"start": str(s.index.min())[:19],
1286-
"end": str(s.index.max())[:19],
1287-
"min": round(float(s.min()), 6),
1288-
"max": round(float(s.max()), 6),
1289-
"mean": round(float(s.mean()), 6),
1290-
"std": round(float(s.std()), 6),
1291-
"skew": round(float(s.skew()), 6),
1292-
"p5": round(float(s.quantile(0.05)), 6),
1293-
"p25": round(float(s.quantile(0.25)), 6),
1294-
"p50": round(float(s.quantile(0.50)), 6),
1295-
"p75": round(float(s.quantile(0.75)), 6),
1296-
"p95": round(float(s.quantile(0.95)), 6),
1297-
"sum": round(float(s.sum()), 6),
1284+
"start": str(s.index.min())[:10],
1285+
"end": str(s.index.max())[:10],
1286+
"min": round(float(s.min()), 4),
1287+
"p25": round(float(s.quantile(0.25)), 4),
1288+
"p50": round(float(s.quantile(0.50)), 4),
1289+
"p75": round(float(s.quantile(0.75)), 4),
1290+
"max": round(float(s.max()), 4),
1291+
"mean": round(float(s.mean()), 4),
1292+
"std": round(float(s.std()), 4),
1293+
"skew": round(float(s.skew()), 4),
1294+
"sum": round(float(s.sum()), 4),
12981295
})
12991296
except Exception as e:
13001297
logger.warning(
13011298
"DescriptiveStatsAction: stats failed for %s: %s",
13021299
row.get("name", "?"), e,
13031300
)
1301+
13041302
if not rows:
13051303
return pn.pane.Markdown("*No data to summarise.*")
1304+
13061305
stats_df = pd.DataFrame(rows).set_index("series")
1307-
return pn.widgets.Tabulator(
1306+
1307+
table = pn.widgets.Tabulator(
13081308
stats_df,
13091309
sizing_mode="stretch_width",
1310+
layout="fit_columns",
13101311
show_index=True,
1312+
disabled=True,
1313+
theme="materialize",
13111314
header_filters=False,
13121315
)
1316+
return table
13131317

13141318

13151319
class AddSourceFilesAction:

0 commit comments

Comments
 (0)