Skip to content

Heatmap with "Normalize Across" x/y will fail when filters reduce the data to a single column/row. #40709

@EUbaldiEC

Description

@EUbaldiEC

Bug description

When creating heatmaps (both tested in 6.0.0 and 6.1.0) with normalisation across X/Y (and posibly color normalisation), the plot will fail when only one column/row is left by applying dynamic filters.

Example is in the flights sample dataset, on a fresh install, putting AIRLINE as the X and CITY as Y (metric COUNT(*) or SUM(AIRLINE_DELAY) or anything else).

This might be related to the underlying eChart heatmap implementation (and the error thrown stems from pandas postprocessing rank function) but I am struggling to understand where to look in the codebase to check for issues.

Let me know should you need any additional information, thanks!

Screenshots/recordings

Example is in the flights sample dataset, on a fresh install, putting AIRLINE as the X and CITY as Y (metric COUNT(*) or SUM(AIRLINE_DELAY) or anything else).

Image

It works as expected with the normalisation across X (above), but as soon as a filter reducing the data to a single column (like AIRLINE = 'AA'), a "Cannot set a DataFrame with multiple columns to the single column rank" error is shown.

Image

The weird thing is that then the plot works with no issues if one normalises across rows/cols (Y/X) (the same works when normalising across heatmap):

Image

To conclude, an unexptected behavior is also found when reducing both the rows and the columns to 1:

  • If one normalises across X/Y we get an empty plot (should plot a single square with 100% in both cases)
Image
  • Instead, when normalising over the heatmap this is working as expected:
Image

Superset version

6.0.0

Python version

3.10

Node version

18 or greater

Browser

Not applicable

Additional context

Here is the python stacktrace from container logs:

2026-06-03 12:27:08,053:WARNING:superset.views.error_handling:Exception
Traceback (most recent call last):
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/flask/app.py", line 917, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/flask/app.py", line 902, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/flask_appbuilder/security/decorators.py", line 101, in wraps
    return f(self, *args, **kwargs)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/views/base_api.py", line 120, in wraps
    duration, response = time_function(f, self, *args, **kwargs)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/utils/core.py", line 1559, in time_function
    response = func(*args, **kwargs)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/utils/log.py", line 299, in wrapper
    value = f(*args, add_extra_log_payload=log, **kwargs)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/charts/data/api.py", line 289, in data
    return self._get_data_response(
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/utils/log.py", line 301, in wrapper
    value = f(*args, **kwargs)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/charts/data/api.py", line 496, in _get_data_response
    result = command.run(force_cached=force_cached)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/commands/chart/data/get_data_command.py", line 46, in run
    payload = self._query_context.get_payload(
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_context.py", line 99, in get_payload
    return self._processor.get_payload(cache_query_context, force_cached)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_context_processor.py", line 353, in get_payload
    query_results = [
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_context_processor.py", line 354, in <listcomp>
    get_query_results(
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_actions.py", line 290, in get_query_results
    return result_func(query_context, query_obj, force_cached)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_actions.py", line 160, in _get_full
    payload = query_context.get_df_payload(query_obj, force_cached=force_cached)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_context.py", line 129, in get_df_payload
    return self._processor.get_df_payload(
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_context_processor.py", line 131, in get_df_payload
    query_result = self.get_query_result(query_obj)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_context_processor.py", line 243, in get_query_result
    return self._qc_datasource.get_query_result(query_object)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/models/helpers.py", line 1343, in get_query_result
    df = query_object.exec_post_processing(df)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_object.py", line 542, in exec_post_processing
    df = getattr(pandas_postprocessing, operation)(df, **options)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/utils/pandas_postprocessing/rank.py", line 37, in rank
    df["rank"] = gb.apply(lambda x: x[metric].rank(pct=True))
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/pandas/core/frame.py", line 4081, in __setitem__
    self._set_item_frame_value(key, value)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/pandas/core/frame.py", line 4239, in _set_item_frame_value
    raise ValueError(
ValueError: Cannot set a DataFrame with multiple columns to the single column rank
2026-06-03 12:27:08,053:ERROR:superset.views.error_handling:Cannot set a DataFrame with multiple columns to the single column rank
Traceback (most recent call last):
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/flask/app.py", line 917, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/flask/app.py", line 902, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)  # type: ignore[no-any-return]
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/flask_appbuilder/security/decorators.py", line 101, in wraps
    return f(self, *args, **kwargs)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/views/base_api.py", line 120, in wraps
    duration, response = time_function(f, self, *args, **kwargs)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/utils/core.py", line 1559, in time_function
    response = func(*args, **kwargs)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/utils/log.py", line 299, in wrapper
    value = f(*args, add_extra_log_payload=log, **kwargs)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/charts/data/api.py", line 289, in data
    return self._get_data_response(
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/utils/log.py", line 301, in wrapper
    value = f(*args, **kwargs)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/charts/data/api.py", line 496, in _get_data_response
    result = command.run(force_cached=force_cached)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/commands/chart/data/get_data_command.py", line 46, in run
    payload = self._query_context.get_payload(
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_context.py", line 99, in get_payload
    return self._processor.get_payload(cache_query_context, force_cached)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_context_processor.py", line 353, in get_payload
    query_results = [
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_context_processor.py", line 354, in <listcomp>
    get_query_results(
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_actions.py", line 290, in get_query_results
    return result_func(query_context, query_obj, force_cached)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_actions.py", line 160, in _get_full
    payload = query_context.get_df_payload(query_obj, force_cached=force_cached)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_context.py", line 129, in get_df_payload
    return self._processor.get_df_payload(
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_context_processor.py", line 131, in get_df_payload
    query_result = self.get_query_result(query_obj)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_context_processor.py", line 243, in get_query_result
    return self._qc_datasource.get_query_result(query_object)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/models/helpers.py", line 1343, in get_query_result
    df = query_object.exec_post_processing(df)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/common/query_object.py", line 542, in exec_post_processing
    df = getattr(pandas_postprocessing, operation)(df, **options)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/superset/utils/pandas_postprocessing/rank.py", line 37, in rank
    df["rank"] = gb.apply(lambda x: x[metric].rank(pct=True))
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/pandas/core/frame.py", line 4081, in __setitem__
    self._set_item_frame_value(key, value)
  File "/home/user/.local/share/pipx/venvs/apache-superset/lib/python3.10/site-packages/pandas/core/frame.py", line 4239, in _set_item_frame_value
    raise ValueError(
ValueError: Cannot set a DataFrame with multiple columns to the single column rank

Checklist

  • I have searched Superset docs and Slack and didn't find a solution to my problem.
  • I have searched the GitHub issue tracker and didn't find a similar bug report.
  • I have checked Superset's logs for errors and if I found a relevant Python stacktrace, I included it here as text in the "additional context" section.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions