diff --git a/pandas/core/reshape/pivot.py b/pandas/core/reshape/pivot.py index 90324044c237c..433b4664fa037 100644 --- a/pandas/core/reshape/pivot.py +++ b/pandas/core/reshape/pivot.py @@ -1163,9 +1163,15 @@ def _normalize( elif margins is True: # keep index and column of pivoted table + table_index = table.index table_columns = table.columns - last_ind_or_col = table.iloc[-1, :].name + try: + last_ind_or_col = table.iloc[-1, :].name + except IndexError as err: + raise IndexError( + "Can't get margins since the result dataframe is empty" + ) from err # check if margin name is not in (for MI cases) and not equal to last # index/column and save the column and index margin diff --git a/pandas/tests/reshape/test_crosstab.py b/pandas/tests/reshape/test_crosstab.py index 1482da8a074eb..fdf808ca49ea6 100644 --- a/pandas/tests/reshape/test_crosstab.py +++ b/pandas/tests/reshape/test_crosstab.py @@ -877,3 +877,38 @@ def test_categoricals(a_dtype, b_dtype): expected = expected.loc[[0, 2, "All"]] expected["All"] = expected["All"].astype("int64") tm.assert_frame_equal(result, expected) + + +def test_crosstab_empty_result_with_normalize(): + # https://github.com/pandas-dev/pandas/issues/60768 + index = ["index1", "index2", "index3"] + columns = ["col1", "col2", "col3"] + values = [1, 2, 3] + + with pytest.raises(IndexError, match="Can't get margins"): + # Raise error when margins=True + crosstab( + index, + columns, + values=values, + normalize=1, + margins=True, + dropna=True, + aggfunc="skew", + ) + + # No error when margins=False, just return empty DataFrame + result = crosstab( + index, + columns, + values=values, + normalize=1, + margins=False, + dropna=True, + aggfunc="skew", + ) + expected = DataFrame( + index=Index([], dtype="str", name="row_0"), + columns=Index([], dtype="str", name="col_0"), + ) + tm.assert_frame_equal(result, expected)