Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/numpy/lib/shape_base.py: 42%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

253 statements  

1import functools 

2 

3import numpy.core.numeric as _nx 

4from numpy.core.numeric import asarray, zeros, array, asanyarray 

5from numpy.core.fromnumeric import reshape, transpose 

6from numpy.core.multiarray import normalize_axis_index 

7from numpy.core import overrides 

8from numpy.core import vstack, atleast_3d 

9from numpy.core.numeric import normalize_axis_tuple 

10from numpy.core.shape_base import _arrays_for_stack_dispatcher 

11from numpy.lib.index_tricks import ndindex 

12from numpy.matrixlib.defmatrix import matrix # this raises all the right alarm bells 

13 

14 

15__all__ = [ 

16 'column_stack', 'row_stack', 'dstack', 'array_split', 'split', 

17 'hsplit', 'vsplit', 'dsplit', 'apply_over_axes', 'expand_dims', 

18 'apply_along_axis', 'kron', 'tile', 'get_array_wrap', 'take_along_axis', 

19 'put_along_axis' 

20 ] 

21 

22 

23array_function_dispatch = functools.partial( 

24 overrides.array_function_dispatch, module='numpy') 

25 

26 

27def _make_along_axis_idx(arr_shape, indices, axis): 

28 # compute dimensions to iterate over 

29 if not _nx.issubdtype(indices.dtype, _nx.integer): 

30 raise IndexError('`indices` must be an integer array') 

31 if len(arr_shape) != indices.ndim: 

32 raise ValueError( 

33 "`indices` and `arr` must have the same number of dimensions") 

34 shape_ones = (1,) * indices.ndim 

35 dest_dims = list(range(axis)) + [None] + list(range(axis+1, indices.ndim)) 

36 

37 # build a fancy index, consisting of orthogonal aranges, with the 

38 # requested index inserted at the right location 

39 fancy_index = [] 

40 for dim, n in zip(dest_dims, arr_shape): 

41 if dim is None: 

42 fancy_index.append(indices) 

43 else: 

44 ind_shape = shape_ones[:dim] + (-1,) + shape_ones[dim+1:] 

45 fancy_index.append(_nx.arange(n).reshape(ind_shape)) 

46 

47 return tuple(fancy_index) 

48 

49 

50def _take_along_axis_dispatcher(arr, indices, axis): 

51 return (arr, indices) 

52 

53 

54@array_function_dispatch(_take_along_axis_dispatcher) 

55def take_along_axis(arr, indices, axis): 

