support for matplotlib.pyplot.hist2d with awkward arrays
Version of Awkward Array
2.8.9
Description and code to reproduce
Trying to use awkward arrays in matplotlib hist2d does not work
plt.hist2d(ak.flatten(a1),ak.flatten(a1))
results in
AttributeError Traceback (most recent call last)
Cell In[6], line 1
----> 1 plt.hist2d(ak.flatten(a1),ak.flatten(a1))
File [~/NSBI-workflow-tutorial/.pixi/envs/nsbi-env-gpu/lib/python3.12/site-packages/matplotlib/_api/deprecation.py:453](https://jupyterhub.ssl-hep.org/user/[email protected]/research-softwa-dia-october2025-47hkxj8t/.pixi/envs/nsbi-env-gpu/lib/python3.12/site-packages/matplotlib/_api/deprecation.py#line=452), in make_keyword_only.<locals>.wrapper(*args, **kwargs)
447 if len(args) > name_idx:
448 warn_deprecated(
449 since, message="Passing the %(name)s %(obj_type)s "
450 "positionally is deprecated since Matplotlib %(since)s; the "
451 "parameter will become keyword-only in %(removal)s.",
452 name=name, obj_type=f"parameter of {func.__name__}()")
--> 453 return func(*args, **kwargs)
File [~/NSBI-workflow-tutorial/.pixi/envs/nsbi-env-gpu/lib/python3.12/site-packages/matplotlib/pyplot.py:3537](https://jupyterhub.ssl-hep.org/user/[email protected]/research-softwa-dia-october2025-47hkxj8t/.pixi/envs/nsbi-env-gpu/lib/python3.12/site-packages/matplotlib/pyplot.py#line=3536), in hist2d(x, y, bins, range, density, weights, cmin, cmax, data, **kwargs)
3523 @_copy_docstring_and_deprecators(Axes.hist2d)
3524 def hist2d(
3525 x: ArrayLike,
(...) 3535 **kwargs,
3536 ) -> tuple[np.ndarray, np.ndarray, np.ndarray, QuadMesh]:
-> 3537 __ret = gca().hist2d(
3538 x,
3539 y,
3540 bins=bins,
3541 range=range,
3542 density=density,
3543 weights=weights,
3544 cmin=cmin,
3545 cmax=cmax,
3546 **({"data": data} if data is not None else {}),
3547 **kwargs,
3548 )
3549 sci(__ret[-1])
3550 return __ret
File [~/NSBI-workflow-tutorial/.pixi/envs/nsbi-env-gpu/lib/python3.12/site-packages/matplotlib/_api/deprecation.py:453](https://jupyterhub.ssl-hep.org/user/[email protected]/research-softwa-dia-october2025-47hkxj8t/.pixi/envs/nsbi-env-gpu/lib/python3.12/site-packages/matplotlib/_api/deprecation.py#line=452), in make_keyword_only.<locals>.wrapper(*args, **kwargs)
447 if len(args) > name_idx:
448 warn_deprecated(
449 since, message="Passing the %(name)s %(obj_type)s "
450 "positionally is deprecated since Matplotlib %(since)s; the "
451 "parameter will become keyword-only in %(removal)s.",
452 name=name, obj_type=f"parameter of {func.__name__}()")
--> 453 return func(*args, **kwargs)
File [~/NSBI-workflow-tutorial/.pixi/envs/nsbi-env-gpu/lib/python3.12/site-packages/matplotlib/__init__.py:1524](https://jupyterhub.ssl-hep.org/user/[email protected]/research-softwa-dia-october2025-47hkxj8t/.pixi/envs/nsbi-env-gpu/lib/python3.12/site-packages/matplotlib/__init__.py#line=1523), in _preprocess_data.<locals>.inner(ax, data, *args, **kwargs)
1521 @functools.wraps(func)
1522 def inner(ax, *args, data=None, **kwargs):
1523 if data is None:
-> 1524 return func(
1525 ax,
1526 *map(cbook.sanitize_sequence, args),
1527 **{k: cbook.sanitize_sequence(v) for k, v in kwargs.items()})
1529 bound = new_sig.bind(ax, *args, **kwargs)
1530 auto_label = (bound.arguments.get(label_namer)
1531 or bound.kwargs.get(label_namer))
File [~/NSBI-workflow-tutorial/.pixi/envs/nsbi-env-gpu/lib/python3.12/site-packages/matplotlib/axes/_axes.py:7531](https://jupyterhub.ssl-hep.org/user/[email protected]/research-softwa-dia-october2025-47hkxj8t/.pixi/envs/nsbi-env-gpu/lib/python3.12/site-packages/matplotlib/axes/_axes.py#line=7530), in Axes.hist2d(self, x, y, bins, range, density, weights, cmin, cmax, **kwargs)
7528 if cmax is not None:
7529 h[h > cmax] = None
-> 7531 pc = self.pcolormesh(xedges, yedges, h.T, **kwargs)
7532 self.set_xlim(xedges[0], xedges[-1])
7533 self.set_ylim(yedges[0], yedges[-1])
File [~/NSBI-workflow-tutorial/.pixi/envs/nsbi-env-gpu/lib/python3.12/site-packages/awkward/highlevel.py:1298](https://jupyterhub.ssl-hep.org/user/[email protected]/research-softwa-dia-october2025-47hkxj8t/.pixi/envs/nsbi-env-gpu/lib/python3.12/site-packages/awkward/highlevel.py#line=1297), in Array.__getattr__(self, where)
1293 raise AttributeError(
1294 f"while trying to get field {where!r}, an exception "
1295 f"occurred:\n{type(err)}: {err!s}"
1296 ) from err
1297 else:
-> 1298 raise AttributeError(f"no field named {where!r}")
AttributeError: no field named 'T'
#1096 seems possibly related. Converting the flattened awkward arrays to numpy arrays is a workaround..
Hmm that's interesting.....ak.Array supports the __array__ protocol and I would hope that matplotlib would convert it to a np.ndarray first before doing anything with it. It looks like it's trying to transpose it as is before converting it to numpy....Maybe that's a request for matplotlib tbh. I don't know how transposition would look like in the general case for awkward arrays. If it's actually rectilinear sure...but I can't think of a general jagged transposition in the awkward array model.