[Numpy-discussion] ENH: Proposal to add atleast_nd function

Benjamin Root ben.v.root at gmail.com
Thu Feb 11 13:26:29 EST 2021


My original usecase for these was dealing with output data from Matlab
where those users would use `squeeze()` quite liberally. In addition, there
was the problem of the implicit squeeze() in the numpy's loadtxt() for
which I added the ndmin kwarg for in case an input CSV file had just one
row or no rows.

np.atleast_1d() is used in matplotlib in a bunch of places where inputs are
allowed to be scalar or lists.

On Thu, Feb 11, 2021 at 1:15 PM Stephan Hoyer <shoyer at gmail.com> wrote:

> On Thu, Feb 11, 2021 at 9:42 AM Benjamin Root <ben.v.root at gmail.com>
> wrote:
>
>> for me, I find that the at_least{1,2,3}d functions are useful for
>> sanitizing inputs. Having an at_leastnd() function can be viewed as a step
>> towards cleaning up the API, not cluttering it (although, deprecations of
>> the existing functions probably should be long given how long they have
>> existed).
>>
>
> I would love to see examples of this -- perhaps in matplotlib?
>
> My thinking is that in most cases it's probably a better idea to keep the
> interface simpler, and raise an error for lower-dimensional arrays.
> Automatic conversion is convenient (and endemic within the SciPy
> ecosystem), but is also a common source of bugs.
>
> On Thu, Feb 11, 2021 at 1:56 AM Stephan Hoyer <shoyer at gmail.com> wrote:
>>
>>> On Wed, Feb 10, 2021 at 9:48 PM Juan Nunez-Iglesias <jni at fastmail.com>
>>> wrote:
>>>
>>>> I totally agree with the namespace clutter concern, but honestly, I
>>>> would use `atleast_nd` with its `pos` argument (I might rename it to
>>>> `position`, `axis`, or `axis_position`) any day over `at_least{1,2,3}d`,
>>>> for which I had no idea where the new axes would end up.
>>>>
>>>> So, I’m in favour of including it, and optionally deprecating
>>>> `atleast_{1,2,3}d`.
>>>>
>>>>
>>> I appreciate that `atleast_nd` feels more sensible than
>>> `at_least{1,2,3}d`, but I don't think "better" than a pattern we would not
>>> recommend is a good enough reason for inclusion in NumPy. It needs to stand
>>> on its own.
>>>
>>> What would be the recommended use-cases for this new function?
>>> Have any libraries building on top of NumPy implemented a version of
>>> this?
>>>
>>>
>>>> Juan.
>>>>
>>>> On 11 Feb 2021, at 9:48 am, Sebastian Berg <sebastian at sipsolutions.net>
>>>> wrote:
>>>>
>>>> On Wed, 2021-02-10 at 17:31 -0500, Joseph Fox-Rabinovitz wrote:
>>>>
>>>> I've created PR#18386 to add a function called atleast_nd to numpy and
>>>> numpy.ma. This would generalize the existing atleast_1d, atleast_2d,
>>>> and
>>>> atleast_3d functions.
>>>>
>>>> I proposed a similar idea about four and a half years ago:
>>>> https://mail.python.org/pipermail/numpy-discussion/2016-July/075722.html
>>>> ,
>>>> PR#7804. The reception was ambivalent, but a couple of folks have asked
>>>> me
>>>> about this, so I'm bringing it back.
>>>>
>>>> Some pros:
>>>>
>>>> - This closes issue #12336
>>>> - There are a couple of Stack Overflow questions that would benefit
>>>> - Been asked about this a couple of times
>>>> - Implementation of three existing atleast_*d functions gets easier
>>>> - Looks nicer that the equivalent broadcasting and reshaping
>>>>
>>>> Some cons:
>>>>
>>>> - Cluttering up the API
>>>> - Maintenance burden (but not a big one)
>>>> - This is just a utility function, which can be achieved through
>>>> broadcasting and reshaping
>>>>
>>>>
>>>> My main concern would be the namespace cluttering. I can't say I use
>>>> even the `atleast_2d` etc. functions personally, so I would tend to be
>>>> slightly against the addition. But if others land on the "useful" side here
>>>> (and it seemed a bit at least on github), I am also not opposed.  It is a
>>>> clean name that lines up with existing ones, so it doesn't seem like a big
>>>> "mental load" with respect to namespace cluttering.
>>>>
>>>> Bike shedding the API is probably a good idea in any case.
>>>>
>>>> I have pasted the current PR documentation (as html) below for quick
>>>> reference. I wonder a bit about the reasoning for having `pos` specify a
>>>> value rather than just a side?
>>>>
>>>>
>>>>
>>>> numpy.atleast_nd(*ary*, *ndim*, *pos=0*)
>>>> View input as array with at least ndim dimensions.
>>>> New unit dimensions are inserted at the index given by *pos* if
>>>> necessary.
>>>> Parameters*ary  *array_like
>>>> The input array. Non-array inputs are converted to arrays. Arrays that
>>>> already have ndim or more dimensions are preserved.
>>>> *ndim  *int
>>>> The minimum number of dimensions required.
>>>> *pos  *int, optional
>>>> The index to insert the new dimensions. May range from -ary.ndim - 1 to
>>>>  +ary.ndim (inclusive). Non-negative indices indicate locations before
>>>> the corresponding axis: pos=0 means to insert at the very beginning.
>>>> Negative indices indicate locations after the corresponding axis:
>>>> pos=-1 means to insert at the very end. 0 and -1 are always guaranteed
>>>> to work. Any other number will depend on the dimensions of the existing
>>>> array. Default is 0.
>>>> Returns*res  *ndarray
>>>> An array with res.ndim >= ndim. A view is returned for array inputs.
>>>> Dimensions are prepended if *pos* is 0, so for example, a 1-D array of
>>>> shape (N,) with ndim=4becomes a view of shape (1, 1, 1, N). Dimensions
>>>> are appended if *pos* is -1, so for example a 2-D array of shape (M, N)
>>>>  becomes a view of shape (M, N, 1, 1)when ndim=4.
>>>> *See also*
>>>> atleast_1d
>>>> <https://18298-908607-gh.circle-artifacts.com/0/doc/build/html/reference/generated/numpy.atleast_1d.html#numpy.atleast_1d>
>>>> , atleast_2d
>>>> <https://18298-908607-gh.circle-artifacts.com/0/doc/build/html/reference/generated/numpy.atleast_2d.html#numpy.atleast_2d>
>>>> , atleast_3d
>>>> <https://18298-908607-gh.circle-artifacts.com/0/doc/build/html/reference/generated/numpy.atleast_3d.html#numpy.atleast_3d>
>>>> *Notes*
>>>> This function does not follow the convention of the other atleast_*d functions
>>>> in numpy in that it only accepts a single array argument. To process
>>>> multiple arrays, use a comprehension or loop around the function call. See
>>>> examples below.
>>>> Setting pos=0 is equivalent to how the array would be interpreted by
>>>> numpy’s broadcasting rules. There is no need to call this function for
>>>> simple broadcasting. This is also roughly (but not exactly) equivalent to
>>>>  np.array(ary, copy=False, subok=True, ndmin=ndim).
>>>> It is easy to create functions for specific dimensions similar to the
>>>> other atleast_*d functions using Python’s functools.partial
>>>> <https://docs.python.org/dev/library/functools.html#functools.partial> function.
>>>> An example is shown below.
>>>> *Examples*
>>>>
>>>> >>> np.atleast_nd(3.0, 4)array([[[[ 3.]]]])
>>>>
>>>> >>> x = np.arange(3.0)>>> np.atleast_nd(x, 2).shape(1, 3)
>>>>
>>>> >>> x = np.arange(12.0).reshape(4, 3)>>> np.atleast_nd(x, 5).shape(1, 1, 1, 4, 3)>>> np.atleast_nd(x, 5).base is x.baseTrue
>>>>
>>>> >>> [np.atleast_nd(x) for x in ((1, 2), [[1, 2]], [[[1, 2]]])]:[array([[1, 2]]), array([[1, 2]]), array([[[1, 2]]])]
>>>>
>>>> >>> np.atleast_nd((1, 2), 5, pos=0).shape(1, 1, 1, 1, 2)>>> np.atleast_nd((1, 2), 5, pos=-1).shape(2, 1, 1, 1, 1)
>>>>
>>>> >>> from functools import partial>>> atleast_4d = partial(np.atleast_nd, ndim=4)>>> atleast_4d([1, 2, 3])[[[[1, 2, 3]]]]
>>>>
>>>>
>>>> _______________________________________________
>>>> NumPy-Discussion mailing list
>>>> NumPy-Discussion at python.org
>>>> https://mail.python.org/mailman/listinfo/numpy-discussion
>>>>
>>>>
>>>> _______________________________________________
>>>> NumPy-Discussion mailing list
>>>> NumPy-Discussion at python.org
>>>> https://mail.python.org/mailman/listinfo/numpy-discussion
>>>>
>>> _______________________________________________
>>> NumPy-Discussion mailing list
>>> NumPy-Discussion at python.org
>>> https://mail.python.org/mailman/listinfo/numpy-discussion
>>>
>> _______________________________________________
>> NumPy-Discussion mailing list
>> NumPy-Discussion at python.org
>> https://mail.python.org/mailman/listinfo/numpy-discussion
>>
> _______________________________________________
> NumPy-Discussion mailing list
> NumPy-Discussion at python.org
> https://mail.python.org/mailman/listinfo/numpy-discussion
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.python.org/pipermail/numpy-discussion/attachments/20210211/2f68d3b3/attachment-0001.html>


More information about the NumPy-Discussion mailing list