56 """ 

57 Take values from the input array by matching 1d index and data slices. 

58 

59 This iterates over matching 1d slices oriented along the specified axis in 

60 the index and data arrays, and uses the former to look up values in the 

61 latter. These slices can be different lengths. 

62 

63 Functions returning an index along an axis, like `argsort` and 

64 `argpartition`, produce suitable indices for this function. 

65 

66 .. versionadded:: 1.15.0 

67 

68 Parameters 

69 ---------- 

70 arr : ndarray (Ni..., M, Nk...) 

71 Source array 

72 indices : ndarray (Ni..., J, Nk...) 

73 Indices to take along each 1d slice of `arr`. This must match the 

74 dimension of arr, but dimensions Ni and Nj only need to broadcast 

75 against `arr`. 

76 axis : int 

77 The axis to take 1d slices along. If axis is None, the input array is 

78 treated as if it had first been flattened to 1d, for consistency with 

79 `sort` and `argsort`. 

80 

81 Returns 

82 ------- 

83 out: ndarray (Ni..., J, Nk...) 

84 The indexed result. 

85 

86 Notes 

87 ----- 

88 This is equivalent to (but faster than) the following use of `ndindex` and 

89 `s_`, which sets each of ``ii`` and ``kk`` to a tuple of indices:: 

90 

91 Ni, M, Nk = a.shape[:axis], a.shape[axis], a.shape[axis+1:] 

92 J = indices.shape[axis] # Need not equal M 

93 out = np.empty(Ni + (J,) + Nk) 

94 

95 for ii in ndindex(Ni): 

96 for kk in ndindex(Nk): 

97 a_1d = a [ii + s_[:,] + kk] 

98 indices_1d = indices[ii + s_[:,] + kk] 

99 out_1d = out [ii + s_[:,] + kk] 

100 for j in range(J): 

101 out_1d[j] = a_1d[indices_1d[j]] 

102 

103 Equivalently, eliminating the inner loop, the last two lines would be:: 

104 

105 out_1d[:] = a_1d[indices_1d] 

106 

107 See Also 

108 -------- 

109 take : Take along an axis, using the same indices for every 1d slice 

110 put_along_axis : 

111 Put values into the destination array by matching 1d index and data slices 

112 

113 Examples 

114 -------- 

115 

116 For this sample array 

117 

118 >>> a = np.array([[10, 30, 20], [60, 40, 50]]) 

119 

120 We can sort either by using sort directly, or argsort and this function 

121 

122 >>> np.sort(a, axis=1) 

123 array([[10, 20, 30], 

124 [40, 50, 60]]) 

125 >>> ai = np.argsort(a, axis=1) 

126 >>> ai 

127 array([[0, 2, 1], 

128 [1, 2, 0]]) 

129 >>> np.take_along_axis(a, ai, axis=1) 

130 array([[10, 20, 30], 

131 [40, 50, 60]]) 

132 

133 The same works for max and min, if you maintain the trivial dimension 

134 with ``keepdims``: 

135 

136 >>> np.max(a, axis=1, keepdims=True) 

137 array([[30], 

138 [60]]) 

139 >>> ai = np.argmax(a, axis=1, keepdims=True) 

140 >>> ai 

141 array([[1], 

142 [0]]) 

143 >>> np.take_along_axis(a, ai, axis=1) 

144 array([[30], 

145 [60]]) 

146 

147 If we want to get the max and min at the same time, we can stack the 

148 indices first 

149 

150 >>> ai_min = np.argmin(a, axis=1, keepdims=True) 

151 >>> ai_max = np.argmax(a, axis=1, keepdims=True) 

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 

168 

169 # use the fancy index 

170 return arr[_make_along_axis_idx(arr_shape, indices, axis)] 

171 

172 

173def _put_along_axis_dispatcher(arr, indices, values, axis): 

174 return (arr, indices, values) 

175 

176 

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. 

181 

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. 

185 

186 Functions returning an index along an axis, like `argsort` and 

187 `argpartition`, produce suitable indices for this function. 

188 

189 .. versionadded:: 1.15.0 

190 

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. 

205 

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:: 

210 

211 Ni, M, Nk = a.shape[:axis], a.shape[axis], a.shape[axis+1:] 

212 J = indices.shape[axis] # Need not equal M 

213 

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] 

221 

222 Equivalently, eliminating the inner loop, the last two lines would be:: 

223 

224 a_1d[indices_1d] = values_1d 

225 

226 See Also 

227 -------- 

228 take_along_axis : 

229 Take values from the input array by matching 1d index and data slices 

230 

231 Examples 

232 -------- 

233 

234 For this sample array 

235 

236 >>> a = np.array([[10, 30, 20], [60, 40, 50]]) 

237 

238 We can replace the maximum values with: 

239 

240 >>> ai = np.argmax(a, axis=1, keepdims=True) 

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]]) 

248 

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 

258 

259 # use the fancy index 

260 arr[_make_along_axis_idx(arr_shape, indices, axis)] = values 

261 

262 

263def _apply_along_axis_dispatcher(func1d, axis, arr, *args, **kwargs): 

264 return (arr,) 

265 

266 

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. 

271 

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`. 

274 

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:: 

277 

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] 

285 

286 Equivalently, eliminating the inner loop, this can be expressed as:: 

287 

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]) 

292 

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`. 

306 

307 .. versionadded:: 1.9.0 

308 

309 

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`. 

318 

319 See Also 

320 -------- 

321 apply_over_axes : Apply a function repeatedly over multiple axes. 

322 

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.]) 

333 

334 For a function that returns a 1D array, the number of dimensions in 

335 `outarr` is the same as `arr`. 

336 

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]]) 

342 

343 For a function that returns a higher dimensional array, those dimensions 

344 are inserted in place of the `axis` dimension. 

345 

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) 

362 

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]) 

366 

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) 

371 

372 # invoke the function on the first item 

373 try: 

374 ind0 = next(inds) 

375 except StopIteration: 

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)) 

380 

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) 

386 

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 ) 

394 

395 # matrices have a nasty __array_prepare__ and __array_wrap__ 

396 if not isinstance(res, matrix): 

397 buff = res.__array_prepare__(buff) 

398 

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)) 

403 

404 if not isinstance(res, matrix): 

405 # wrap the array, to preserve subclasses 

406 buff = res.__array_wrap__(buff) 

407 

408 # finally, rotate the inserted axes back to where they belong 

409 return transpose(buff, buff_permute) 

410 

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) 

415 

416 

417def _apply_over_axes_dispatcher(func, a, axes): 

418 return (a,) 

419 

420 

421@array_function_dispatch(_apply_over_axes_dispatcher) 

422def apply_over_axes(func, a, axes): 

423 """ 

424 Apply a function repeatedly over multiple axes. 

425 

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. 

432 

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. 

441 

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. 

448 

449 See Also 

450 -------- 

451 apply_along_axis : 

452 Apply a function to 1-D slices of an array along the given axis. 

453 

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. 

459 

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]]]) 

470 

471 Sum over axes 0 and 2. The result has same number of dimensions 

472 as the original array: 

473 

