amaannawab923 commented on code in PR #43718:
URL: https://github.com/apache/superset/pull/43718#discussion_r3896176855
##########
tests/unit_tests/charts/test_client_processing.py:
##########
@@ -1804,6 +1805,235 @@ def test_pivot_df_complex_null_values():
)
+# --- `showValuesAs` percent modes (#42809) -----------------------------------
+#
+# Exports and scheduled reports render server-side, so they have to reproduce
+# the client's `fractionOf` aggregator: each cell over its row, column, or
grand
+# total, computed per metric, with totals dividing by their own rollup rather
+# than summing the fractions around them.
+
+SHOW_VALUES_AS_OPTIONS: dict[str, Any] = {
+ "rows": ["nation"],
+ "columns": ["gender"],
+ "metrics": ["SUM(num)"],
+ "aggfunc": "Sum",
+ "transpose_pivot": False,
+ "combine_metrics": False,
+ "show_rows_total": True,
+ "show_columns_total": True,
+ "apply_metrics_on_rows": False,
+}
+
+
+def show_values_as_df() -> pd.DataFrame:
+ """A 2x2 pivot: row totals 40/40, column totals 30/50, grand total 80."""
+ return pd.DataFrame(
+ {
+ "nation": ["US", "US", "UK", "UK"],
+ "gender": ["boy", "girl", "boy", "girl"],
+ "SUM(num)": [10, 30, 20, 20],
+ }
+ )
+
+
+def total_label() -> str:
+ return f"{_('Total')} (Sum)"
+
+
+def test_pivot_df_show_values_as_percent_row():
+ pivoted = pivot_df(
+ show_values_as_df(), **SHOW_VALUES_AS_OPTIONS,
show_values_as="percent_row"
+ )
+ total = total_label()
+
+ assert pivoted.loc[("US",), ("SUM(num)", "boy")] == 0.25
+ assert pivoted.loc[("US",), ("SUM(num)", "girl")] == 0.75
+ assert pivoted.loc[("UK",), ("SUM(num)", "boy")] == 0.5
+ # a row is always 100% of itself
+ assert pivoted.loc[("US",), (total, "")] == 1
+ # the totals row shows each column's share of the grand total (30/80 and
+ # 50/80), not the sum of the fractions above it
+ assert pivoted.loc[(total,), ("SUM(num)", "boy")] == 0.375
+ assert pivoted.loc[(total,), ("SUM(num)", "girl")] == 0.625
+ assert pivoted.loc[(total,), (total, "")] == 1
+
+
+def test_pivot_df_show_values_as_percent_col():
+ pivoted = pivot_df(
+ show_values_as_df(), **SHOW_VALUES_AS_OPTIONS,
show_values_as="percent_col"
+ )
+ total = total_label()
+
+ assert pivoted.loc[("US",), ("SUM(num)", "boy")] == pytest.approx(1 / 3)
+ assert pivoted.loc[("UK",), ("SUM(num)", "boy")] == pytest.approx(2 / 3)
+ assert pivoted.loc[("US",), ("SUM(num)", "girl")] == 0.6
+ # a column is always 100% of itself
+ assert pivoted.loc[(total,), ("SUM(num)", "boy")] == 1
+ # the totals column shows each row's share of the grand total
+ assert pivoted.loc[("US",), (total, "")] == 0.5
+
+
+def test_pivot_df_show_values_as_percent_total():
+ pivoted = pivot_df(
+ show_values_as_df(), **SHOW_VALUES_AS_OPTIONS,
show_values_as="percent_total"
+ )
+ total = total_label()
+
+ assert pivoted.loc[("US",), ("SUM(num)", "boy")] == 0.125
+ assert pivoted.loc[("US",), ("SUM(num)", "girl")] == 0.375
+ assert pivoted.loc[("UK",), ("SUM(num)", "boy")] == 0.25
+ assert pivoted.loc[(total,), ("SUM(num)", "boy")] == 0.375
+ assert pivoted.loc[("US",), (total, "")] == 0.5
+ assert pivoted.loc[(total,), (total, "")] == 1
+
+
+def test_pivot_df_show_values_as_keeps_metrics_separate():
+ """One metric's cells are never divided by another metric's total."""
+ df = show_values_as_df()
+ df["MAX(num)"] = [1, 3, 6, 10]
+ pivoted = pivot_df(
+ df,
+ **{**SHOW_VALUES_AS_OPTIONS, "metrics": ["SUM(num)", "MAX(num)"]},
+ show_values_as="percent_row",
+ )
+
+ assert pivoted.loc[("US",), ("SUM(num)", "boy")] == 0.25
+ assert pivoted.loc[("UK",), ("MAX(num)", "boy")] == 0.375
+ assert pivoted.loc[("UK",), ("MAX(num)", "girl")] == 0.625
Review Comment:
this does set up the cross metric case, so the `metric is None` branch does
run, but the asserts all land on metric columns.
one assert on a total cell would pin the behaviour the docstring describes,
where cross metric totals divide by the denominator spanning every metric.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]