Skip to content

fix(pivot-table): blank a total that collapses mixed metrics, not sum or pick one - #44730

Open
itzzdev09 wants to merge 5 commits into
apache:masterfrom
itzzdev09:fix/pivot-blank-mixed-metric-total
Open

itzzdev09 wants to merge 5 commits into
apache:masterfrom
itzzdev09:fix/pivot-blank-mixed-metric-total

Conversation

@itzzdev09

@itzzdev09 itzzdev09 commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #44725.

Depends on #44657. Hold this until the browser fix lands: on master today the chart still fills the mixed-metric Total cells on the GROUPING SETS path, so merging this first would make exports blank cells that Explore still shows. Once #44657 is in, both paths agree.

_collapsed_metric picked the last configured metric for any rollup spanning 2+ distinct metrics on the collapsed "Total" pseudo-dimension, so the report/export path (scheduled report, CSV/Excel export) could show a specific, plausible-looking value for a cell that actually mixes e.g. MAX(sales) with MEDIAN(msrp). #44657 changes the interactive chart to blank that cell instead, since combining metrics that share no unit has no single meaningful value. This brings the export/report path in line with it.

Changes:

  • _collapsed_metric now returns None when its input spans more than one distinct metric, instead of tie-breaking via reversed(metrics).
  • pivot_df's collapse() propagates that as a genuinely blank total (previously fell back to summing across every metric when the picked metric was None).
  • Every row total runs through collapse(), in Actual Values mode as in the percent modes. The additive path (all metrics SUM/COUNT/MIN/MAX, so no GROUPING SETS requested) used to reduce the leaf cells across metrics there, exporting e.g. 14 / 26 / 40 for a SUM + MAX pivot. The blanked columns are re-blanked after the column-totals pass, which would otherwise sum a column of blanks to 0 in the grand-total corner. The currency-context pass keeps its unions.
  • _reduce's sum now passes min_count=1 so a rollup of nothing but blanks stays blank, rather than pandas defaulting an all-NaN sum to 0. This matches synthesizeAdditiveLevels in the chart, which returns null for an all-empty group, and is a small user-visible change on its own: a single-metric total over all-NULL cells now exports blank instead of 0.
  • Both rollup consumers (_apply_rollup_totals, _rollup_denominators) take the metric names as a set built once per call instead of a list lookup per cell.

Tests: test_pivot_table_v2_blanks_every_mixed_metric_total covers Actual Values and all three percent modes, both metric layouts (COLUMNS and ROWS, where the mixed cells are the bottom Total row), with and without database rollups; the two Actual Values additive cases fail without the fix. test_pivot_df_show_values_as_blanks_mixed_metric_grand_total covers the grand-total corner from the issue's repro, and test_pivot_df_show_values_as_keeps_metrics_separate was updated (its old assertion documented the exact pre-#44657 behavior). Existing two-metric snapshots change only in the mixed Total/Subtotal cells. tests/unit_tests/charts/: 373 passed, 2 xfailed.

Not in scope (noted in review, separate issue): on the additive path in Actual Values mode a single MAX metric's total is still the sum of the maxima rather than the maximum.

… or pick one

_collapsed_metric picked the last configured metric for any rollup
spanning 2+ distinct metrics on the collapsed 'Total' pseudo-dimension,
so the report/export path could show a specific, plausible-looking
percentage for a cell that mixes e.g. MAX(sales) with MEDIAN(msrp).
apache#44657 already changed the interactive chart to blank that cell, since
combining metrics that share no unit has no single meaningful value;
this brings the export/report path in line with it.

- _collapsed_metric now returns None on a mixed present, instead of
  reversed(metrics)'s tie-break.
- pivot_df's collapse() propagates that as a genuinely blank total
  (was: falling back to summing across every metric).
- _reduce's sum uses min_count=1 so a rollup of nothing but blanks
  stays blank, rather than pandas defaulting an all-NaN sum to 0.

Fixes apache#44725.
@codecov

codecov Bot commented Sep 27, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.60%. Comparing base (19bb094) to head (b32c47e).
⚠️ Report is 202 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master   #44730      +/-   ##
==========================================
- Coverage   83.49%   82.60%   -0.90%     
==========================================
  Files        3047     3018      -29     
  Lines      199523   195691    -3832     
  Branches    46554    44858    -1696     
==========================================
- Hits       166597   161648    -4949     
- Misses      29699    30819    +1120     
+ Partials     3227     3224       -3     
Flag Coverage Δ
hive 34.97% <12.00%> (-0.01%) ⬇️
mysql 52.92% <12.00%> (-0.01%) ⬇️
postgres 52.93% <12.00%> (-0.01%) ⬇️
presto 36.72% <12.00%> (-0.01%) ⬇️
python 87.01% <100.00%> (+<0.01%) ⬆️
sqlite 52.69% <12.00%> (-0.01%) ⬇️
unit 81.06% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@bito-code-review bito-code-review Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review Agent Run #68b9b7