474 >>> np.apply_over_axes(np.sum, a, [0,2]) 

475 array([[[ 60], 

476 [ 92], 

477 [124]]]) 

478 

479 Tuple axis arguments to ufuncs are equivalent: 

480 

481 >>> np.sum(a, axis=(0,2), keepdims=True) 

482 array([[[ 60], 

483 [ 92], 

484 [124]]]) 

485 

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 

506 

507 

508def _expand_dims_dispatcher(a, axis): 

509 return (a,) 

510 

511 

512@array_function_dispatch(_expand_dims_dispatcher) 

513def expand_dims(a, axis): 

514 """ 

515 Expand the shape of an array. 

516 

517 Insert a new axis that will appear at the `axis` position in the expanded 

518 array shape. 

519 

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. 

526 

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. 

531 

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`. 

535 

536 Returns 

537 ------- 

538 result : ndarray 

539 View of `a` with the number of dimensions increased. 

540 

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 

546 

547 Examples 

548 -------- 

549 >>> x = np.array([1, 2]) 

550 >>> x.shape 

551 (2,) 

552 

553 The following is equivalent to ``x[np.newaxis, :]`` or ``x[np.newaxis]``: 

554 

555 >>> y = np.expand_dims(x, axis=0) 

556 >>> y 

557 array([[1, 2]]) 

558 >>> y.shape 

559 (1, 2) 

560 

561 The following is equivalent to ``x[:, np.newaxis]``: 

562 

563 >>> y = np.expand_dims(x, axis=1) 

564 >>> y 

565 array([[1], 

566 [2]]) 

567 >>> y.shape 

568 (2, 1) 

569 

570 ``axis`` may also be a tuple: 

571 

572 >>> y = np.expand_dims(x, axis=(0, 1)) 

573 >>> y 

574 array([[[1, 2]]]) 

575 

576 >>> y = np.expand_dims(x, axis=(2, 0)) 

577 >>> y 

578 array([[[1], 

579 [2]]]) 

580 

581 Note that some examples may use ``None`` instead of ``np.newaxis``. These 

582 are the same objects: 

583 

584 >>> np.newaxis is None 

585 True 

586 

587 """ 

588 if isinstance(a, matrix): 

589 a = asarray(a) 

590 else: 

591 a = asanyarray(a) 

592 

593 if type(axis) not in (tuple, list): 

594 axis = (axis,) 

595 

596 out_ndim = len(axis) + a.ndim 

597 axis = normalize_axis_tuple(axis, out_ndim) 

598 

599 shape_it = iter(a.shape) 

600 shape = [1 if ax in axis else next(shape_it) for ax in range(out_ndim)] 

601 

602 return a.reshape(shape) 

603 

604 

605row_stack = vstack 

606 

607 

608def _column_stack_dispatcher(tup): 

609 return _arrays_for_stack_dispatcher(tup) 

610 

611 

612@array_function_dispatch(_column_stack_dispatcher) 

613def column_stack(tup): 

614 """ 

615 Stack 1-D arrays as columns into a 2-D array. 

616 

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. 

621 

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. 

626 

627 Returns 

628 ------- 

629 stacked : 2-D array 

630 The array formed by stacking the given arrays. 

631 

632 See Also 

633 -------- 

634 stack, hstack, vstack, concatenate 

635 

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]]) 

644 

645 """ 

646 arrays = [] 

647 for v in tup: 

648 arr = asanyarray(v) 

649 if arr.ndim < 2: 

650 arr = array(arr, copy=False, subok=True, ndmin=2).T 

651 arrays.append(arr) 

652 return _nx.concatenate(arrays, 1) 

653 

654 

655def _dstack_dispatcher(tup): 

656 return _arrays_for_stack_dispatcher(tup) 

657 

658 

659@array_function_dispatch(_dstack_dispatcher) 

660def dstack(tup): 

