Source code for nums.numpy.api.manipulation

# Copyright (C) 2020 NumS Development Team.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# pylint: disable = redefined-builtin, too-many-lines, anomalous-backslash-in-string, unused-wildcard-import, wildcard-import, unused-import

import scipy
from scipy import stats

from nums.core.application_manager import instance as _instance
from nums.core.array.blockarray import BlockArray

from nums.numpy.api.logic import *

############################################
# Manipulation Ops
############################################


[docs]def atleast_1d(*arys): """Convert inputs to arrays with at least one dimension. This docstring was copied from numpy.atleast_1d. Some inconsistencies with the NumS version may exist. Scalar inputs are converted to 1-dimensional arrays, whilst higher-dimensional inputs are preserved. Parameters ---------- arys1, arys2, ... : BlockArray One or more input arrays. Returns ------- ret : BlockArray An array, or list of arrays, each with ``a.ndim >= 1``. Copies are made only if necessary. See Also -------- atleast_2d, atleast_3d Examples -------- The doctests shown below are copied from NumPy. They won’t show the correct result until you operate ``get()``. >>> nps.atleast_1d(1.0).get() # doctest: +SKIP array([1.]) >>> x = nps.arange(9.0).reshape(3,3) # doctest: +SKIP >>> nps.atleast_1d(x).get() # doctest: +SKIP array([[0., 1., 2.], [3., 4., 5.], [6., 7., 8.]]) >>> [a.get() for a in nps.atleast_1d(1, [3, 4])] # doctest: +SKIP [array([1]), array([3, 4])] """ return _instance().atleast_1d(*arys)
[docs]def atleast_2d(*arys): """View inputs as arrays with at least two dimensions. This docstring was copied from numpy.atleast_2d. Some inconsistencies with the NumS version may exist. Parameters ---------- arys1, arys2, ... : BlockArray One or more array-like sequences. Non-array inputs are converted to arrays. Arrays that already have two or more dimensions are preserved. Returns ------- res, res2, ... : BlockArray An array, or list of arrays, each with ``a.ndim >= 2``. Copies are avoided where possible, and views with two or more dimensions are returned. See Also -------- atleast_1d, atleast_3d Examples -------- The doctests shown below are copied from NumPy. They won’t show the correct result until you operate ``get()``. >>> nps.atleast_2d(3.0).get() # doctest: +SKIP array([[3.]]) >>> x = nps.arange(3.0) # doctest: +SKIP >>> nps.atleast_2d(x).get() # doctest: +SKIP array([[0., 1., 2.]]) >>> [a.get() for a in nps.atleast_2d(1, [1, 2], [[1, 3]])] # doctest: +SKIP [array([[1]]), array([[1, 2]]), array([[1, 2]])] """ return _instance().atleast_2d(*arys)
[docs]def atleast_3d(*arys): """View inputs as arrays with at least three dimensions. This docstring was copied from numpy.atleast_3d. Some inconsistencies with the NumS version may exist. Parameters ---------- arys1, arys2, ... : BlockArray One or more array-like sequences. Non-array inputs are converted to arrays. Arrays that already have three or more dimensions are preserved. Returns ------- res1, res2, ... : BlockArray An array, or list of arrays, each with ``a.ndim >= 3``. Copies are avoided where possible, and views with three or more dimensions are returned. For example, a 1-D array of shape ``(N,)`` becomes a view of shape ``(1, N, 1)``, and a 2-D array of shape ``(M, N)`` becomes a view of shape ``(M, N, 1)``. See Also -------- atleast_1d, atleast_2d Examples -------- The doctests shown below are copied from NumPy. They won’t show the correct result until you operate ``get()``. >>> nps.atleast_3d(3.0).get() # doctest: +SKIP array([[[3.]]]) >>> x = nps.arange(3.0) # doctest: +SKIP >>> nps.atleast_3d(x).shape # doctest: +SKIP (1, 3, 1) >>> x = nps.arange(12.0).reshape(4,3) # doctest: +SKIP >>> nps.atleast_3d(x).shape # doctest: +SKIP (4, 3, 1) >>> for arr in nps.atleast_3d([1, 2], [[1, 2]], [[[1, 2]]]): # doctest: +SKIP ... print(arr.get(), arr.shape) # doctest: +SKIP ... [[[1] [2]]] (1, 2, 1) [[[1] [2]]] (1, 2, 1) [[[1 2]]] (1, 1, 2) """ return _instance().atleast_3d(*arys)
[docs]def column_stack(tup): """Stack 1-D arrays as columns into a 2-D array. This docstring was copied from numpy.column_stack. Some inconsistencies with the NumS version may exist. Take a sequence of 1-D arrays and stack them as columns to make a single 2-D array. 2-D arrays are stacked as-is, just like with `hstack`. 1-D arrays are turned into 2-D columns first. Parameters ---------- tup : sequence of 1-D or 2-D arrays. Arrays to stack. All of them must have the same first dimension. Returns ------- stacked : 2-D array The array formed by stacking the given arrays. See Also -------- stack, hstack, vstack, concatenate Examples -------- The doctests shown below are copied from NumPy. They won’t show the correct result until you operate ``get()``. >>> a = nps.array((1,2,3)) # doctest: +SKIP >>> b = nps.array((2,3,4)) # doctest: +SKIP >>> nps.column_stack((a,b)).get() # doctest: +SKIP array([[1, 2], [2, 3], [3, 4]]) """ return _instance().column_stack(tup)
[docs]def concatenate(arrays, axis=0, out=None): """Join a sequence of arrays along an existing axis. This docstring was copied from numpy.concatenate. Some inconsistencies with the NumS version may exist. Parameters ---------- a1, a2, ... : sequence of array_like The arrays must have the same shape, except in the dimension corresponding to `axis` (the first, by default). axis : int, optional The axis along which the arrays will be joined. If axis is None, arrays are flattened before use. Default is 0. out : BlockArray, optional If provided, the destination to place the result. The shape must be correct, matching that of what concatenate would have returned if no out argument were specified. Returns ------- res : BlockArray The concatenated array. See Also -------- ma.concatenate : Concatenate function that preserves input masks. array_split : Split an array into multiple sub-arrays of equal or near-equal size. split : Split array into a list of multiple sub-arrays of equal size. hsplit : Split array into multiple sub-arrays horizontally (column wise). vsplit : Split array into multiple sub-arrays vertically (row wise). dsplit : Split array into multiple sub-arrays along the 3rd axis (depth). stack : Stack a sequence of arrays along a new axis. block : Assemble arrays from blocks. hstack : Stack arrays in sequence horizontally (column wise). vstack : Stack arrays in sequence vertically (row wise). dstack : Stack arrays in sequence depth wise (along third dimension). column_stack : Stack 1-D arrays as columns into a 2-D array. Notes ----- When one or more of the arrays to be concatenated is a MaskedArray, this function will return a MaskedArray object instead of an BlockArray, but the input masks are *not* preserved. In cases where a MaskedArray is expected as input, use the ma.concatenate function from the masked array module instead. out is currently not supported for concatenate. Examples -------- The doctests shown below are copied from NumPy. They won’t show the correct result until you operate ``get()``. >>> a = nps.array([[1, 2], [3, 4]]) # doctest: +SKIP >>> b = nps.array([[5, 6]]) # doctest: +SKIP >>> nps.concatenate((a, b), axis=0).get() # doctest: +SKIP array([[1, 2], [3, 4], [5, 6]]) >>> nps.concatenate((a, b.T), axis=1).get() # doctest: +SKIP array([[1, 2, 5], [3, 4, 6]]) """ if out is not None: raise NotImplementedError("out is currently not supported for concatenate.") # Pick the mode along specified axis. axis_block_size = stats.mode( list(map(lambda arr: arr.block_shape[axis], arrays)) ).mode.item() return _instance().concatenate(arrays, axis=axis, axis_block_size=axis_block_size)
[docs]def dstack(tup): """Stack arrays in sequence depth wise (along third axis). This docstring was copied from numpy.dstack. Some inconsistencies with the NumS version may exist. This is equivalent to concatenation along the third axis after 2-D arrays of shape `(M,N)` have been reshaped to `(M,N,1)` and 1-D arrays of shape `(N,)` have been reshaped to `(1,N,1)`. Rebuilds arrays divided by `dsplit`. This function makes most sense for arrays with up to 3 dimensions. For instance, for pixel-data with a height (first axis), width (second axis), and r/g/b channels (third axis). The functions `concatenate`, `stack` and `block` provide more general stacking and concatenation operations. Parameters ---------- tup : sequence of arrays The arrays must have the same shape along all but the third axis. 1-D or 2-D arrays must have the same shape. Returns ------- stacked : BlockArray The array formed by stacking the given arrays, will be at least 3-D. See Also -------- concatenate : Join a sequence of arrays along an existing axis. stack : Join a sequence of arrays along a new axis. block : Assemble an nd-array from nested lists of blocks. vstack : Stack arrays in sequence vertically (row wise). hstack : Stack arrays in sequence horizontally (column wise). column_stack : Stack 1-D arrays as columns into a 2-D array. dsplit : Split array along third axis. Examples -------- The doctests shown below are copied from NumPy. They won’t show the correct result until you operate ``get()``. >>> a = nps.array((1,2,3)) # doctest: +SKIP >>> b = nps.array((2,3,4)) # doctest: +SKIP >>> nps.dstack((a,b)).get() # doctest: +SKIP array([[[1, 2], [2, 3], [3, 4]]]) >>> a = nps.array([[1],[2],[3]]) # doctest: +SKIP >>> b = nps.array([[2],[3],[4]]) # doctest: +SKIP >>> nps.dstack((a,b)).get() # doctest: +SKIP array([[[1, 2]], [[2, 3]], [[3, 4]]]) """ return _instance().dstack(tup)
[docs]def expand_dims(a: BlockArray, axis): """Expand the shape of an array. This docstring was copied from numpy.expand_dims. Some inconsistencies with the NumS version may exist. Insert a new axis that will appear at the `axis` position in the expanded array shape. Parameters ---------- a : BlockArray Input array. axis : int or tuple of ints Position in the expanded axes where the new axis (or axes) is placed. Returns ------- result : BlockArray View of `a` with the number of dimensions increased. See Also -------- squeeze : The inverse operation, removing singleton dimensions reshape : Insert, remove, and combine dimensions, and resize existing ones atleast_1d, atleast_2d, atleast_3d Examples -------- The doctests shown below are copied from NumPy. They won’t show the correct result until you operate ``get()``. >>> x = nps.array([1, 2]) # doctest: +SKIP >>> x.shape # doctest: +SKIP (2,) The following is equivalent to ``x[nps.newaxis, :]`` or ``x[nps.newaxis]``: >>> y = nps.expand_dims(x, axis=0) # doctest: +SKIP >>> y.get() # doctest: +SKIP array([[1, 2]]) >>> y.shape # doctest: +SKIP (1, 2) The following is equivalent to ``x[:, nps.newaxis]``: >>> y = nps.expand_dims(x, axis=1) # doctest: +SKIP >>> y.get() # doctest: +SKIP array([[1], [2]]) >>> y.shape # doctest: +SKIP (2, 1) ``axis`` may also be a tuple: >>> y = nps.expand_dims(x, axis=(0, 1)) # doctest: +SKIP >>> y.get() # doctest: +SKIP array([[[1, 2]]]) >>> y = nps.expand_dims(x, axis=(2, 0)) # doctest: +SKIP >>> y.get() # doctest: +SKIP array([[[1], [2]]]) """ return a.expand_dims(axis)
[docs]def hstack(tup): """Stack arrays in sequence horizontally (column wise). This docstring was copied from numpy.hstack. Some inconsistencies with the NumS version may exist. This is equivalent to concatenation along the second axis, except for 1-D arrays where it concatenates along the first axis. Rebuilds arrays divided by `hsplit`. This function makes most sense for arrays with up to 3 dimensions. For instance, for pixel-data with a height (first axis), width (second axis), and r/g/b channels (third axis). The functions `concatenate`, `stack` and `block` provide more general stacking and concatenation operations. Parameters ---------- tup : sequence of BlockArray The arrays must have the same shape along all but the second axis, except 1-D arrays which can be any length. Returns ------- stacked : BlockArray The array formed by stacking the given arrays. See Also -------- concatenate : Join a sequence of arrays along an existing axis. stack : Join a sequence of arrays along a new axis. block : Assemble an nd-array from nested lists of blocks. vstack : Stack arrays in sequence vertically (row wise). dstack : Stack arrays in sequence depth wise (along third axis). column_stack : Stack 1-D arrays as columns into a 2-D array. hsplit : Split an array into multiple sub-arrays horizontally (column-wise). Examples -------- The doctests shown below are copied from NumPy. They won’t show the correct result until you operate ``get()``. >>> a = nps.array((1,2,3)) # doctest: +SKIP >>> b = nps.array((2,3,4)) # doctest: +SKIP >>> nps.hstack((a,b)).get() # doctest: +SKIP array([1, 2, 3, 2, 3, 4]) >>> a = nps.array([[1],[2],[3]]) # doctest: +SKIP >>> b = nps.array([[2],[3],[4]]) # doctest: +SKIP >>> nps.hstack((a,b)).get() # doctest: +SKIP array([[1, 2], [2, 3], [3, 4]]) """ return _instance().hstack(tup)
[docs]def reshape(a: BlockArray, shape): """Gives a new shape to an array without changing its data. This docstring was copied from numpy.reshape. Some inconsistencies with the NumS version may exist. Parameters ---------- a : BlockArray Array to be reshaped. Returns ------- reshaped_array : BlockArray This will be a new view object if possible; otherwise, it will be a copy. """ block_shape = _instance().compute_block_shape(shape, a.dtype) return a.reshape(shape, block_shape=block_shape)
[docs]def row_stack(tup): """Stack arrays in sequence vertically (row wise). This docstring was copied from numpy.row_stack. Some inconsistencies with the NumS version may exist. This is equivalent to concatenation along the first axis after 1-D arrays of shape `(N,)` have been reshaped to `(1,N)`. Rebuilds arrays divided by `vsplit`. This function makes most sense for arrays with up to 3 dimensions. For instance, for pixel-data with a height (first axis), width (second axis), and r/g/b channels (third axis). The functions `concatenate`, `stack` and `block` provide more general stacking and concatenation operations. Parameters ---------- tup : sequence of BlockArrays The arrays must have the same shape along all but the first axis. 1-D arrays must have the same length. Returns ------- stacked : BlockArray The array formed by stacking the given arrays, will be at least 2-D. See Also -------- concatenate : Join a sequence of arrays along an existing axis. stack : Join a sequence of arrays along a new axis. block : Assemble an nd-array from nested lists of blocks. hstack : Stack arrays in sequence horizontally (column wise). dstack : Stack arrays in sequence depth wise (along third axis). column_stack : Stack 1-D arrays as columns into a 2-D array. vsplit : Split an array into multiple sub-arrays vertically (row-wise). Examples -------- The doctests shown below are copied from NumPy. They won’t show the correct result until you operate ``get()``. >>> a = nps.array([1, 2, 3]) # doctest: +SKIP >>> b = nps.array([2, 3, 4]) # doctest: +SKIP >>> nps.vstack((a,b)).get() # doctest: +SKIP array([[1, 2, 3], [2, 3, 4]]) >>> a = nps.array([[1], [2], [3]]) # doctest: +SKIP >>> b = nps.array([[2], [3], [4]]) # doctest: +SKIP >>> nps.vstack((a,b)).get() # doctest: +SKIP array([[1], [2], [3], [2], [3], [4]]) """ return _instance().row_stack(tup)
[docs]def squeeze(a: BlockArray, axis=None): """Remove single-dimensional entries from the shape of an array. This docstring was copied from numpy.squeeze. Some inconsistencies with the NumS version may exist. Parameters ---------- a : BlockArray Input data. Returns ------- squeezed : BlockArray The input array, but with all or a subset of the dimensions of length 1 removed. This is always `a` itself or a view into `a`. See Also -------- expand_dims : The inverse operation, adding singleton dimensions reshape : Insert, remove, and combine dimensions, and resize existing ones Notes ----- axis not supported. Examples -------- The doctests shown below are copied from NumPy. They won’t show the correct result until you operate ``get()``. >>> x = nps.array([[[0], [1], [2]]]) # doctest: +SKIP >>> x.shape # doctest: +SKIP (1, 3, 1) >>> nps.squeeze(x).shape # doctest: +SKIP (3,) >>> x = nps.array([[1234]]) # doctest: +SKIP >>> x.shape # doctest: +SKIP (1, 1) >>> nps.squeeze(x).get() # doctest: +SKIP array(1234) # 0d array >>> nps.squeeze(x).shape # doctest: +SKIP () >>> nps.squeeze(x)[()].get() # doctest: +SKIP array(1234) """ assert axis is None, "axis not supported." return a.squeeze()
[docs]def split(ary: BlockArray, indices_or_sections, axis=0): """Split an array into multiple sub-arrays as views into `ary`. This docstring was copied from numpy.split. Some inconsistencies with the NumS version may exist. Parameters ---------- ary : BlockArray Array to be divided into sub-arrays. indices_or_sections : int or 1-D array If `indices_or_sections` is an integer, N, the array will be divided into N equal arrays along `axis`. If such a split is not possible, an error is raised. If `indices_or_sections` is a 1-D array of sorted integers, the entries indicate where along `axis` the array is split. For example, ``[2, 3]`` would, for ``axis=0``, result in - ary[:2] - ary[2:3] - ary[3:] If an index exceeds the dimension of the array along `axis`, an empty sub-array is returned correspondingly. axis : int, optional The axis along which to split, default is 0. Returns ------- sub-arrays : list of BlockArrays A list of sub-arrays as views into `ary`. Raises ------ ValueError If `indices_or_sections` is given as an integer, but a split does not result in equal division. See Also -------- array_split : Split an array into multiple sub-arrays of equal or near-equal size. Does not raise an exception if an equal division cannot be made. hsplit : Split array into multiple sub-arrays horizontally (column-wise). vsplit : Split array into multiple sub-arrays vertically (row wise). dsplit : Split array into multiple sub-arrays along the 3rd axis (depth). concatenate : Join a sequence of arrays along an existing axis. stack : Join a sequence of arrays along a new axis. hstack : Stack arrays in sequence horizontally (column wise). vstack : Stack arrays in sequence vertically (row wise). dstack : Stack arrays in sequence depth wise (along third dimension). Notes ----- Split currently supports integers only. Examples -------- The doctests shown below are copied from NumPy. They won’t show the correct result until you operate ``get()``. >>> x = nps.arange(9.0) # doctest: +SKIP >>> [a.get() for a in nps.split(x, 3)] # doctest: +SKIP [array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7., 8.])] """ if not isinstance(indices_or_sections, int): raise NotImplementedError("Split currently supports integers only.") dim_total = ary.shape[axis] # Splits into N equal arrays, and raise if this is not possible. if dim_total % indices_or_sections != 0: raise ValueError( "ary axis %s cannot be split into %s equal arrays." % (axis, indices_or_sections) ) dim_partial = dim_total // indices_or_sections results = [] ss_op = [slice(None, None, 1) for _ in ary.shape] for i in range(0, dim_total, dim_partial): start = i stop = i + dim_partial ss_op[axis] = slice(start, stop, 1) ary_part = ary[tuple(ss_op)] results.append(ary_part) return tuple(results)
[docs]def swapaxes(a: BlockArray, axis1: int, axis2: int): """Interchange two axes of an array. This docstring was copied from numpy.swapaxes. Some inconsistencies with the NumS version may exist. Parameters ---------- a : BlockArray Input array. axis1 : int First axis. axis2 : int Second axis. Returns ------- a_swapped : BlockArray For NumPy >= 1.10.0, if `a` is an BlockArray, then a view of `a` is returned; otherwise a new array is created. For earlier NumPy versions a view of `a` is returned only if the order of the axes is changed, otherwise the input array is returned. Examples -------- The doctests shown below are copied from NumPy. They won’t show the correct result until you operate ``get()``. >>> x = nps.array([[1,2,3]]) # doctest: +SKIP >>> nps.swapaxes(x,0,1).get() # doctest: +SKIP array([[1], [2], [3]]) >>> x = nps.array([[[0,1],[2,3]],[[4,5],[6,7]]]) # doctest: +SKIP >>> x.get() # doctest: +SKIP array([[[0, 1], [2, 3]], [[4, 5], [6, 7]]]) >>> nps.swapaxes(x,0,2).get() # doctest: +SKIP array([[[0, 4], [2, 6]], [[1, 5], [3, 7]]]) """ return a.swapaxes(axis1, axis2)
[docs]def transpose(a: BlockArray, axes=None): """Reverse or permute the axes of an array; returns the modified array. This docstring was copied from numpy.transpose. Some inconsistencies with the NumS version may exist. For an array a with two axes, transpose(a) gives the matrix transpose. Parameters ---------- a : BlockArray Input array. Returns ------- p : BlockArray `a` with its axes permuted. A view is returned whenever possible. Notes ----- Transposing a 1-D array returns an unchanged view of the original array. axes not supported. Examples -------- The doctests shown below are copied from NumPy. They won’t show the correct result until you operate ``get()``. >>> x = nps.arange(4).reshape((2,2)) # doctest: +SKIP >>> x.get() # doctest: +SKIP array([[0, 1], [2, 3]]) >>> nps.transpose(x).get() # doctest: +SKIP array([[0, 2], [1, 3]]) """ assert axes is None, "axes not supported." return a.T
[docs]def vstack(tup): """Stack arrays in sequence vertically (row wise). This docstring was copied from numpy.vstack. Some inconsistencies with the NumS version may exist. This is equivalent to concatenation along the first axis after 1-D arrays of shape `(N,)` have been reshaped to `(1,N)`. Rebuilds arrays divided by `vsplit`. This function makes most sense for arrays with up to 3 dimensions. For instance, for pixel-data with a height (first axis), width (second axis), and r/g/b channels (third axis). The functions `concatenate`, `stack` and `block` provide more general stacking and concatenation operations. Parameters ---------- tup : sequence of BlockArrays The arrays must have the same shape along all but the first axis. 1-D arrays must have the same length. Returns ------- stacked : BlockArray The array formed by stacking the given arrays, will be at least 2-D. See Also -------- concatenate : Join a sequence of arrays along an existing axis. stack : Join a sequence of arrays along a new axis. block : Assemble an nd-array from nested lists of blocks. hstack : Stack arrays in sequence horizontally (column wise). dstack : Stack arrays in sequence depth wise (along third axis). column_stack : Stack 1-D arrays as columns into a 2-D array. vsplit : Split an array into multiple sub-arrays vertically (row-wise). Examples -------- The doctests shown below are copied from NumPy. They won’t show the correct result until you operate ``get()``. >>> a = nps.array([1, 2, 3]) # doctest: +SKIP >>> b = nps.array([2, 3, 4]) # doctest: +SKIP >>> nps.vstack((a,b)).get() # doctest: +SKIP array([[1, 2, 3], [2, 3, 4]]) >>> a = nps.array([[1], [2], [3]]) # doctest: +SKIP >>> b = nps.array([[2], [3], [4]]) # doctest: +SKIP >>> nps.vstack((a,b)).get() # doctest: +SKIP array([[1], [2], [3], [2], [3], [4]]) """ return _instance().vstack(tup)