Title: Discussion: Use of masked arrays internally · Issue #31008 · matplotlib/matplotlib · GitHub
Open Graph Title: Discussion: Use of masked arrays internally · Issue #31008 · matplotlib/matplotlib
X Title: Discussion: Use of masked arrays internally · Issue #31008 · matplotlib/matplotlib
Description: Chatting with @timhoffm in #31004 (comment), I'd like to more widely discuss our use of masked arrays in internal code. My position is that they add a lot of maintenance headache and fragility, and we would be best off excising them from...
Open Graph Description: Chatting with @timhoffm in #31004 (comment), I'd like to more widely discuss our use of masked arrays in internal code. My position is that they add a lot of maintenance headache and fragility, and...
X Description: Chatting with @timhoffm in #31004 (comment), I'd like to more widely discuss our use of masked arrays in internal code. My position is that they add a lot of maintenance headache and fragility,...
Opengraph URL: https://github.com/matplotlib/matplotlib/issues/31008
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Discussion: Use of masked arrays internally","articleBody":"Chatting with @timhoffm in https://github.com/matplotlib/matplotlib/pull/31004#discussion_r2713671431, I'd like to more widely discuss our use of masked arrays in internal code. My position is that they add a lot of maintenance headache and fragility, and we would be best off excising them from the codebase altogether.\n\nCurrently we have 185 counts of `np.ma` in the core library. Most of them are pass-through checks, or are immediately `.filled()` with nans.\n\n**Problems**\n- Internal APIs do not usually document whether they expect or can handle masked arrays. It's easy to miss needing to handle the masked array case, contributors may not be familiar with them, and numpy functions still work so we can fail silently\n- Lots of code clutter and specific paths needed to handle masked arrays\n- Poor test coverage of masked array inputs/outputs\n- Performance degradation from passing around extra data and not being able to rely on more efficient array operations.\n Note also that `a = np.ma.masked_array(a, mask=mask).filled()` is slower than `a = np.where(mask, np.nan, a)` is slower than `a[mask] = np.nan`.\n\n**Proposal**\n- Replace all instances of masked arrays with float arrays filled with NaNs, or in instances where the underlying data needs to be preserved (eg when clipping) then use an explicitly defined boolean mask variable\n- Sanitize all user inputs to pure numpy arrays and do not return masked arrays\n- Document a dev policy to minimize internal use of masked arrays, and to never return them\n\n**Migration issues**\n- `cbook.safe_masked_invalid()` is used a few places and causes some other functions to return a masked array. I haven't traced this all the way through to see where those come out\n- All `colors.Normalize` subclasses preserve input masks in their output (this is the only docstring I see with a masked array output documented for the public API)\n\nDeprecation warnings might be difficult to raise without spamming regular uses of these functions, since we can't tell when users use the mask on returned arrays. We may need to accept some silent breakage and just make the release notes clear.","author":{"url":"https://github.com/scottshambaugh","@type":"Person","name":"scottshambaugh"},"datePublished":"2026-01-21T19:20:06.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":27},"url":"https://github.com/31008/matplotlib/issues/31008"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:b1ad742a-825b-d0b4-b598-2dc455a3fb7b |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | AB20:117213:2986B02:381F754:6A53AD71 |
| html-safe-nonce | a2154639e1f849041158da79f3387d66844e41937abc05874154490eac76c80b |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJBQjIwOjExNzIxMzoyOTg2QjAyOjM4MUY3NTQ6NkE1M0FENzEiLCJ2aXNpdG9yX2lkIjoiOTE3MTEwNTc5MDIxNDU4ODAxIiwicmVnaW9uX2VkZ2UiOiJpYWQiLCJyZWdpb25fcmVuZGVyIjoiaWFkIn0= |
| visitor-hmac | c862d78c86df8d805c98737d90515e1e7365a5313256bd251a3e04a25b5038e3 |
| hovercard-subject-tag | issue:3839682421 |
| github-keyboard-shortcuts | repository,issues,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/_view_fragments/issues/show/matplotlib/matplotlib/31008/issue_layout |
| twitter:image | https://opengraph.githubassets.com/29a9163d6883eba70aa3dd94d72168eff7148f11f1dbfac60bfc51fcc5ecfda9/matplotlib/matplotlib/issues/31008 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/29a9163d6883eba70aa3dd94d72168eff7148f11f1dbfac60bfc51fcc5ecfda9/matplotlib/matplotlib/issues/31008 |
| og:image:alt | Chatting with @timhoffm in #31004 (comment), I'd like to more widely discuss our use of masked arrays in internal code. My position is that they add a lot of maintenance headache and fragility, and... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | scottshambaugh |
| hostname | github.com |
| expected-hostname | github.com |
| None | b9a586c06a05a7a86fc7e3f4dbd03e42f6869085879aa184aa6369456dbd50fb |
| turbo-cache-control | no-preview |
| 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 |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 07a982c1d40157c619b364352b704c3ce66bb332 |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width