661 """ 

662 Stack arrays in sequence depth wise (along third axis). 

663 

664 This is equivalent to concatenation along the third axis after 2-D arrays 

665 of shape `(M,N)` have been reshaped to `(M,N,1)` and 1-D arrays of shape 

666 `(N,)` have been reshaped to `(1,N,1)`. Rebuilds arrays divided by 

667 `dsplit`. 

668 

669 This function makes most sense for arrays with up to 3 dimensions. For 

670 instance, for pixel-data with a height (first axis), width (second axis), 

671 and r/g/b channels (third axis). The functions `concatenate`, `stack` and 

672 `block` provide more general stacking and concatenation operations. 

673 

674 Parameters 

675 ---------- 

676 tup : sequence of arrays 

677 The arrays must have the same shape along all but the third axis. 

678 1-D or 2-D arrays must have the same shape. 

679 

680 Returns 

681 ------- 

682 stacked : ndarray 

683 The array formed by stacking the given arrays, will be at least 3-D. 

684 

685 See Also 

686 -------- 

687 concatenate : Join a sequence of arrays along an existing axis. 

688 stack : Join a sequence of arrays along a new axis. 

689 block : Assemble an nd-array from nested lists of blocks. 

690 vstack : Stack arrays in sequence vertically (row wise). 

691 hstack : Stack arrays in sequence horizontally (column wise). 

692 column_stack : Stack 1-D arrays as columns into a 2-D array. 

693 dsplit : Split array along third axis. 

694 

695 Examples 

696 -------- 

697 >>> a = np.array((1,2,3)) 

698 >>> b = np.array((2,3,4)) 

699 >>> np.dstack((a,b)) 

700 array([[[1, 2], 

701 [2, 3], 

702 [3, 4]]]) 

703 

704 >>> a = np.array([[1],[2],[3]]) 

705 >>> b = np.array([[2],[3],[4]]) 

706 >>> np.dstack((a,b)) 

707 array([[[1, 2]], 

708 [[2, 3]], 

709 [[3, 4]]]) 

710 

711 """ 

712 arrs = atleast_3d(*tup) 

713 if not isinstance(arrs, list): 

714 arrs = [arrs] 

715 return _nx.concatenate(arrs, 2) 

716 

717 

718def _replace_zero_by_x_arrays(sub_arys): 

719 for i in range(len(sub_arys)): 

720 if _nx.ndim(sub_arys[i]) == 0: 

721 sub_arys[i] = _nx.empty(0, dtype=sub_arys[i].dtype) 

722 elif _nx.sometrue(_nx.equal(_nx.shape(sub_arys[i]), 0)): 

723 sub_arys[i] = _nx.empty(0, dtype=sub_arys[i].dtype) 

724 return sub_arys 

725 

726 

727def _array_split_dispatcher(ary, indices_or_sections, axis=None): 

728 return (ary, indices_or_sections) 

729 

730 

731@array_function_dispatch(_array_split_dispatcher) 

732def array_split(ary, indices_or_sections, axis=0): 

733 """ 

734 Split an array into multiple sub-arrays. 

735 

736 Please refer to the ``split`` documentation. The only difference 

737 between these functions is that ``array_split`` allows 

738 `indices_or_sections` to be an integer that does *not* equally 

739 divide the axis. For an array of length l that should be split 

740 into n sections, it returns l % n sub-arrays of size l//n + 1 

741 and the rest of size l//n. 

742 

743 See Also 

744 -------- 

745 split : Split array into multiple sub-arrays of equal size. 

746 

747 Examples 

748 -------- 

749 >>> x = np.arange(8.0) 

750 >>> np.array_split(x, 3) 

751 [array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7.])] 

752 

753 >>> x = np.arange(9) 

754 >>> np.array_split(x, 4) 

755 [array([0, 1, 2]), array([3, 4]), array([5, 6]), array([7, 8])] 

756 

757 """ 

758 try: 

759 Ntotal = ary.shape[axis] 

760 except AttributeError: 

761 Ntotal = len(ary) 

762 try: 

763 # handle array case. 

764 Nsections = len(indices_or_sections) + 1 

765 div_points = [0] + list(indices_or_sections) + [Ntotal] 

766 except TypeError: 

767 # indices_or_sections is a scalar, not an array. 

768 Nsections = int(indices_or_sections) 

769 if Nsections <= 0: 

770 raise ValueError('number sections must be larger than 0.') from None 

771 Neach_section, extras = divmod(Ntotal, Nsections) 

772 section_sizes = ([0] + 

773 extras * [Neach_section+1] + 

774 (Nsections-extras) * [Neach_section]) 

775 div_points = _nx.array(section_sizes, dtype=_nx.intp).cumsum() 

776 

777 sub_arys = [] 

778 sary = _nx.swapaxes(ary, axis, 0) 

779 for i in range(Nsections): 

780 st = div_points[i] 

781 end = div_points[i + 1] 

782 sub_arys.append(_nx.swapaxes(sary[st:end], axis, 0)) 

783 

784 return sub_arys 

785 

786 

787def _split_dispatcher(ary, indices_or_sections, axis=None): 

788 return (ary, indices_or_sections) 

789 

790 

791@array_function_dispatch(_split_dispatcher) 

792def split(ary, indices_or_sections, axis=0): 

