Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/numpy/lib/shape_base.py: 17%
257 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1import functools
3import numpy.core.numeric as _nx
4from numpy.core.numeric import (
5 asarray, zeros, outer, concatenate, array, asanyarray
6 )
7from numpy.core.fromnumeric import reshape, transpose
8from numpy.core.multiarray import normalize_axis_index
9from numpy.core import overrides
10from numpy.core import vstack, atleast_3d
11from numpy.core.numeric import normalize_axis_tuple
12from numpy.core.shape_base import _arrays_for_stack_dispatcher
13from numpy.lib.index_tricks import ndindex
14from numpy.matrixlib.defmatrix import matrix # this raises all the right alarm bells
17__all__ = [
18 'column_stack', 'row_stack', 'dstack', 'array_split', 'split',
19 'hsplit', 'vsplit', 'dsplit', 'apply_over_axes', 'expand_dims',
20 'apply_along_axis', 'kron', 'tile', 'get_array_wrap', 'take_along_axis',
21 'put_along_axis'
22 ]
25array_function_dispatch = functools.partial(
26 overrides.array_function_dispatch, module='numpy')
29def _make_along_axis_idx(arr_shape, indices, axis):
30 # compute dimensions to iterate over
31 if not _nx.issubdtype(indices.dtype, _nx.integer):
32 raise IndexError('`indices` must be an integer array')
33 if len(arr_shape) != indices.ndim:
34 raise ValueError(
35 "`indices` and `arr` must have the same number of dimensions")
36 shape_ones = (1,) * indices.ndim
37 dest_dims = list(range(axis)) + [None] + list(range(axis+1, indices.ndim))
39 # build a fancy index, consisting of orthogonal aranges, with the
40 # requested index inserted at the right location
41 fancy_index = []
42 for dim, n in zip(dest_dims, arr_shape):
43 if dim is None:
44 fancy_index.append(indices)
45 else:
46 ind_shape = shape_ones[:dim] + (-1,) + shape_ones[dim+1:]
47 fancy_index.append(_nx.arange(n).reshape(ind_shape))
49 return tuple(fancy_index)
52def _take_along_axis_dispatcher(arr, indices, axis):
53 return (arr, indices)
56@array_function_dispatch(_take_along_axis_dispatcher)
57def take_along_axis(arr, indices, axis):
58 """
59 Take values from the input array by matching 1d index and data slices.
61 This iterates over matching 1d slices oriented along the specified axis in
62 the index and data arrays, and uses the former to look up values in the
63 latter. These slices can be different lengths.
65 Functions returning an index along an axis, like `argsort` and
66 `argpartition`, produce suitable indices for this function.
68 .. versionadded:: 1.15.0
70 Parameters
71 ----------
72 arr : ndarray (Ni..., M, Nk...)
73 Source array
74 indices : ndarray (Ni..., J, Nk...)
75 Indices to take along each 1d slice of `arr`. This must match the
76 dimension of arr, but dimensions Ni and Nj only need to broadcast
77 against `arr`.
78 axis : int
79 The axis to take 1d slices along. If axis is None, the input array is
80 treated as if it had first been flattened to 1d, for consistency with
81 `sort` and `argsort`.
83 Returns
84 -------
85 out: ndarray (Ni..., J, Nk...)
86 The indexed result.
88 Notes
89 -----
90 This is equivalent to (but faster than) the following use of `ndindex` and
91 `s_`, which sets each of ``ii`` and ``kk`` to a tuple of indices::
93 Ni, M, Nk = a.shape[:axis], a.shape[axis], a.shape[axis+1:]
94 J = indices.shape[axis] # Need not equal M
95 out = np.empty(Ni + (J,) + Nk)
97 for ii in ndindex(Ni):
98 for kk in ndindex(Nk):
99 a_1d = a [ii + s_[:,] + kk]
100 indices_1d = indices[ii + s_[:,] + kk]
101 out_1d = out [ii + s_[:,] + kk]
102 for j in range(J):
103 out_1d[j] = a_1d[indices_1d[j]]
105 Equivalently, eliminating the inner loop, the last two lines would be::
107 out_1d[:] = a_1d[indices_1d]
109 See Also
110 --------
111 take : Take along an axis, using the same indices for every 1d slice
112 put_along_axis :
113 Put values into the destination array by matching 1d index and data slices
115 Examples
116 --------
118 For this sample array
120 >>> a = np.array([[10, 30, 20], [60, 40, 50]])
122 We can sort either by using sort directly, or argsort and this function
124 >>> np.sort(a, axis=1)
125 array([[10, 20, 30],
126 [40, 50, 60]])
127 >>> ai = np.argsort(a, axis=1); ai
128 array([[0, 2, 1],
129 [1, 2, 0]])
130 >>> np.take_along_axis(a, ai, axis=1)
131 array([[10, 20, 30],
132 [40, 50, 60]])
134 The same works for max and min, if you expand the dimensions:
136 >>> np.expand_dims(np.max(a, axis=1), axis=1)
137 array([[30],
138 [60]])
139 >>> ai = np.expand_dims(np.argmax(a, axis=1), axis=1)
140 >>> ai
141 array([[1],
142 [0]])
143 >>> np.take_along_axis(a, ai, axis=1)
144 array([[30],
145 [60]])
147 If we want to get the max and min at the same time, we can stack the
148 indices first
150 >>> ai_min = np.expand_dims(np.argmin(a, axis=1), axis=1)
151 >>> ai_max = np.expand_dims(np.argmax(a, axis=1), axis=1)
152 >>> ai = np.concatenate([ai_min, ai_max], axis=1)
153 >>> ai
154 array([[0, 1],
155 [1, 0]])
156 >>> np.take_along_axis(a, ai, axis=1)
157 array([[10, 30],
158 [40, 60]])
159 """
160 # normalize inputs
161 if axis is None:
162 arr = arr.flat
163 arr_shape = (len(arr),) # flatiter has no .shape
164 axis = 0
165 else:
166 axis = normalize_axis_index(axis, arr.ndim)
167 arr_shape = arr.shape
169 # use the fancy index
170 return arr[_make_along_axis_idx(arr_shape, indices, axis)]
173def _put_along_axis_dispatcher(arr, indices, values, axis):
174 return (arr, indices, values)
177@array_function_dispatch(_put_along_axis_dispatcher)
178def put_along_axis(arr, indices, values, axis):
179 """
180 Put values into the destination array by matching 1d index and data slices.
182 This iterates over matching 1d slices oriented along the specified axis in
183 the index and data arrays, and uses the former to place values into the
184 latter. These slices can be different lengths.
186 Functions returning an index along an axis, like `argsort` and
187 `argpartition`, produce suitable indices for this function.
189 .. versionadded:: 1.15.0
191 Parameters
192 ----------
193 arr : ndarray (Ni..., M, Nk...)
194 Destination array.
195 indices : ndarray (Ni..., J, Nk...)
196 Indices to change along each 1d slice of `arr`. This must match the
197 dimension of arr, but dimensions in Ni and Nj may be 1 to broadcast
198 against `arr`.
199 values : array_like (Ni..., J, Nk...)
200 values to insert at those indices. Its shape and dimension are
201 broadcast to match that of `indices`.
202 axis : int
203 The axis to take 1d slices along. If axis is None, the destination
204 array is treated as if a flattened 1d view had been created of it.
206 Notes
207 -----
208 This is equivalent to (but faster than) the following use of `ndindex` and
209 `s_`, which sets each of ``ii`` and ``kk`` to a tuple of indices::
211 Ni, M, Nk = a.shape[:axis], a.shape[axis], a.shape[axis+1:]
212 J = indices.shape[axis] # Need not equal M
214 for ii in ndindex(Ni):
215 for kk in ndindex(Nk):
216 a_1d = a [ii + s_[:,] + kk]
217 indices_1d = indices[ii + s_[:,] + kk]
218 values_1d = values [ii + s_[:,] + kk]
219 for j in range(J):
220 a_1d[indices_1d[j]] = values_1d[j]
222 Equivalently, eliminating the inner loop, the last two lines would be::
224 a_1d[indices_1d] = values_1d
226 See Also
227 --------
228 take_along_axis :
229 Take values from the input array by matching 1d index and data slices
231 Examples
232 --------
234 For this sample array
236 >>> a = np.array([[10, 30, 20], [60, 40, 50]])
238 We can replace the maximum values with:
240 >>> ai = np.expand_dims(np.argmax(a, axis=1), axis=1)
241 >>> ai
242 array([[1],
243 [0]])
244 >>> np.put_along_axis(a, ai, 99, axis=1)
245 >>> a
246 array([[10, 99, 20],
247 [99, 40, 50]])
249 """
250 # normalize inputs
251 if axis is None:
252 arr = arr.flat
253 axis = 0
254 arr_shape = (len(arr),) # flatiter has no .shape
255 else:
256 axis = normalize_axis_index(axis, arr.ndim)
257 arr_shape = arr.shape
259 # use the fancy index
260 arr[_make_along_axis_idx(arr_shape, indices, axis)] = values
263def _apply_along_axis_dispatcher(func1d, axis, arr, *args, **kwargs):
264 return (arr,)
267@array_function_dispatch(_apply_along_axis_dispatcher)
268def apply_along_axis(func1d, axis, arr, *args, **kwargs):
269 """
270 Apply a function to 1-D slices along the given axis.
272 Execute `func1d(a, *args, **kwargs)` where `func1d` operates on 1-D arrays
273 and `a` is a 1-D slice of `arr` along `axis`.
275 This is equivalent to (but faster than) the following use of `ndindex` and
276 `s_`, which sets each of ``ii``, ``jj``, and ``kk`` to a tuple of indices::
278 Ni, Nk = a.shape[:axis], a.shape[axis+1:]
279 for ii in ndindex(Ni):
280 for kk in ndindex(Nk):
281 f = func1d(arr[ii + s_[:,] + kk])
282 Nj = f.shape
283 for jj in ndindex(Nj):
284 out[ii + jj + kk] = f[jj]
286 Equivalently, eliminating the inner loop, this can be expressed as::
288 Ni, Nk = a.shape[:axis], a.shape[axis+1:]
289 for ii in ndindex(Ni):
290 for kk in ndindex(Nk):
291 out[ii + s_[...,] + kk] = func1d(arr[ii + s_[:,] + kk])
293 Parameters
294 ----------
295 func1d : function (M,) -> (Nj...)
296 This function should accept 1-D arrays. It is applied to 1-D
297 slices of `arr` along the specified axis.
298 axis : integer
299 Axis along which `arr` is sliced.
300 arr : ndarray (Ni..., M, Nk...)
301 Input array.
302 args : any
303 Additional arguments to `func1d`.
304 kwargs : any
305 Additional named arguments to `func1d`.
307 .. versionadded:: 1.9.0
310 Returns
311 -------
312 out : ndarray (Ni..., Nj..., Nk...)
313 The output array. The shape of `out` is identical to the shape of
314 `arr`, except along the `axis` dimension. This axis is removed, and
315 replaced with new dimensions equal to the shape of the return value
316 of `func1d`. So if `func1d` returns a scalar `out` will have one
317 fewer dimensions than `arr`.
319 See Also
320 --------
321 apply_over_axes : Apply a function repeatedly over multiple axes.
323 Examples
324 --------
325 >>> def my_func(a):
326 ... \"\"\"Average first and last element of a 1-D array\"\"\"
327 ... return (a[0] + a[-1]) * 0.5
328 >>> b = np.array([[1,2,3], [4,5,6], [7,8,9]])
329 >>> np.apply_along_axis(my_func, 0, b)
330 array([4., 5., 6.])
331 >>> np.apply_along_axis(my_func, 1, b)
332 array([2., 5., 8.])
334 For a function that returns a 1D array, the number of dimensions in
335 `outarr` is the same as `arr`.
337 >>> b = np.array([[8,1,7], [4,3,9], [5,2,6]])
338 >>> np.apply_along_axis(sorted, 1, b)
339 array([[1, 7, 8],
340 [3, 4, 9],
341 [2, 5, 6]])
343 For a function that returns a higher dimensional array, those dimensions
344 are inserted in place of the `axis` dimension.
346 >>> b = np.array([[1,2,3], [4,5,6], [7,8,9]])
347 >>> np.apply_along_axis(np.diag, -1, b)
348 array([[[1, 0, 0],
349 [0, 2, 0],
350 [0, 0, 3]],
351 [[4, 0, 0],
352 [0, 5, 0],
353 [0, 0, 6]],
354 [[7, 0, 0],
355 [0, 8, 0],
356 [0, 0, 9]]])
357 """
358 # handle negative axes
359 arr = asanyarray(arr)
360 nd = arr.ndim
361 axis = normalize_axis_index(axis, nd)
363 # arr, with the iteration axis at the end
364 in_dims = list(range(nd))
365 inarr_view = transpose(arr, in_dims[:axis] + in_dims[axis+1:] + [axis])
367 # compute indices for the iteration axes, and append a trailing ellipsis to
368 # prevent 0d arrays decaying to scalars, which fixes gh-8642
369 inds = ndindex(inarr_view.shape[:-1])
370 inds = (ind + (Ellipsis,) for ind in inds)
372 # invoke the function on the first item
373 try:
374 ind0 = next(inds)
375 except StopIteration as e:
376 raise ValueError(
377 'Cannot apply_along_axis when any iteration dimensions are 0'
378 ) from None
379 res = asanyarray(func1d(inarr_view[ind0], *args, **kwargs))
381 # build a buffer for storing evaluations of func1d.
382 # remove the requested axis, and add the new ones on the end.
383 # laid out so that each write is contiguous.
384 # for a tuple index inds, buff[inds] = func1d(inarr_view[inds])
385 buff = zeros(inarr_view.shape[:-1] + res.shape, res.dtype)
387 # permutation of axes such that out = buff.transpose(buff_permute)
388 buff_dims = list(range(buff.ndim))
389 buff_permute = (
390 buff_dims[0 : axis] +
391 buff_dims[buff.ndim-res.ndim : buff.ndim] +
392 buff_dims[axis : buff.ndim-res.ndim]
393 )
395 # matrices have a nasty __array_prepare__ and __array_wrap__
396 if not isinstance(res, matrix):
397 buff = res.__array_prepare__(buff)
399 # save the first result, then compute and save all remaining results
400 buff[ind0] = res
401 for ind in inds:
402 buff[ind] = asanyarray(func1d(inarr_view[ind], *args, **kwargs))
404 if not isinstance(res, matrix):
405 # wrap the array, to preserve subclasses
406 buff = res.__array_wrap__(buff)
408 # finally, rotate the inserted axes back to where they belong
409 return transpose(buff, buff_permute)
411 else:
412 # matrices have to be transposed first, because they collapse dimensions!
413 out_arr = transpose(buff, buff_permute)
414 return res.__array_wrap__(out_arr)
417def _apply_over_axes_dispatcher(func, a, axes):
418 return (a,)
421@array_function_dispatch(_apply_over_axes_dispatcher)
422def apply_over_axes(func, a, axes):
423 """
424 Apply a function repeatedly over multiple axes.
426 `func` is called as `res = func(a, axis)`, where `axis` is the first
427 element of `axes`. The result `res` of the function call must have
428 either the same dimensions as `a` or one less dimension. If `res`
429 has one less dimension than `a`, a dimension is inserted before
430 `axis`. The call to `func` is then repeated for each axis in `axes`,
431 with `res` as the first argument.
433 Parameters
434 ----------
435 func : function
436 This function must take two arguments, `func(a, axis)`.
437 a : array_like
438 Input array.
439 axes : array_like
440 Axes over which `func` is applied; the elements must be integers.
442 Returns
443 -------
444 apply_over_axis : ndarray
445 The output array. The number of dimensions is the same as `a`,
446 but the shape can be different. This depends on whether `func`
447 changes the shape of its output with respect to its input.
449 See Also
450 --------
451 apply_along_axis :
452 Apply a function to 1-D slices of an array along the given axis.
454 Notes
455 -----
456 This function is equivalent to tuple axis arguments to reorderable ufuncs
457 with keepdims=True. Tuple axis arguments to ufuncs have been available since
458 version 1.7.0.
460 Examples
461 --------
462 >>> a = np.arange(24).reshape(2,3,4)
463 >>> a
464 array([[[ 0, 1, 2, 3],
465 [ 4, 5, 6, 7],
466 [ 8, 9, 10, 11]],
467 [[12, 13, 14, 15],
468 [16, 17, 18, 19],
469 [20, 21, 22, 23]]])
471 Sum over axes 0 and 2. The result has same number of dimensions
472 as the original array:
474 >>> np.apply_over_axes(np.sum, a, [0,2])
475 array([[[ 60],
476 [ 92],
477 [124]]])
479 Tuple axis arguments to ufuncs are equivalent:
481 >>> np.sum(a, axis=(0,2), keepdims=True)
482 array([[[ 60],
483 [ 92],
484 [124]]])
486 """
487 val = asarray(a)
488 N = a.ndim
489 if array(axes).ndim == 0:
490 axes = (axes,)
491 for axis in axes:
492 if axis < 0:
493 axis = N + axis
494 args = (val, axis)
495 res = func(*args)
496 if res.ndim == val.ndim:
497 val = res
498 else:
499 res = expand_dims(res, axis)
500 if res.ndim == val.ndim:
501 val = res
502 else:
503 raise ValueError("function is not returning "
504 "an array of the correct shape")
505 return val
508def _expand_dims_dispatcher(a, axis):
509 return (a,)
512@array_function_dispatch(_expand_dims_dispatcher)
513def expand_dims(a, axis):
514 """
515 Expand the shape of an array.
517 Insert a new axis that will appear at the `axis` position in the expanded
518 array shape.
520 Parameters
521 ----------
522 a : array_like
523 Input array.
524 axis : int or tuple of ints
525 Position in the expanded axes where the new axis (or axes) is placed.
527 .. deprecated:: 1.13.0
528 Passing an axis where ``axis > a.ndim`` will be treated as
529 ``axis == a.ndim``, and passing ``axis < -a.ndim - 1`` will
530 be treated as ``axis == 0``. This behavior is deprecated.
532 .. versionchanged:: 1.18.0
533 A tuple of axes is now supported. Out of range axes as
534 described above are now forbidden and raise an `AxisError`.
536 Returns
537 -------
538 result : ndarray
539 View of `a` with the number of dimensions increased.
541 See Also
542 --------
543 squeeze : The inverse operation, removing singleton dimensions
544 reshape : Insert, remove, and combine dimensions, and resize existing ones
545 doc.indexing, atleast_1d, atleast_2d, atleast_3d
547 Examples
548 --------
549 >>> x = np.array([1, 2])
550 >>> x.shape
551 (2,)
553 The following is equivalent to ``x[np.newaxis, :]`` or ``x[np.newaxis]``:
555 >>> y = np.expand_dims(x, axis=0)
556 >>> y
557 array([[1, 2]])
558 >>> y.shape
559 (1, 2)
561 The following is equivalent to ``x[:, np.newaxis]``:
563 >>> y = np.expand_dims(x, axis=1)
564 >>> y
565 array([[1],
566 [2]])
567 >>> y.shape
568 (2, 1)
570 ``axis`` may also be a tuple:
572 >>> y = np.expand_dims(x, axis=(0, 1))
573 >>> y
574 array([[[1, 2]]])
576 >>> y = np.expand_dims(x, axis=(2, 0))
577 >>> y
578 array([[[1],
579 [2]]])
581 Note that some examples may use ``None`` instead of ``np.newaxis``. These
582 are the same objects:
584 >>> np.newaxis is None
585 True
587 """
588 if isinstance(a, matrix):
589 a = asarray(a)
590 else:
591 a = asanyarray(a)
593 if type(axis) not in (tuple, list):
594 axis = (axis,)
596 out_ndim = len(axis) + a.ndim
597 axis = normalize_axis_tuple(axis, out_ndim)
599 shape_it = iter(a.shape)
600 shape = [1 if ax in axis else next(shape_it) for ax in range(out_ndim)]
602 return a.reshape(shape)
605row_stack = vstack
608def _column_stack_dispatcher(tup):
609 return _arrays_for_stack_dispatcher(tup)
612@array_function_dispatch(_column_stack_dispatcher)
613def column_stack(tup):
614 """
615 Stack 1-D arrays as columns into a 2-D array.
617 Take a sequence of 1-D arrays and stack them as columns
618 to make a single 2-D array. 2-D arrays are stacked as-is,
619 just like with `hstack`. 1-D arrays are turned into 2-D columns
620 first.
622 Parameters
623 ----------
624 tup : sequence of 1-D or 2-D arrays.
625 Arrays to stack. All of them must have the same first dimension.
627 Returns
628 -------
629 stacked : 2-D array
630 The array formed by stacking the given arrays.
632 See Also
633 --------
634 stack, hstack, vstack, concatenate
636 Examples
637 --------
638 >>> a = np.array((1,2,3))
639 >>> b = np.array((2,3,4))
640 >>> np.column_stack((a,b))
641 array([[1, 2],
642 [2, 3],
643 [3, 4]])
645 """
646 if not overrides.ARRAY_FUNCTION_ENABLED:
647 # raise warning if necessary
648 _arrays_for_stack_dispatcher(tup, stacklevel=2)
650 arrays = []
651 for v in tup:
652 arr = asanyarray(v)
653 if arr.ndim < 2:
654 arr = array(arr, copy=False, subok=True, ndmin=2).T
655 arrays.append(arr)
656 return _nx.concatenate(arrays, 1)
659def _dstack_dispatcher(tup):
660 return _arrays_for_stack_dispatcher(tup)
663@array_function_dispatch(_dstack_dispatcher)
664def dstack(tup):
665 """
666 Stack arrays in sequence depth wise (along third axis).
668 This is equivalent to concatenation along the third axis after 2-D arrays
669 of shape `(M,N)` have been reshaped to `(M,N,1)` and 1-D arrays of shape
670 `(N,)` have been reshaped to `(1,N,1)`. Rebuilds arrays divided by
671 `dsplit`.
673 This function makes most sense for arrays with up to 3 dimensions. For
674 instance, for pixel-data with a height (first axis), width (second axis),
675 and r/g/b channels (third axis). The functions `concatenate`, `stack` and
676 `block` provide more general stacking and concatenation operations.
678 Parameters
679 ----------
680 tup : sequence of arrays
681 The arrays must have the same shape along all but the third axis.
682 1-D or 2-D arrays must have the same shape.
684 Returns
685 -------
686 stacked : ndarray
687 The array formed by stacking the given arrays, will be at least 3-D.
689 See Also
690 --------
691 concatenate : Join a sequence of arrays along an existing axis.
692 stack : Join a sequence of arrays along a new axis.
693 block : Assemble an nd-array from nested lists of blocks.
694 vstack : Stack arrays in sequence vertically (row wise).
695 hstack : Stack arrays in sequence horizontally (column wise).
696 column_stack : Stack 1-D arrays as columns into a 2-D array.
697 dsplit : Split array along third axis.
699 Examples
700 --------
701 >>> a = np.array((1,2,3))
702 >>> b = np.array((2,3,4))
703 >>> np.dstack((a,b))
704 array([[[1, 2],
705 [2, 3],
706 [3, 4]]])
708 >>> a = np.array([[1],[2],[3]])
709 >>> b = np.array([[2],[3],[4]])
710 >>> np.dstack((a,b))
711 array([[[1, 2]],
712 [[2, 3]],
713 [[3, 4]]])
715 """
716 if not overrides.ARRAY_FUNCTION_ENABLED:
717 # raise warning if necessary
718 _arrays_for_stack_dispatcher(tup, stacklevel=2)
720 arrs = atleast_3d(*tup)
721 if not isinstance(arrs, list):
722 arrs = [arrs]
723 return _nx.concatenate(arrs, 2)
726def _replace_zero_by_x_arrays(sub_arys):
727 for i in range(len(sub_arys)):
728 if _nx.ndim(sub_arys[i]) == 0:
729 sub_arys[i] = _nx.empty(0, dtype=sub_arys[i].dtype)
730 elif _nx.sometrue(_nx.equal(_nx.shape(sub_arys[i]), 0)):
731 sub_arys[i] = _nx.empty(0, dtype=sub_arys[i].dtype)
732 return sub_arys
735def _array_split_dispatcher(ary, indices_or_sections, axis=None):
736 return (ary, indices_or_sections)
739@array_function_dispatch(_array_split_dispatcher)
740def array_split(ary, indices_or_sections, axis=0):
741 """
742 Split an array into multiple sub-arrays.
744 Please refer to the ``split`` documentation. The only difference
745 between these functions is that ``array_split`` allows
746 `indices_or_sections` to be an integer that does *not* equally
747 divide the axis. For an array of length l that should be split
748 into n sections, it returns l % n sub-arrays of size l//n + 1
749 and the rest of size l//n.
751 See Also
752 --------
753 split : Split array into multiple sub-arrays of equal size.
755 Examples
756 --------
757 >>> x = np.arange(8.0)
758 >>> np.array_split(x, 3)
759 [array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7.])]
761 >>> x = np.arange(9)
762 >>> np.array_split(x, 4)
763 [array([0, 1, 2]), array([3, 4]), array([5, 6]), array([7, 8])]
765 """
766 try:
767 Ntotal = ary.shape[axis]
768 except AttributeError:
769 Ntotal = len(ary)
770 try:
771 # handle array case.
772 Nsections = len(indices_or_sections) + 1
773 div_points = [0] + list(indices_or_sections) + [Ntotal]
774 except TypeError:
775 # indices_or_sections is a scalar, not an array.
776 Nsections = int(indices_or_sections)
777 if Nsections <= 0:
778 raise ValueError('number sections must be larger than 0.') from None
779 Neach_section, extras = divmod(Ntotal, Nsections)
780 section_sizes = ([0] +
781 extras * [Neach_section+1] +
782 (Nsections-extras) * [Neach_section])
783 div_points = _nx.array(section_sizes, dtype=_nx.intp).cumsum()
785 sub_arys = []
786 sary = _nx.swapaxes(ary, axis, 0)
787 for i in range(Nsections):
788 st = div_points[i]
789 end = div_points[i + 1]
790 sub_arys.append(_nx.swapaxes(sary[st:end], axis, 0))
792 return sub_arys
795def _split_dispatcher(ary, indices_or_sections, axis=None):
796 return (ary, indices_or_sections)
799@array_function_dispatch(_split_dispatcher)
800def split(ary, indices_or_sections, axis=0):
801 """
802 Split an array into multiple sub-arrays as views into `ary`.
804 Parameters
805 ----------
806 ary : ndarray
807 Array to be divided into sub-arrays.
808 indices_or_sections : int or 1-D array
809 If `indices_or_sections` is an integer, N, the array will be divided
810 into N equal arrays along `axis`. If such a split is not possible,
811 an error is raised.
813 If `indices_or_sections` is a 1-D array of sorted integers, the entries
814 indicate where along `axis` the array is split. For example,
815 ``[2, 3]`` would, for ``axis=0``, result in
817 - ary[:2]
818 - ary[2:3]
819 - ary[3:]
821 If an index exceeds the dimension of the array along `axis`,
822 an empty sub-array is returned correspondingly.
823 axis : int, optional
824 The axis along which to split, default is 0.
826 Returns
827 -------
828 sub-arrays : list of ndarrays
829 A list of sub-arrays as views into `ary`.
831 Raises
832 ------
833 ValueError
834 If `indices_or_sections` is given as an integer, but
835 a split does not result in equal division.
837 See Also
838 --------
839 array_split : Split an array into multiple sub-arrays of equal or
840 near-equal size. Does not raise an exception if
841 an equal division cannot be made.
842 hsplit : Split array into multiple sub-arrays horizontally (column-wise).
843 vsplit : Split array into multiple sub-arrays vertically (row wise).
844 dsplit : Split array into multiple sub-arrays along the 3rd axis (depth).
845 concatenate : Join a sequence of arrays along an existing axis.
846 stack : Join a sequence of arrays along a new axis.
847 hstack : Stack arrays in sequence horizontally (column wise).
848 vstack : Stack arrays in sequence vertically (row wise).
849 dstack : Stack arrays in sequence depth wise (along third dimension).
851 Examples
852 --------
853 >>> x = np.arange(9.0)
854 >>> np.split(x, 3)
855 [array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7., 8.])]
857 >>> x = np.arange(8.0)
858 >>> np.split(x, [3, 5, 6, 10])
859 [array([0., 1., 2.]),
860 array([3., 4.]),
861 array([5.]),
862 array([6., 7.]),
863 array([], dtype=float64)]
865 """
866 try:
867 len(indices_or_sections)
868 except TypeError:
869 sections = indices_or_sections
870 N = ary.shape[axis]
871 if N % sections:
872 raise ValueError(
873 'array split does not result in an equal division') from None
874 return array_split(ary, indices_or_sections, axis)
877def _hvdsplit_dispatcher(ary, indices_or_sections):
878 return (ary, indices_or_sections)
881@array_function_dispatch(_hvdsplit_dispatcher)
882def hsplit(ary, indices_or_sections):
883 """
884 Split an array into multiple sub-arrays horizontally (column-wise).
886 Please refer to the `split` documentation. `hsplit` is equivalent
887 to `split` with ``axis=1``, the array is always split along the second
888 axis except for 1-D arrays, where it is split at ``axis=0``.
890 See Also
891 --------
892 split : Split an array into multiple sub-arrays of equal size.
894 Examples
895 --------
896 >>> x = np.arange(16.0).reshape(4, 4)
897 >>> x
898 array([[ 0., 1., 2., 3.],
899 [ 4., 5., 6., 7.],
900 [ 8., 9., 10., 11.],
901 [12., 13., 14., 15.]])
902 >>> np.hsplit(x, 2)
903 [array([[ 0., 1.],
904 [ 4., 5.],
905 [ 8., 9.],
906 [12., 13.]]),
907 array([[ 2., 3.],
908 [ 6., 7.],
909 [10., 11.],
910 [14., 15.]])]
911 >>> np.hsplit(x, np.array([3, 6]))
912 [array([[ 0., 1., 2.],
913 [ 4., 5., 6.],
914 [ 8., 9., 10.],
915 [12., 13., 14.]]),
916 array([[ 3.],
917 [ 7.],
918 [11.],
919 [15.]]),
920 array([], shape=(4, 0), dtype=float64)]
922 With a higher dimensional array the split is still along the second axis.
924 >>> x = np.arange(8.0).reshape(2, 2, 2)
925 >>> x
926 array([[[0., 1.],
927 [2., 3.]],
928 [[4., 5.],
929 [6., 7.]]])
930 >>> np.hsplit(x, 2)
931 [array([[[0., 1.]],
932 [[4., 5.]]]),
933 array([[[2., 3.]],
934 [[6., 7.]]])]
936 With a 1-D array, the split is along axis 0.
938 >>> x = np.array([0, 1, 2, 3, 4, 5])
939 >>> np.hsplit(x, 2)
940 [array([0, 1, 2]), array([3, 4, 5])]
942 """
943 if _nx.ndim(ary) == 0:
944 raise ValueError('hsplit only works on arrays of 1 or more dimensions')
945 if ary.ndim > 1:
946 return split(ary, indices_or_sections, 1)
947 else:
948 return split(ary, indices_or_sections, 0)
951@array_function_dispatch(_hvdsplit_dispatcher)
952def vsplit(ary, indices_or_sections):
953 """
954 Split an array into multiple sub-arrays vertically (row-wise).
956 Please refer to the ``split`` documentation. ``vsplit`` is equivalent
957 to ``split`` with `axis=0` (default), the array is always split along the
958 first axis regardless of the array dimension.
960 See Also
961 --------
962 split : Split an array into multiple sub-arrays of equal size.
964 Examples
965 --------
966 >>> x = np.arange(16.0).reshape(4, 4)
967 >>> x
968 array([[ 0., 1., 2., 3.],
969 [ 4., 5., 6., 7.],
970 [ 8., 9., 10., 11.],
971 [12., 13., 14., 15.]])
972 >>> np.vsplit(x, 2)
973 [array([[0., 1., 2., 3.],
974 [4., 5., 6., 7.]]), array([[ 8., 9., 10., 11.],
975 [12., 13., 14., 15.]])]
976 >>> np.vsplit(x, np.array([3, 6]))
977 [array([[ 0., 1., 2., 3.],
978 [ 4., 5., 6., 7.],
979 [ 8., 9., 10., 11.]]), array([[12., 13., 14., 15.]]), array([], shape=(0, 4), dtype=float64)]
981 With a higher dimensional array the split is still along the first axis.
983 >>> x = np.arange(8.0).reshape(2, 2, 2)
984 >>> x
985 array([[[0., 1.],
986 [2., 3.]],
987 [[4., 5.],
988 [6., 7.]]])
989 >>> np.vsplit(x, 2)
990 [array([[[0., 1.],
991 [2., 3.]]]), array([[[4., 5.],
992 [6., 7.]]])]
994 """
995 if _nx.ndim(ary) < 2:
996 raise ValueError('vsplit only works on arrays of 2 or more dimensions')
997 return split(ary, indices_or_sections, 0)
1000@array_function_dispatch(_hvdsplit_dispatcher)
1001def dsplit(ary, indices_or_sections):
1002 """
1003 Split array into multiple sub-arrays along the 3rd axis (depth).
1005 Please refer to the `split` documentation. `dsplit` is equivalent
1006 to `split` with ``axis=2``, the array is always split along the third
1007 axis provided the array dimension is greater than or equal to 3.
1009 See Also
1010 --------
1011 split : Split an array into multiple sub-arrays of equal size.
1013 Examples
1014 --------
1015 >>> x = np.arange(16.0).reshape(2, 2, 4)
1016 >>> x
1017 array([[[ 0., 1., 2., 3.],
1018 [ 4., 5., 6., 7.]],
1019 [[ 8., 9., 10., 11.],
1020 [12., 13., 14., 15.]]])
1021 >>> np.dsplit(x, 2)
1022 [array([[[ 0., 1.],
1023 [ 4., 5.]],
1024 [[ 8., 9.],
1025 [12., 13.]]]), array([[[ 2., 3.],
1026 [ 6., 7.]],
1027 [[10., 11.],
1028 [14., 15.]]])]
1029 >>> np.dsplit(x, np.array([3, 6]))
1030 [array([[[ 0., 1., 2.],
1031 [ 4., 5., 6.]],
1032 [[ 8., 9., 10.],
1033 [12., 13., 14.]]]),
1034 array([[[ 3.],
1035 [ 7.]],
1036 [[11.],
1037 [15.]]]),
1038 array([], shape=(2, 2, 0), dtype=float64)]
1039 """
1040 if _nx.ndim(ary) < 3:
1041 raise ValueError('dsplit only works on arrays of 3 or more dimensions')
1042 return split(ary, indices_or_sections, 2)
1044def get_array_prepare(*args):
1045 """Find the wrapper for the array with the highest priority.
1047 In case of ties, leftmost wins. If no wrapper is found, return None
1048 """
1049 wrappers = sorted((getattr(x, '__array_priority__', 0), -i,
1050 x.__array_prepare__) for i, x in enumerate(args)
1051 if hasattr(x, '__array_prepare__'))
1052 if wrappers:
1053 return wrappers[-1][-1]
1054 return None
1056def get_array_wrap(*args):
1057 """Find the wrapper for the array with the highest priority.
1059 In case of ties, leftmost wins. If no wrapper is found, return None
1060 """
1061 wrappers = sorted((getattr(x, '__array_priority__', 0), -i,
1062 x.__array_wrap__) for i, x in enumerate(args)
1063 if hasattr(x, '__array_wrap__'))
1064 if wrappers:
1065 return wrappers[-1][-1]
1066 return None
1069def _kron_dispatcher(a, b):
1070 return (a, b)
1073@array_function_dispatch(_kron_dispatcher)
1074def kron(a, b):
1075 """
1076 Kronecker product of two arrays.
1078 Computes the Kronecker product, a composite array made of blocks of the
1079 second array scaled by the first.
1081 Parameters
1082 ----------
1083 a, b : array_like
1085 Returns
1086 -------
1087 out : ndarray
1089 See Also
1090 --------
1091 outer : The outer product
1093 Notes
1094 -----
1095 The function assumes that the number of dimensions of `a` and `b`
1096 are the same, if necessary prepending the smallest with ones.
1097 If ``a.shape = (r0,r1,..,rN)`` and ``b.shape = (s0,s1,...,sN)``,
1098 the Kronecker product has shape ``(r0*s0, r1*s1, ..., rN*SN)``.
1099 The elements are products of elements from `a` and `b`, organized
1100 explicitly by::
1102 kron(a,b)[k0,k1,...,kN] = a[i0,i1,...,iN] * b[j0,j1,...,jN]
1104 where::
1106 kt = it * st + jt, t = 0,...,N
1108 In the common 2-D case (N=1), the block structure can be visualized::
1110 [[ a[0,0]*b, a[0,1]*b, ... , a[0,-1]*b ],
1111 [ ... ... ],
1112 [ a[-1,0]*b, a[-1,1]*b, ... , a[-1,-1]*b ]]
1115 Examples
1116 --------
1117 >>> np.kron([1,10,100], [5,6,7])
1118 array([ 5, 6, 7, ..., 500, 600, 700])
1119 >>> np.kron([5,6,7], [1,10,100])
1120 array([ 5, 50, 500, ..., 7, 70, 700])
1122 >>> np.kron(np.eye(2), np.ones((2,2)))
1123 array([[1., 1., 0., 0.],
1124 [1., 1., 0., 0.],
1125 [0., 0., 1., 1.],
1126 [0., 0., 1., 1.]])
1128 >>> a = np.arange(100).reshape((2,5,2,5))
1129 >>> b = np.arange(24).reshape((2,3,4))
1130 >>> c = np.kron(a,b)
1131 >>> c.shape
1132 (2, 10, 6, 20)
1133 >>> I = (1,3,0,2)
1134 >>> J = (0,2,1)
1135 >>> J1 = (0,) + J # extend to ndim=4
1136 >>> S1 = (1,) + b.shape
1137 >>> K = tuple(np.array(I) * np.array(S1) + np.array(J1))
1138 >>> c[K] == a[I]*b[J]
1139 True
1141 """
1142 # Working:
1143 # 1. Equalise the shapes by prepending smaller array with 1s
1144 # 2. Expand shapes of both the arrays by adding new axes at
1145 # odd positions for 1st array and even positions for 2nd
1146 # 3. Compute the product of the modified array
1147 # 4. The inner most array elements now contain the rows of
1148 # the Kronecker product
1149 # 5. Reshape the result to kron's shape, which is same as
1150 # product of shapes of the two arrays.
1151 b = asanyarray(b)
1152 a = array(a, copy=False, subok=True, ndmin=b.ndim)
1153 is_any_mat = isinstance(a, matrix) or isinstance(b, matrix)
1154 ndb, nda = b.ndim, a.ndim
1155 nd = max(ndb, nda)
1157 if (nda == 0 or ndb == 0):
1158 return _nx.multiply(a, b)
1160 as_ = a.shape
1161 bs = b.shape
1162 if not a.flags.contiguous:
1163 a = reshape(a, as_)
1164 if not b.flags.contiguous:
1165 b = reshape(b, bs)
1167 # Equalise the shapes by prepending smaller one with 1s
1168 as_ = (1,)*max(0, ndb-nda) + as_
1169 bs = (1,)*max(0, nda-ndb) + bs
1171 # Insert empty dimensions
1172 a_arr = expand_dims(a, axis=tuple(range(ndb-nda)))
1173 b_arr = expand_dims(b, axis=tuple(range(nda-ndb)))
1175 # Compute the product
1176 a_arr = expand_dims(a_arr, axis=tuple(range(1, nd*2, 2)))
1177 b_arr = expand_dims(b_arr, axis=tuple(range(0, nd*2, 2)))
1178 # In case of `mat`, convert result to `array`
1179 result = _nx.multiply(a_arr, b_arr, subok=(not is_any_mat))
1181 # Reshape back
1182 result = result.reshape(_nx.multiply(as_, bs))
1184 return result if not is_any_mat else matrix(result, copy=False)
1187def _tile_dispatcher(A, reps):
1188 return (A, reps)
1191@array_function_dispatch(_tile_dispatcher)
1192def tile(A, reps):
1193 """
1194 Construct an array by repeating A the number of times given by reps.
1196 If `reps` has length ``d``, the result will have dimension of
1197 ``max(d, A.ndim)``.
1199 If ``A.ndim < d``, `A` is promoted to be d-dimensional by prepending new
1200 axes. So a shape (3,) array is promoted to (1, 3) for 2-D replication,
1201 or shape (1, 1, 3) for 3-D replication. If this is not the desired
1202 behavior, promote `A` to d-dimensions manually before calling this
1203 function.
1205 If ``A.ndim > d``, `reps` is promoted to `A`.ndim by pre-pending 1's to it.
1206 Thus for an `A` of shape (2, 3, 4, 5), a `reps` of (2, 2) is treated as
1207 (1, 1, 2, 2).
1209 Note : Although tile may be used for broadcasting, it is strongly
1210 recommended to use numpy's broadcasting operations and functions.
1212 Parameters
1213 ----------
1214 A : array_like
1215 The input array.
1216 reps : array_like
1217 The number of repetitions of `A` along each axis.
1219 Returns
1220 -------
1221 c : ndarray
1222 The tiled output array.
1224 See Also
1225 --------
1226 repeat : Repeat elements of an array.
1227 broadcast_to : Broadcast an array to a new shape
1229 Examples
1230 --------
1231 >>> a = np.array([0, 1, 2])
1232 >>> np.tile(a, 2)
1233 array([0, 1, 2, 0, 1, 2])
1234 >>> np.tile(a, (2, 2))
1235 array([[0, 1, 2, 0, 1, 2],
1236 [0, 1, 2, 0, 1, 2]])
1237 >>> np.tile(a, (2, 1, 2))
1238 array([[[0, 1, 2, 0, 1, 2]],
1239 [[0, 1, 2, 0, 1, 2]]])
1241 >>> b = np.array([[1, 2], [3, 4]])
1242 >>> np.tile(b, 2)
1243 array([[1, 2, 1, 2],
1244 [3, 4, 3, 4]])
1245 >>> np.tile(b, (2, 1))
1246 array([[1, 2],
1247 [3, 4],
1248 [1, 2],
1249 [3, 4]])
1251 >>> c = np.array([1,2,3,4])
1252 >>> np.tile(c,(4,1))
1253 array([[1, 2, 3, 4],
1254 [1, 2, 3, 4],
1255 [1, 2, 3, 4],
1256 [1, 2, 3, 4]])
1257 """
1258 try:
1259 tup = tuple(reps)
1260 except TypeError:
1261 tup = (reps,)
1262 d = len(tup)
1263 if all(x == 1 for x in tup) and isinstance(A, _nx.ndarray):
1264 # Fixes the problem that the function does not make a copy if A is a
1265 # numpy array and the repetitions are 1 in all dimensions
1266 return _nx.array(A, copy=True, subok=True, ndmin=d)
1267 else:
1268 # Note that no copy of zero-sized arrays is made. However since they
1269 # have no data there is no risk of an inadvertent overwrite.
1270 c = _nx.array(A, copy=False, subok=True, ndmin=d)
1271 if (d < c.ndim):
1272 tup = (1,)*(c.ndim-d) + tup
1273 shape_out = tuple(s*t for s, t in zip(c.shape, tup))
1274 n = c.size
1275 if n > 0:
1276 for dim_in, nrep in zip(c.shape, tup):
1277 if nrep != 1:
1278 c = c.reshape(-1, n).repeat(nrep, 0)
1279 n //= dim_in
1280 return c.reshape(shape_out)