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).On Thu, Feb 11, 2021 at 1:56 AM Stephan Hoyer <[email protected]> wrote: > On Wed, Feb 10, 2021 at 9:48 PM Juan Nunez-Iglesias <[email protected]> > 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 <[email protected]> >> 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 >> [email protected] >> https://mail.python.org/mailman/listinfo/numpy-discussion >> >> >> _______________________________________________ >> NumPy-Discussion mailing list >> [email protected] >> https://mail.python.org/mailman/listinfo/numpy-discussion >> > _______________________________________________ > NumPy-Discussion mailing list > [email protected] > https://mail.python.org/mailman/listinfo/numpy-discussion >
_______________________________________________ NumPy-Discussion mailing list [email protected] https://mail.python.org/mailman/listinfo/numpy-discussion