793 """ 

794 Split an array into multiple sub-arrays as views into `ary`. 

795 

796 Parameters 

797 ---------- 

798 ary : ndarray 

799 Array to be divided into sub-arrays. 

800 indices_or_sections : int or 1-D array 

801 If `indices_or_sections` is an integer, N, the array will be divided 

802 into N equal arrays along `axis`. If such a split is not possible, 

803 an error is raised. 

804 

805 If `indices_or_sections` is a 1-D array of sorted integers, the entries 

806 indicate where along `axis` the array is split. For example, 

807 ``[2, 3]`` would, for ``axis=0``, result in 

808 

809 - ary[:2] 

810 - ary[2:3] 

811 - ary[3:] 

812 

813 If an index exceeds the dimension of the array along `axis`, 

814 an empty sub-array is returned correspondingly. 

815 axis : int, optional 

816 The axis along which to split, default is 0. 

817 

818 Returns 

819 ------- 

820 sub-arrays : list of ndarrays 

821 A list of sub-arrays as views into `ary`. 

822 

823 Raises 

824 ------ 

825 ValueError 

826 If `indices_or_sections` is given as an integer, but 

827 a split does not result in equal division. 

828 

829 See Also 

830 -------- 

831 array_split : Split an array into multiple sub-arrays of equal or 

832 near-equal size. Does not raise an exception if 

833 an equal division cannot be made. 

834 hsplit : Split array into multiple sub-arrays horizontally (column-wise). 

835 vsplit : Split array into multiple sub-arrays vertically (row wise). 

836 dsplit : Split array into multiple sub-arrays along the 3rd axis (depth). 

837 concatenate : Join a sequence of arrays along an existing axis. 

838 stack : Join a sequence of arrays along a new axis. 

839 hstack : Stack arrays in sequence horizontally (column wise). 

840 vstack : Stack arrays in sequence vertically (row wise). 

841 dstack : Stack arrays in sequence depth wise (along third dimension). 

842 

843 Examples 

844 -------- 

845 >>> x = np.arange(9.0) 

846 >>> np.split(x, 3) 

847 [array([0., 1., 2.]), array([3., 4., 5.]), array([6., 7., 8.])] 

848 

849 >>> x = np.arange(8.0) 

850 >>> np.split(x, [3, 5, 6, 10]) 

851 [array([0., 1., 2.]), 

852 array([3., 4.]), 

853 array([5.]), 

854 array([6., 7.]), 

855 array([], dtype=float64)] 

856 

857 """ 

858 try: 

859 len(indices_or_sections) 

860 except TypeError: 

861 sections = indices_or_sections 

862 N = ary.shape[axis] 

863 if N % sections: 

864 raise ValueError( 

865 'array split does not result in an equal division') from None 

866 return array_split(ary, indices_or_sections, axis) 

867 

868 

869def _hvdsplit_dispatcher(ary, indices_or_sections): 

870 return (ary, indices_or_sections) 

871 

872 

873@array_function_dispatch(_hvdsplit_dispatcher) 

874def hsplit(ary, indices_or_sections): 

875 """ 

876 Split an array into multiple sub-arrays horizontally (column-wise). 

877 

878 Please refer to the `split` documentation. `hsplit` is equivalent 

879 to `split` with ``axis=1``, the array is always split along the second 

880 axis except for 1-D arrays, where it is split at ``axis=0``. 

881 

882 See Also 

883 -------- 

884 split : Split an array into multiple sub-arrays of equal size. 

885 

886 Examples 

887 -------- 

888 >>> x = np.arange(16.0).reshape(4, 4) 

889 >>> x 

890 array([[ 0., 1., 2., 3.], 

891 [ 4., 5., 6., 7.], 

892 [ 8., 9., 10., 11.], 

893 [12., 13., 14., 15.]]) 

894 >>> np.hsplit(x, 2) 

895 [array([[ 0., 1.], 

896 [ 4., 5.], 

897 [ 8., 9.], 

898 [12., 13.]]), 

899 array([[ 2., 3.], 

900 [ 6., 7.], 

901 [10., 11.], 

902 [14., 15.]])] 

903 >>> np.hsplit(x, np.array([3, 6])) 

904 [array([[ 0., 1., 2.], 

905 [ 4., 5., 6.], 

906 [ 8., 9., 10.], 

907 [12., 13., 14.]]), 

908 array([[ 3.], 

909 [ 7.], 

910 [11.], 

911 [15.]]), 

912 array([], shape=(4, 0), dtype=float64)] 

913 

914 With a higher dimensional array the split is still along the second axis. 

915 

916 >>> x = np.arange(8.0).reshape(2, 2, 2) 

917 >>> x 

918 array([[[0., 1.], 

919 [2., 3.]], 

920 [[4., 5.], 

921 [6., 7.]]]) 

922 >>> np.hsplit(x, 2) 

923 [array([[[0., 1.]], 

924 [[4., 5.]]]), 

925 array([[[2., 3.]], 

926 [[6., 7.]]])] 

927 

928 With a 1-D array, the split is along axis 0. 

929 

930 >>> x = np.array([0, 1, 2, 3, 4, 5]) 

931 >>> np.hsplit(x, 2) 

932 [array([0, 1, 2]), array([3, 4, 5])] 

933 

934 """ 

935 if _nx.ndim(ary) == 0: 

936 raise ValueError('hsplit only works on arrays of 1 or more dimensions') 

937 if ary.ndim > 1: 

938 return split(ary, indices_or_sections, 1) 

939 else: 

940 return split(ary, indices_or_sections, 0) 

941 

942 

943@array_function_dispatch(_hvdsplit_dispatcher) 

944def vsplit(ary, indices_or_sections): 

945 """ 

946 Split an array into multiple sub-arrays vertically (row-wise). 

947 

948 Please refer to the ``split`` documentation. ``vsplit`` is equivalent 

949 to ``split`` with `axis=0` (default), the array is always split along the 

950 first axis regardless of the array dimension. 

951 

952 See Also 

953 -------- 

954 split : Split an array into multiple sub-arrays of equal size. 

955 

956 Examples 

957 -------- 

958 >>> x = np.arange(16.0).reshape(4, 4) 

959 >>> x 

960 array([[ 0., 1., 2., 3.], 

961 [ 4., 5., 6., 7.], 

962 [ 8., 9., 10., 11.], 

963 [12., 13., 14., 15.]]) 

964 >>> np.vsplit(x, 2) 

965 [array([[0., 1., 2., 3.], 

966 [4., 5., 6., 7.]]), array([[ 8., 9., 10., 11.], 

967 [12., 13., 14., 15.]])] 

968 >>> np.vsplit(x, np.array([3, 6])) 

969 [array([[ 0., 1., 2., 3.], 

970 [ 4., 5., 6., 7.], 

971 [ 8., 9., 10., 11.]]), array([[12., 13., 14., 15.]]), array([], shape=(0, 4), dtype=float64)] 

972 

973 With a higher dimensional array the split is still along the first axis. 

974 

975 >>> x = np.arange(8.0).reshape(2, 2, 2) 

976 >>> x 

977 array([[[0., 1.], 

978 [2., 3.]], 

979 [[4., 5.], 

980 [6., 7.]]]) 

981 >>> np.vsplit(x, 2) 

982 [array([[[0., 1.], 

983 [2., 3.]]]), array([[[4., 5.], 

984 [6., 7.]]])] 

985 

986 """ 

987 if _nx.ndim(ary) < 2: 

988 raise ValueError('vsplit only works on arrays of 2 or more dimensions') 

989 return split(ary, indices_or_sections, 0) 

990 

991 

992@array_function_dispatch(_hvdsplit_dispatcher) 

993def dsplit(ary, indices_or_sections): 

994 """ 

995 Split array into multiple sub-arrays along the 3rd axis (depth). 

996 

997 Please refer to the `split` documentation. `dsplit` is equivalent 

998 to `split` with ``axis=2``, the array is always split along the third 

999 axis provided the array dimension is greater than or equal to 3. 

1000 

1001 See Also 

1002 -------- 

1003 split : Split an array into multiple sub-arrays of equal size. 

1004 

1005 Examples 

1006 -------- 

1007 >>> x = np.arange(16.0).reshape(2, 2, 4) 

1008 >>> x 

1009 array([[[ 0., 1., 2., 3.], 

1010 [ 4., 5., 6., 7.]], 

1011 [[ 8., 9., 10., 11.], 

1012 [12., 13., 14., 15.]]]) 

1013 >>> np.dsplit(x, 2) 

1014 [array([[[ 0., 1.], 

1015 [ 4., 5.]], 

1016 [[ 8., 9.], 

1017 [12., 13.]]]), array([[[ 2., 3.], 

1018 [ 6., 7.]], 

1019 [[10., 11.], 

1020 [14., 15.]]])] 

1021 >>> np.dsplit(x, np.array([3, 6])) 

1022 [array([[[ 0., 1., 2.], 

1023 [ 4., 5., 6.]], 

1024 [[ 8., 9., 10.], 

1025 [12., 13., 14.]]]), 

1026 array([[[ 3.], 

1027 [ 7.]], 

1028 [[11.], 

1029 [15.]]]), 

1030 array([], shape=(2, 2, 0), dtype=float64)] 

1031 """ 

1032 if _nx.ndim(ary) < 3: 

1033 raise ValueError('dsplit only works on arrays of 3 or more dimensions') 

1034 return split(ary, indices_or_sections, 2) 

1035 

1036 

1037def get_array_prepare(*args): 

1038 """Find the wrapper for the array with the highest priority. 

1039 

1040 In case of ties, leftmost wins. If no wrapper is found, return None 

1041 """ 

1042 wrappers = sorted((getattr(x, '__array_priority__', 0), -i, 

1043 x.__array_prepare__) for i, x in enumerate(args) 

1044 if hasattr(x, '__array_prepare__')) 

1045 if wrappers: 

1046 return wrappers[-1][-1] 

1047 return None 

1048 

1049 

1050def get_array_wrap(*args): 

