Skip to content

feat: support stackPercent for normalized stacking #20910

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

sjcobb
Copy link

@sjcobb sjcobb commented Apr 10, 2025

Brief Information

This pull request is in the type of:

  • bug fixing
  • new feature
  • others

What does this PR do?

Adds support for stackPercent: boolean, which normalizes all stacked series values into percentages per category index (so the stacked total always adds up to 100%).

Fixed issues

Details

Before: What was the problem?

No built-in way to compute percent-stacked values across a stack group without pre-processing data (see bar-stack-normalization example).

image

image

After: How does it behave after the fixing?

When stackPercent: true is set on a stacked series, values are automatically normalized to percentages per category. Tooltip shows both raw value and percentage.

image

image

With formatters:
image

Document Info

One of the following should be checked.

Misc

ZRender Changes

  • This PR depends on ZRender changes (ecomfe/zrender#xxx).

Related test cases or examples to use the new APIs

bar-stack-normalization

Others

Merging options

  • Please squash the commits into a single one when merging.

Other information

@echarts-bot echarts-bot bot added PR: awaiting doc Document changes is required for this PR. PR: awaiting review labels Apr 10, 2025
Copy link

echarts-bot bot commented Apr 10, 2025

Thanks for your contribution!
The community will review it ASAP. In the meanwhile, please checkout the coding standard and Wiki about How to make a pull request.

Document changes are required in this PR. Please also make a PR to apache/echarts-doc for document changes and update the issue id in the PR description. When the doc PR is merged, the maintainers will remove the PR: awaiting doc label.

Copy link
Contributor

@Ovilia Ovilia left a comment

Choose a reason for hiding this comment

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

If we are going to support normalized stacking, it should not use stackStrategy because this concept is for deciding whether to stack positive/negative values. You should probably need another new option for this feature.

Stacking by percentage can be supported with current ECharts with a little hacking so it should be nice to have this feature to make the option more intuitive. Thanks for your contribution.

@Ovilia
Copy link
Contributor

Ovilia commented Apr 11, 2025

And I'm not sure how to let the axis know that this is a normalized series and should use % in the axis labels. Maybe it's still necessary to set formatter: (params) => Math.round({params or params.value} * 1000) / 10 + '%' both in series.label and yAxis.axisLabel. Do you have any better ideas?

@sjcobb
Copy link
Author

sjcobb commented Apr 11, 2025

If we are going to support normalized stacking, it should not use stackStrategy because this concept is for deciding whether to stack positive/negative values. You should probably need another new option for this feature.

Stacking by percentage can be supported with current ECharts with a little hacking so it should be nice to have this feature to make the option more intuitive. Thanks for your contribution.

Yeah this makes sense, I found an older discussion on this topic here where you proposed: stackPercent: true

I went ahead and made that change in this commit but open to any other ideas!

@sjcobb
Copy link
Author

sjcobb commented Apr 11, 2025

And I'm not sure how to let the axis know that this is a normalized series and should use % in the axis labels. Maybe it's still necessary to set formatter: (params) => Math.round({params or params.value} * 1000) / 10 + '%' both in series.label and yAxis.axisLabel. Do you have any better ideas?

Agreed this seems difficult, I think starting with requiring the custom formatter can work (I can point this out in docs / create a new example).

I played around with setting the axisLabel formatter automatically (when one isn't already defined) in this branch, but that doesn't seem like a great solution

EDIT: Added examples in percent-stack.html here

@sjcobb sjcobb changed the title feat: percent stack strategy feat: support stackPercent for normalized stacking Apr 11, 2025
@sjcobb sjcobb requested a review from Ovilia April 15, 2025 00:53
@Justin-ZS
Copy link

Maybe you should set the axis max to 100%?
Otherwise the total value maybe 1.00000001(due to precision lost)and causes the max value to be 120%

@sjcobb
Copy link
Author

sjcobb commented Apr 28, 2025

Maybe you should set the axis max to 100%? Otherwise the total value maybe 1.00000001(due to precision lost)and causes the max value to be 120%

Yeah good call, it is a little awkward to do this for similar reasons as here but I'll look into it more. This PR is already pretty large, @Ovilia would you prefer I open a separate PR to adjust the axis max / formatter or keep adding to this one?

@Justin-ZS
Copy link

Hi, based on this PR.
How can we get the raw value/total value so that we can customize the datalabel/tooltip with label.formatter/tooltip.formatter?

@yuicer
Copy link

yuicer commented May 22, 2025

Do you happen to have any updates here? wish to see this pr be merged, it's beneficial

@echarts-bot echarts-bot bot added PR: doc ready and removed PR: awaiting doc Document changes is required for this PR. labels May 23, 2025
@sjcobb
Copy link
Author

sjcobb commented May 23, 2025

Hi, based on this PR. How can we get the raw value/total value so that we can customize the datalabel/tooltip with label.formatter/tooltip.formatter?

Raw value is still included and the normalized value was added in series label and tooltip formatter as percent (I reused this since it was already in types from 'pie' series), example:

tooltip: {
trigger: "item",
// https://echarts.apache.org/en/option.html#tooltip.formatter
formatter: (params) => {
return `Normalized value: ${params.percent}%`;
},

image

@sjcobb
Copy link
Author

sjcobb commented May 23, 2025

Do you happen to have any updates here? wish to see this pr be merged, it's beneficial

Glad to hear you find it useful! I just opened a docs PR so I'm waiting on more feedback on the initial implementation and the new option name stackPercent.

Hoping to add enhancements like appending '%' to series label / yAxis.axisLabel and setting yAxis.max to 100 automatically in a later PR (since they can be set explicitly as shown in percent-stack.html example)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants