Title: ENH: Add grouped_bar() method by timhoffm · Pull Request #28560 · matplotlib/matplotlib · GitHub
Open Graph Title: ENH: Add grouped_bar() method by timhoffm · Pull Request #28560 · matplotlib/matplotlib
X Title: ENH: Add grouped_bar() method by timhoffm · Pull Request #28560 · matplotlib/matplotlib
Description: This is a WIP to implement #24313. It will be updated incrementally. As a first step, I've designed the data and label input API. Please check the included example, which explains the API variants and motivations/consistency considerations. It's a WIP for the illustration and discussion of the API, and will not go into the final PR I've flagged as "work in progress" because many aspects are not implemented yet. **But please give comments as I consider the implemented parts as complete proposal for that aspects.** The API proposal is complete. Please check whether it is reasonable. You can get an overview the preliminary overview example and in the API docs for grouped_bar. Design decisions and background are listed in right below in the todos: 👉 Ready for review What's new API docs Updated example, which is now much simpler. Todos: API: How to structure and interpret the two data dimensions and the associated labels. For now, only categorical labels are supported as x. Should we also support numbers as with bar? Numbers are now also supported. How to parametrize bar width and group spacing? A bar group takes horizontal space w (default: 1). I believe explicit bar widths are not helpful because they can easily overflow if enough bars are in a group, and "reasonable" values need fine-tuning for per number of bars in a group. I therefore suggest to define the spacing (margin / padding; name t.b.d.) in relative units. Options: padding in units of w: e.g. pad=0.1 would mean a bar group targeting the interval (x-0.5*w, x+0.5*w) would have the outer bar edges at (x-(0.5-pad*w), x+(0.5-pad*w) = (x-0.4w, x+0.4w)`. padding as multiples of the bar width: e.g. a pad=1 would mean that the bar width is chosen so that there's a padding of 1-bar width on both sides of the group. I believe, we can choose reasonable defaults for both cases. It's possibly easier to tune a desired look with the second approach, but harder if one wants to fully control positions. Decision: Implemented as multiples of bar width Do we want to support spacing between the bars in a group? Yes. Spacing should follow the same relative conventions as group padding. Since we have num_bars times the spacing "spacing in units of w will require tuning depending on the number of bars. Spacing would be universal when given as "fraction of bar width". When defaulting to 0 (my slight preference) both variants will work for any number of bars by default. How to support horizontal bars? Use orientation parameter. Replicating to a separate function grouped_barh is overly cumbersome. Do we want to support stacked bars? And grouped stacked bars? - Not for now/here. While stacked bars could use the same input datastructures, other plotting parameters like width and spacing settings do not match, and some bar() flexibility like varying width will not be available via grouped_bar(). I thus recommend not to try and squeeze stacked bars in to grouped_bar(). Stacking bars is already much simpler with the existing bar() methods compared to grouping bars. bar() is thus more sufficient. If we want a higher level interface, a separate stacked_bar() would be a thin wrapper around bar(). I don't see a reasonable function for stacked and grouped bars, because the addtional dimension of data and labelling would make the interface very difficult. If you need stacked and grouped bars, you should use a loop of grouped_bar() with adjusted bottom. support kwargs (Rectangle properties) support vectorized style parameters - at least colors optional: support bottom values, so that one could stack (but could be added later) dataset labels naming? label as in bar(), or labels or dataset_labels or … Note: stackplot() uses labels. This would be an argument for consistency. What's different: We potentially have two labels: dataset labels and group labels. This may warrant deviating from the simple labels apporach to disambiguate them. OTOH, I feel "dataset" is quite a generic name (but I don't have any better) so that it does not make things much clearer. The group labels are implicit in x (or historically in bar(), called tick_labels. I'm going with labels because its consistent with stackplot() and bar() (which uses label) consistent with legend labels always being specified through label a longer name does not significantly help with disambiguation add pyplot wrapper add mypy stubs improve documentation add tests Should we mark this as provisional? This would allow to react to user feedback. -> Yes. What is the return type? List of BarContainer, a new BarGroupContainer, something else, nothing for a start (because we can't decide yet)? Going with list[BarContainer}. This is most simple and in analogy to what stackplot() does. Since the API is provisional, we can still reconsider.
Open Graph Description: This is a WIP to implement #24313. It will be updated incrementally. As a first step, I've designed the data and label input API. Please check the included example, which explains the API varia...
X Description: This is a WIP to implement #24313. It will be updated incrementally. As a first step, I've designed the data and label input API. Please check the included example, which explains the API v...
Opengraph URL: https://github.com/matplotlib/matplotlib/pull/28560
X: @github
Domain: github.com
| route-pattern | /:user_id/:repository/pull/:id/files(.:format) |
| route-controller | pull_requests |
| route-action | files |
| fetch-nonce | v2:abf44aa0-b8cf-4673-a54b-f4e3d790f3da |
| current-catalog-service-hash | ae870bc5e265a340912cde392f23dad3671a0a881730ffdadd82f2f57d81641b |
| request-id | A990:120FB6:C31A:10387:6A523370 |
| html-safe-nonce | 48456ec6f19bb091a1414e7556dccaeca11149ae49356982ff4f57f7cc864697 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJBOTkwOjEyMEZCNjpDMzFBOjEwMzg3OjZBNTIzMzcwIiwidmlzaXRvcl9pZCI6IjE1MjE1MTgwMzA2ODQ4Mjg1MjgiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | e3d3c7d961d803f3d1a8cebec671df230e01b004948c4c99ba6dbb56130b17b2 |
| hovercard-subject-tag | pull_request:1967742971 |
| github-keyboard-shortcuts | repository,pull-request-list,pull-request-conversation,pull-request-files-changed,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/matplotlib/matplotlib/pull/28560/files |
| twitter:image | https://avatars.githubusercontent.com/u/2836374?s=400&v=4 |
| twitter:card | summary_large_image |
| og:image | https://avatars.githubusercontent.com/u/2836374?s=400&v=4 |
| og:image:alt | This is a WIP to implement #24313. It will be updated incrementally. As a first step, I've designed the data and label input API. Please check the included example, which explains the API varia... |
| og:site_name | GitHub |
| og:type | object |
| hostname | github.com |
| expected-hostname | github.com |
| None | b9a586c06a05a7a86fc7e3f4dbd03e42f6869085879aa184aa6369456dbd50fb |
| turbo-cache-control | no-preview |
| diff-view | unified |
| go-import | github.com/matplotlib/matplotlib git https://github.com/matplotlib/matplotlib.git |
| octolytics-dimension-user_id | 215947 |
| octolytics-dimension-user_login | matplotlib |
| octolytics-dimension-repository_id | 1385122 |
| octolytics-dimension-repository_nwo | matplotlib/matplotlib |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 1385122 |
| octolytics-dimension-repository_network_root_nwo | matplotlib/matplotlib |
| turbo-body-classes | logged-out env-production page-responsive full-width |
| disable-turbo | true |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 7aed05249554b889eb33d002851a973eebcc7e91 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width