1051 """Find the wrapper for the array with the highest priority. 

1052 

1053 In case of ties, leftmost wins. If no wrapper is found, return None 

1054 """ 

1055 wrappers = sorted((getattr(x, '__array_priority__', 0), -i, 

1056 x.__array_wrap__) for i, x in enumerate(args) 

1057 if hasattr(x, '__array_wrap__')) 

1058 if wrappers: 

1059 return wrappers[-1][-1] 

1060 return None 

1061 

1062 

1063def _kron_dispatcher(a, b): 

1064 return (a, b) 

1065 

1066 

1067@array_function_dispatch(_kron_dispatcher) 

1068def kron(a, b): 

1069 """ 

1070 Kronecker product of two arrays. 

1071 

1072 Computes the Kronecker product, a composite array made of blocks of the 

1073 second array scaled by the first. 

1074 

1075 Parameters 

1076 ---------- 

1077 a, b : array_like 

1078 

1079 Returns 

1080 ------- 

1081 out : ndarray 

1082 

1083 See Also 

1084 -------- 

1085 outer : The outer product 

1086 

1087 Notes 

1088 ----- 

1089 The function assumes that the number of dimensions of `a` and `b` 

1090 are the same, if necessary prepending the smallest with ones. 

1091 If ``a.shape = (r0,r1,..,rN)`` and ``b.shape = (s0,s1,...,sN)``, 

1092 the Kronecker product has shape ``(r0*s0, r1*s1, ..., rN*SN)``. 

1093 The elements are products of elements from `a` and `b`, organized 

1094 explicitly by:: 

1095 

1096 kron(a,b)[k0,k1,...,kN] = a[i0,i1,...,iN] * b[j0,j1,...,jN] 

1097 

1098 where:: 

1099 

1100 kt = it * st + jt, t = 0,...,N 

1101 

1102 In the common 2-D case (N=1), the block structure can be visualized:: 

1103 

1104 [[ a[0,0]*b, a[0,1]*b, ... , a[0,-1]*b ], 

1105 [ ... ... ], 

1106 [ a[-1,0]*b, a[-1,1]*b, ... , a[-1,-1]*b ]] 

1107 

1108 

1109 Examples 

1110 -------- 

1111 >>> np.kron([1,10,100], [5,6,7]) 

1112 array([ 5, 6, 7, ..., 500, 600, 700]) 

1113 >>> np.kron([5,6,7], [1,10,100]) 

1114 array([ 5, 50, 500, ..., 7, 70, 700]) 

1115 

1116 >>> np.kron(np.eye(2), np.ones((2,2))) 

1117 array([[1., 1., 0., 0.], 

1118 [1., 1., 0., 0.], 

1119 [0., 0., 1., 1.], 

1120 [0., 0., 1., 1.]]) 

1121 

1122 >>> a = np.arange(100).reshape((2,5,2,5)) 

1123 >>> b = np.arange(24).reshape((2,3,4)) 

1124 >>> c = np.kron(a,b) 

1125 >>> c.shape 

1126 (2, 10, 6, 20) 

1127 >>> I = (1,3,0,2) 

1128 >>> J = (0,2,1) 

1129 >>> J1 = (0,) + J # extend to ndim=4 

1130 >>> S1 = (1,) + b.shape 

1131 >>> K = tuple(np.array(I) * np.array(S1) + np.array(J1)) 

1132 >>> c[K] == a[I]*b[J] 

1133 True 

1134 

1135 """ 

1136 # Working: 

1137 # 1. Equalise the shapes by prepending smaller array with 1s 

1138 # 2. Expand shapes of both the arrays by adding new axes at 

1139 # odd positions for 1st array and even positions for 2nd 

1140 # 3. Compute the product of the modified array 

1141 # 4. The inner most array elements now contain the rows of 

1142 # the Kronecker product 

1143 # 5. Reshape the result to kron's shape, which is same as 

1144 # product of shapes of the two arrays. 

1145 b = asanyarray(b) 

1146 a = array(a, copy=False, subok=True, ndmin=b.ndim) 

1147 is_any_mat = isinstance(a, matrix) or isinstance(b, matrix) 

1148 ndb, nda = b.ndim, a.ndim 

1149 nd = max(ndb, nda) 

1150 

1151 if (nda == 0 or ndb == 0): 

1152 return _nx.multiply(a, b) 

1153 

1154 as_ = a.shape 

1155 bs = b.shape 

1156 if not a.flags.contiguous: 

1157 a = reshape(a, as_) 

1158 if not b.flags.contiguous: 

1159 b = reshape(b, bs) 

1160 

1161 # Equalise the shapes by prepending smaller one with 1s 

1162 as_ = (1,)*max(0, ndb-nda) + as_ 

1163 bs = (1,)*max(0, nda-ndb) + bs 

1164 

1165 # Insert empty dimensions 