Actionable Suggestions - 1
  • superset/charts/client_processing.py - 1
Additional Suggestions - 1
  • tests/unit_tests/charts/test_client_processing.py - 1
    • duplicated test setup · Line 1915-1934
      The new test duplicates the setup and blanking assertion of `test_pivot_df_show_values_as_keeps_metrics_separate` (same `MAX(num)` df, same 2-metric pivot, same `pd.isna` on the mixed-metric total). It only adds `percent_total` mode and the grand-total-row cell. A shared helper or a merge would keep the two from diverging and masking a regression.
Review Details
  • Files reviewed - 2 · Commit Range: e9ab69e..e9ab69e
    • superset/charts/client_processing.py
    • tests/unit_tests/charts/test_client_processing.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

Comment thread superset/charts/client_processing.py Outdated
_apply_rollup_totals and _rollup_denominators each defined the same
metric_of closure; replace both with a module-level _rollup_metric.
@pull-request-size pull-request-size Bot added size/L and removed size/M labels Sep 29, 2026
@netlify

netlify Bot commented Sep 29, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for superset-docs-preview ready!

Name Link
🔨 Latest commit b6ec96f
🔍 Latest deploy log https://app.netlify.com/projects/superset-docs-preview/deploys/6abc4a728f36240008392dc1
😎 Deploy Preview https://deploy-preview-44730--superset-docs-preview.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@bito-code-review

bito-code-review Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Code Review Agent Run #99890b

Actionable Suggestions - 0
Additional Suggestions - 1
  • superset/charts/client_processing.py - 1
    • perf regression set->list · Line 201-201
      The removed closure built `metric_names = set(metrics)` once and used O(1) membership; `_rollup_metric` now does `name in metrics` on a list, an O(n) scan per call. It runs per cell in the nested row×column loops of `_apply_rollup_totals`/`_rollup_denominators`, so the set optimization is silently lost. Pass a precomputed `set(metrics)` to keep it O(1).
Review Details
  • Files reviewed - 1 · Commit Range: e9ab69e..a35d176
    • superset/charts/client_processing.py
  • Files skipped - 0
  • Tools
    • MyPy (Static Code Analysis) - ✔︎ Successful
    • Astral Ruff (Static Code Analysis) - ✔︎ Successful
    • Whispers (Secret Scanner) - ✔︎ Successful
    • Detect-secrets (Secret Scanner) - ✔︎ Successful

Bito Usage Guide

Commands

Type the following command in the pull request comment and save the comment.

  • /review - Manually triggers an incremental AI Review.

  • /review full - Manually triggers a full AI Review.

  • /pause - Pauses automatic reviews on this pull request.

  • /resume - Resumes automatic reviews.

  • /resolve - Marks all Bito-posted review comments as resolved.

  • /abort - Cancels all in-progress reviews.

Refer to the documentation for additional commands.

Configuration

This repository uses Superset You can customize the agent settings here or contact your Bito workspace admin at evan@preset.io.

Documentation & Help

AI Code Review powered by Bito Logo

@fitzee

fitzee commented Sep 29, 2026

Copy link
Copy Markdown
Contributor

Review notes, full context in #44725 (comment). I checked this diff against master @ 9a5faa8 by running pivot_df directly: rows=country, cols=gender, metrics=SUM(num), MAX(num), both totals on.

Must fix before merge

  1. The branch is stale and CI ran against old code. The base is 81 commits behind and predates fix: use database rollups for pivot table subtotals in Actual Values mode #44631. pivot_df here still gates on if percent_mode and rollup_levels:, but master now also runs _apply_rollup_totals in Actual Values mode. The diff does apply cleanly to master, and rebased it behaves correctly on the GROUPING SETS path: the mixed Total/corner blanks in Actual Values and in all three percent modes. The passing checks on this PR don't show that, though, so please rebase and re-run.
  2. It has to merge after fix(pivot-table): stop the grand-total corner from silently picking one metric #44657. fix(pivot-table): stop the grand-total corner from silently picking one metric #44657 is still open. On master the browser still keeps the last configured metric, so browser and export currently agree on the GROUPING SETS path. Merging this first would make exports blank cells that Explore still fills in. Please call out that dependency in the description, or hold this PR until fix(pivot-table): stop the grand-total corner from silently picking one metric #44657 lands.
  3. It doesn't cover the additive path (all metrics SUM/COUNT/MIN/MAX, so no grouping_sets) in Actual Values mode. rollup_levels is empty there. The Total column comes from pivot_v2_aggfunc_map[aggfunc](block, axis=1) over every metric column, and nothing overwrites it. With this PR rebased onto master, the export still shows 14 / 26 / 40 (SUM + MAX added together), while the browser shows 3 / 10 / 10 today and would blank it after fix(pivot-table): stop the grand-total corner from silently picking one metric #44657. The percent-mode cells on this path do blank correctly with your change; before it, the grand-total corner read 130%. The fix is to run the non-percent show_rows_total branch through collapse() as well, and blank when it returns None.

Tests

  • Both new assertions only cover percent modes, on the no-rollups fixture. Please add:
    • Actual Values mode with rollup_levels (the _apply_rollup_totals → record.get(None) path).
    • Actual Values mode without rollups (point 3).
    • metricsLayout: ROWS, where the mixed cells become the bottom Total row rather than the right-hand column.

Minor

  • _reduce's min_count=1 matches synthesizeAdditiveLevels, which returns null for an all-empty group. That's a real parity improvement; worth mentioning in the description, since it also changes single-metric all-NaN totals from 0 to blank.
  • _rollup_metric does a name in metrics list lookup per cell inside the row × column loops. Pass set(metrics) as the old closure did (Bito flagged this too).
  • Unrelated to this diff but found on the same path: Actual Values mode on the additive path totals a single MAX metric as the sum of maxes (4 / 16 / 20 vs. the browser's 3 / 10 / 10). Totals only follow metric_rollup_reducers in percent mode. That should be a separate issue, not scope for this PR.

Verdict: Needs changes. Items 1–3.

@rusackas

rusackas commented Sep 29, 2026 •

Copy link
Copy Markdown
Member

Updated the branch. That takes care of #1 for @fitzee :) @itzzdev09 let me/us know if you can tackle #2 and #3... or if you'd like me to take a stab at it.

@fitzee

fitzee commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

@rusackas you good to take a stab at #2 and #3? :)

@itzzdev09

Copy link
Copy Markdown
Contributor Author

@rusackas hey, sorry.... currently have a lot on my plate. Please go ahead, u guys can have it for sure.

@fitzee

fitzee commented Oct 15, 2026

Copy link
Copy Markdown
Contributor

Continued this in #45311 after the author's handoff, preserving the original commits. I cannot push to this fork from my account.

The continuation updates to current master, fixes Actual Values without GROUPING SETS (including the grand-total corner), restores set-based metric lookup, and covers both layouts across all four value modes and both data paths. Charts unit tests: 374 passed, 2 xfailed; changed-file pre-commit checks pass. The two missing Actual Values cases fail against the unfinished implementation.

#45311 explicitly depends on #44657 and remains draft until that browser change lands. This PR has been left open for maintainers to decide how to consolidate the work.

rusackas and others added 2 commits October 16, 2026 18:02
A total that collapses the metric axis -- the right-hand Total column, or
the bottom Total row with metrics on rows, grand-total corner included --
mixes every configured metric, so it has no single meaningful value. The
percent modes already left it blank; in Actual Values mode the additive
path (every metric SUM/COUNT/MIN/MAX, so no GROUPING SETS requested) still
reduced the leaf cells across metrics, exporting e.g. 14 / 26 / 40 for a
SUM + MAX pivot where the chart shows nothing (apache#44657).

Run every row total through `collapse()` and blank it when the block spans
more than one metric, then re-blank those columns after the column totals
pass, which would otherwise sum a column of blanks to 0. The currency
context pass keeps its unions. Both rollup consumers now take the metric
names as a set built once per call instead of a list lookup per cell.

Snapshots for two-metric pivots change only in the mixed Total/Subtotal
cells. The regression test covers Actual Values and all three percent
modes, both metric layouts, with and without database rollups.

Co-Authored-By: Evan Rusackas <evan@preset.io>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@codeant-ai-for-open-source

Copy link
Copy Markdown
Contributor

CodeAnt PR Risk: Low Risk

  • The PR appears safe to merge based on the supplied code and review conversations.
  • Mixed-metric totals now remain blank, including the grand-total corner, while per-metric totals are preserved.
  • New tests cover both metric layouts, additive totals, database rollups, and percentage modes.

Assessed commit: b32c47ec3f69

@github-actions github-actions Bot added the requires:rebase Requires rebasing on top of current master label Oct 20, 2026

@aminghadersohi aminghadersohi left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes because this PR is a duplicate: the same pivot-table total fix already landed in #45311 (merged). Please close this PR rather than rebasing it; if you believe something in it is not covered by the merged change, open a new PR for that remainder only.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

requires:rebase Requires rebasing on top of current master size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Pivot table reports/exports pick an arbitrary metric for a mixed-metric total instead of blanking it

4 participants