Skip to content

Conversation

@carlosgmartin
Copy link
Contributor

Fixes #29239.

@carlosgmartin carlosgmartin force-pushed the numpy_size_multiple_axes branch 5 times, most recently from 8f17ccf to 5dfded8 Compare June 19, 2025 23:07
@jorenham jorenham added the 56 - Needs Release Note. Needs an entry in doc/release/upcoming_changes label Jun 20, 2025
Copy link
Member

@jorenham jorenham left a comment

Choose a reason for hiding this comment

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

Thanks for this. The use-cases are probably a bit niche, but I'm sure that there are genuine use-cases for this, and the required changes are nice and subtle.

I left some comments about two edge-cases. It could help to add a quick example of this in the docstring. A release note might also be a good idea here, but it's probably a good idea to wait until everyone is happy, otherwise you risk having to change it a couple of times.

Oh and don't forget about the stubs :)

def size(a: ArrayLike, axis: int | None = ...) -> int: ...

@mattip
Copy link
Member

mattip commented Jun 20, 2025

I don't mind putting this in, but the discussion did not actually point to why this is useful.

It would have been nice to make axis a kwonly argument, which unfortunately is not a backward compatible change. I would need to reach for the documentation if I ever saw np.size(a, 1), and even moreso if I saw np.size(a, (1, 1)). Perhaps at least for the examples we should be using the kwarg?

@carlosgmartin
Copy link
Contributor Author

carlosgmartin commented Jun 20, 2025

@mattip This is useful for measuring the size of a multidimensional array with semantically-meaningful axes in a specific, nontrivial way.

For example, I can get the pixel size of an image in HWC format via jnp.size(array, (0, 1)), or in CHW format via jnp.size(array, (1, 2)). I can get the voxel size of a volumetric image via jnp.size(array, (0, 1, 2)). These might have leading batch dimensions, so I can adjust the tuple accordingly. There might also be a temporal dimension, for videos or spatio-temporal data/simulations. And so on.

@mattip
Copy link
Member

mattip commented Jun 21, 2025

Thanks. Personally i use dtype.itemsize * factor, but I guess using size works too

@carlosgmartin carlosgmartin force-pushed the numpy_size_multiple_axes branch from 57fbe4b to 991148d Compare June 21, 2025 05:55
@carlosgmartin carlosgmartin requested review from jorenham and seberg June 21, 2025 20:32
@carlosgmartin carlosgmartin force-pushed the numpy_size_multiple_axes branch from 991148d to 328008c Compare July 9, 2025 16:33
@carlosgmartin carlosgmartin requested a review from seberg July 9, 2025 16:34
@seberg
Copy link
Member

seberg commented Jul 10, 2025

Thanks @carlosgmartin, I don't know if I think it's very useful, but I think that places that accept axis and multiple make clearly sense and is simple, then it's good to just do it.

@seberg seberg merged commit 8cf1f7d into numpy:main Jul 10, 2025
78 checks passed
@carlosgmartin carlosgmartin deleted the numpy_size_multiple_axes branch July 10, 2025 07:21
@carlosgmartin
Copy link
Contributor Author

carlosgmartin commented Jul 10, 2025

@seberg In addition to #29240 (comment), this is needed by reductions like mean and var, which need to know the size of the axis or axes along which the reduction takes place.

Thus the endpoint of the chain mean > _mean > _count_reduce_items does something similar.

@seberg
Copy link
Member

seberg commented Jul 10, 2025

this is needed by reductions like mean and var, which need to know the size of the axis or axes along which the reduction takes place.

I don't like np.size to begin with much, since it does coercion to ndarray first potentially. That function is needed because of the masked path, the other path could be simplified, but whether it's better off calling np.size or just simplifying the logic here, dunno.

@carlosgmartin
Copy link
Contributor Author

carlosgmartin commented Jul 10, 2025

The non-masked path could perhaps reuse the new np.size, whereas the masked path could stick to where.sum(axis=axis, keepdims=keepdims) or something similar.

IndifferentArea pushed a commit to IndifferentArea/numpy that referenced this pull request Dec 7, 2025
* Let numpy.size accept multiple axes.

* Apply suggestions from code review

---------

Co-authored-by: Sebastian Berg <sebastian@sipsolutions.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

01 - Enhancement 56 - Needs Release Note. Needs an entry in doc/release/upcoming_changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ENH: Let numpy.size accept multiple axes

4 participants