1166 a_arr = expand_dims(a, axis=tuple(range(ndb-nda))) 

1167 b_arr = expand_dims(b, axis=tuple(range(nda-ndb))) 

1168 

1169 # Compute the product 

1170 a_arr = expand_dims(a_arr, axis=tuple(range(1, nd*2, 2))) 

1171 b_arr = expand_dims(b_arr, axis=tuple(range(0, nd*2, 2))) 

1172 # In case of `mat`, convert result to `array` 

1173 result = _nx.multiply(a_arr, b_arr, subok=(not is_any_mat)) 

1174 

1175 # Reshape back 

1176 result = result.reshape(_nx.multiply(as_, bs)) 

1177 

1178 return result if not is_any_mat else matrix(result, copy=False) 

1179 

1180 

1181def _tile_dispatcher(A, reps): 

1182 return (A, reps) 

1183 

1184 

1185@array_function_dispatch(_tile_dispatcher) 

1186def tile(A, reps): 

1187 """ 

1188 Construct an array by repeating A the number of times given by reps. 

1189 

1190 If `reps` has length ``d``, the result will have dimension of 

1191 ``max(d, A.ndim)``. 

1192 

1193 If ``A.ndim < d``, `A` is promoted to be d-dimensional by prepending new 

1194 axes. So a shape (3,) array is promoted to (1, 3) for 2-D replication, 

1195 or shape (1, 1, 3) for 3-D replication. If this is not the desired 

1196 behavior, promote `A` to d-dimensions manually before calling this 

1197 function. 

1198 

1199 If ``A.ndim > d``, `reps` is promoted to `A`.ndim by pre-pending 1's to it. 

1200 Thus for an `A` of shape (2, 3, 4, 5), a `reps` of (2, 2) is treated as 

1201 (1, 1, 2, 2). 

1202 

1203 Note : Although tile may be used for broadcasting, it is strongly 

1204 recommended to use numpy's broadcasting operations and functions. 

1205 

1206 Parameters 

1207 ---------- 

1208 A : array_like 

1209 The input array. 

1210 reps : array_like 

1211 The number of repetitions of `A` along each axis. 

1212 

1213 Returns 

1214 ------- 

1215 c : ndarray 

1216 The tiled output array. 

1217 

1218 See Also 

1219 -------- 

1220 repeat : Repeat elements of an array. 

1221 broadcast_to : Broadcast an array to a new shape 

1222 

1223 Examples 

1224 -------- 

1225 >>> a = np.array([0, 1, 2]) 

1226 >>> np.tile(a, 2) 

1227 array([0, 1, 2, 0, 1, 2]) 

1228 >>> np.tile(a, (2, 2)) 

1229 array([[0, 1, 2, 0, 1, 2], 

1230 [0, 1, 2, 0, 1, 2]]) 

1231 >>> np.tile(a, (2, 1, 2)) 

1232 array([[[0, 1, 2, 0, 1, 2]], 

1233 [[0, 1, 2, 0, 1, 2]]]) 

1234 

1235 >>> b = np.array([[1, 2], [3, 4]]) 

1236 >>> np.tile(b, 2) 

1237 array([[1, 2, 1, 2], 

1238 [3, 4, 3, 4]]) 

1239 >>> np.tile(b, (2, 1)) 

1240 array([[1, 2], 

1241 [3, 4], 

1242 [1, 2], 

1243 [3, 4]]) 

1244 

1245 >>> c = np.array([1,2,3,4]) 

1246 >>> np.tile(c,(4,1)) 

1247 array([[1, 2, 3, 4], 

1248 [1, 2, 3, 4], 

1249 [1, 2, 3, 4], 

1250 [1, 2, 3, 4]]) 

1251 """ 

1252 try: 

1253 tup = tuple(reps) 

1254 except TypeError: 

1255 tup = (reps,) 

1256 d = len(tup) 

1257 if all(x == 1 for x in tup) and isinstance(A, _nx.ndarray): 

1258 # Fixes the problem that the function does not make a copy if A is a 

1259 # numpy array and the repetitions are 1 in all dimensions 

1260 return _nx.array(A, copy=True, subok=True, ndmin=d) 

1261 else: 

1262 # Note that no copy of zero-sized arrays is made. However since they 

1263 # have no data there is no risk of an inadvertent overwrite. 

1264 c = _nx.array(A, copy=False, subok=True, ndmin=d) 

1265 if (d < c.ndim): 

1266 tup = (1,)*(c.ndim-d) + tup 

1267 shape_out = tuple(s*t for s, t in zip(c.shape, tup)) 

1268 n = c.size 

1269 if n > 0: 

1270 for dim_in, nrep in zip(c.shape, tup): 

1271 if nrep != 1: 

1272 c = c.reshape(-1, n).repeat(nrep, 0) 

1273 n //= dim_in 

1274 return c.reshape(shape_out)