Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/numpy/lib/function_base.py: 13%

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

1221 statements  

1import collections.abc 

2import functools 

3import re 

4import sys 

5import warnings 

6 

7import numpy as np 

8import numpy.core.numeric as _nx 

9from numpy.core import transpose 

10from numpy.core.numeric import ( 

11 ones, zeros_like, arange, concatenate, array, asarray, asanyarray, empty, 

12 ndarray, take, dot, where, intp, integer, isscalar, absolute 

13 ) 

14from numpy.core.umath import ( 

15 pi, add, arctan2, frompyfunc, cos, less_equal, sqrt, sin, 

16 mod, exp, not_equal, subtract 

17 ) 

18from numpy.core.fromnumeric import ( 

19 ravel, nonzero, partition, mean, any, sum 

20 ) 

21from numpy.core.numerictypes import typecodes 

22from numpy.core.overrides import set_module 

23from numpy.core import overrides 

24from numpy.core.function_base import add_newdoc 

25from numpy.lib.twodim_base import diag 

26from numpy.core.multiarray import ( 

27 _insert, add_docstring, bincount, normalize_axis_index, _monotonicity, 

28 interp as compiled_interp, interp_complex as compiled_interp_complex 

29 ) 

30from numpy.core.umath import _add_newdoc_ufunc as add_newdoc_ufunc 

31 

32import builtins 

33 

34# needed in this module for compatibility 

35from numpy.lib.histograms import histogram, histogramdd # noqa: F401 

36 

37 

38array_function_dispatch = functools.partial( 

39 overrides.array_function_dispatch, module='numpy') 

40 

41 

42__all__ = [ 

43 'select', 'piecewise', 'trim_zeros', 'copy', 'iterable', 'percentile', 

44 'diff', 'gradient', 'angle', 'unwrap', 'sort_complex', 'disp', 'flip', 

45 'rot90', 'extract', 'place', 'vectorize', 'asarray_chkfinite', 'average', 

46 'bincount', 'digitize', 'cov', 'corrcoef', 

47 'msort', 'median', 'sinc', 'hamming', 'hanning', 'bartlett', 

48 'blackman', 'kaiser', 'trapz', 'i0', 'add_newdoc', 'add_docstring', 

49 'meshgrid', 'delete', 'insert', 'append', 'interp', 'add_newdoc_ufunc', 

50 'quantile' 

51 ] 

52 

53# _QuantileMethods is a dictionary listing all the supported methods to 

54# compute quantile/percentile. 

55# 

56# Below virtual_index refer to the index of the element where the percentile 

57# would be found in the sorted sample. 

58# When the sample contains exactly the percentile wanted, the virtual_index is 

59# an integer to the index of this element. 

60# When the percentile wanted is in between two elements, the virtual_index 

61# is made of a integer part (a.k.a 'i' or 'left') and a fractional part 

62# (a.k.a 'g' or 'gamma') 

63# 

64# Each method in _QuantileMethods has two properties 

65# get_virtual_index : Callable 

66# The function used to compute the virtual_index. 

67# fix_gamma : Callable 

68# A function used for discret methods to force the index to a specific value. 

69_QuantileMethods = dict( 

70 # --- HYNDMAN and FAN METHODS 

71 # Discrete methods 

72 inverted_cdf=dict( 

73 get_virtual_index=lambda n, quantiles: _inverted_cdf(n, quantiles), 

74 fix_gamma=lambda gamma, _: gamma, # should never be called 

75 ), 

76 averaged_inverted_cdf=dict( 

77 get_virtual_index=lambda n, quantiles: (n * quantiles) - 1, 

78 fix_gamma=lambda gamma, _: _get_gamma_mask( 

79 shape=gamma.shape, 

80 default_value=1., 

81 conditioned_value=0.5, 

82 where=gamma == 0), 

83 ), 

84 closest_observation=dict( 

85 get_virtual_index=lambda n, quantiles: _closest_observation(n, 

86 quantiles), 

87 fix_gamma=lambda gamma, _: gamma, # should never be called 

88 ), 

89 # Continuous methods 

90 interpolated_inverted_cdf=dict( 

91 get_virtual_index=lambda n, quantiles: 

92 _compute_virtual_index(n, quantiles, 0, 1), 

93 fix_gamma=lambda gamma, _: gamma, 

94 ), 

95 hazen=dict( 

96 get_virtual_index=lambda n, quantiles: 

97 _compute_virtual_index(n, quantiles, 0.5, 0.5), 

98 fix_gamma=lambda gamma, _: gamma, 

99 ), 

100 weibull=dict( 

101 get_virtual_index=lambda n, quantiles: 

102 _compute_virtual_index(n, quantiles, 0, 0), 

103 fix_gamma=lambda gamma, _: gamma, 

104 ), 

105 # Default method. 

106 # To avoid some rounding issues, `(n-1) * quantiles` is preferred to 

107 # `_compute_virtual_index(n, quantiles, 1, 1)`. 

108 # They are mathematically equivalent. 

109 linear=dict( 

110 get_virtual_index=lambda n, quantiles: (n - 1) * quantiles, 

111 fix_gamma=lambda gamma, _: gamma, 

112 ), 

113 median_unbiased=dict( 

114 get_virtual_index=lambda n, quantiles: 

115 _compute_virtual_index(n, quantiles, 1 / 3.0, 1 / 3.0), 

116 fix_gamma=lambda gamma, _: gamma, 

117 ), 

118 normal_unbiased=dict( 

119 get_virtual_index=lambda n, quantiles: 

120 _compute_virtual_index(n, quantiles, 3 / 8.0, 3 / 8.0), 

121 fix_gamma=lambda gamma, _: gamma, 

122 ), 

123 # --- OTHER METHODS 

124 lower=dict( 

125 get_virtual_index=lambda n, quantiles: np.floor( 

126 (n - 1) * quantiles).astype(np.intp), 

127 fix_gamma=lambda gamma, _: gamma, 

128 # should never be called, index dtype is int 

129 ), 

130 higher=dict( 

131 get_virtual_index=lambda n, quantiles: np.ceil( 

132 (n - 1) * quantiles).astype(np.intp), 

133 fix_gamma=lambda gamma, _: gamma, 

134 # should never be called, index dtype is int 

135 ), 

136 midpoint=dict( 

137 get_virtual_index=lambda n, quantiles: 0.5 * ( 

138 np.floor((n - 1) * quantiles) 

139 + np.ceil((n - 1) * quantiles)), 

140 fix_gamma=lambda gamma, index: _get_gamma_mask( 

141 shape=gamma.shape, 

142 default_value=0.5, 

143 conditioned_value=0., 

144 where=index % 1 == 0), 

145 ), 

146 nearest=dict( 

147 get_virtual_index=lambda n, quantiles: np.around( 

148 (n - 1) * quantiles).astype(np.intp), 

149 fix_gamma=lambda gamma, _: gamma, 

150 # should never be called, index dtype is int 

151 )) 

152 

153 

154def _rot90_dispatcher(m, k=None, axes=None): 

155 return (m,) 

156 

157 

158@array_function_dispatch(_rot90_dispatcher) 

159def rot90(m, k=1, axes=(0, 1)): 

160 """ 

161 Rotate an array by 90 degrees in the plane specified by axes. 

162 

163 Rotation direction is from the first towards the second axis. 

164 

165 Parameters 

166 ---------- 

167 m : array_like 

168 Array of two or more dimensions. 

169 k : integer 

170 Number of times the array is rotated by 90 degrees. 

171 axes : (2,) array_like 

172 The array is rotated in the plane defined by the axes. 

173 Axes must be different. 

174 

175 .. versionadded:: 1.12.0 

176 

177 Returns 

178 ------- 

179 y : ndarray 

180 A rotated view of `m`. 

181 

182 See Also 

183 -------- 

184 flip : Reverse the order of elements in an array along the given axis. 

185 fliplr : Flip an array horizontally. 

186 flipud : Flip an array vertically. 

187 

188 Notes 

189 ----- 

190 ``rot90(m, k=1, axes=(1,0))`` is the reverse of 

191 ``rot90(m, k=1, axes=(0,1))`` 

192 

193 ``rot90(m, k=1, axes=(1,0))`` is equivalent to 

194 ``rot90(m, k=-1, axes=(0,1))`` 

195 

196 Examples 

197 -------- 

198 >>> m = np.array([[1,2],[3,4]], int) 

199 >>> m 

200 array([[1, 2], 

201 [3, 4]]) 

202 >>> np.rot90(m) 

203 array([[2, 4], 

204 [1, 3]]) 

205 >>> np.rot90(m, 2) 

206 array([[4, 3], 

207 [2, 1]]) 

208 >>> m = np.arange(8).reshape((2,2,2)) 

209 >>> np.rot90(m, 1, (1,2)) 

210 array([[[1, 3], 

211 [0, 2]], 

212 [[5, 7], 

213 [4, 6]]]) 

214 

215 """ 

216 axes = tuple(axes) 

217 if len(axes) != 2: 

218 raise ValueError("len(axes) must be 2.") 

219 

220 m = asanyarray(m) 

221 

222 if axes[0] == axes[1] or absolute(axes[0] - axes[1]) == m.ndim: 

223 raise ValueError("Axes must be different.") 

224 

225 if (axes[0] >= m.ndim or axes[0] < -m.ndim 

226 or axes[1] >= m.ndim or axes[1] < -m.ndim): 

227 raise ValueError("Axes={} out of range for array of ndim={}." 

228 .format(axes, m.ndim)) 

229 

230 k %= 4 

231 

232 if k == 0: 

233 return m[:] 

234 if k == 2: 

235 return flip(flip(m, axes[0]), axes[1]) 

236 

237 axes_list = arange(0, m.ndim) 

238 (axes_list[axes[0]], axes_list[axes[1]]) = (axes_list[axes[1]], 

239 axes_list[axes[0]]) 

240 

241 if k == 1: 

242 return transpose(flip(m, axes[1]), axes_list) 

243 else: 

244 # k == 3 

245 return flip(transpose(m, axes_list), axes[1]) 

246 

247 

248def _flip_dispatcher(m, axis=None): 

249 return (m,) 

250 

251 

252@array_function_dispatch(_flip_dispatcher) 

253def flip(m, axis=None): 

254 """ 

255 Reverse the order of elements in an array along the given axis. 

256 

257 The shape of the array is preserved, but the elements are reordered. 

258 

259 .. versionadded:: 1.12.0 

260 

261 Parameters 

262 ---------- 

263 m : array_like 

264 Input array. 

265 axis : None or int or tuple of ints, optional 

266 Axis or axes along which to flip over. The default, 

267 axis=None, will flip over all of the axes of the input array. 

268 If axis is negative it counts from the last to the first axis. 

269 

270 If axis is a tuple of ints, flipping is performed on all of the axes 

271 specified in the tuple. 

272 

273 .. versionchanged:: 1.15.0 

274 None and tuples of axes are supported 

275 

276 Returns 

277 ------- 

278 out : array_like 

279 A view of `m` with the entries of axis reversed. Since a view is 

280 returned, this operation is done in constant time. 

281 

282 See Also 

283 -------- 

284 flipud : Flip an array vertically (axis=0). 

285 fliplr : Flip an array horizontally (axis=1). 

286 

287 Notes 

288 ----- 

289 flip(m, 0) is equivalent to flipud(m). 

290 

291 flip(m, 1) is equivalent to fliplr(m). 

292 

293 flip(m, n) corresponds to ``m[...,::-1,...]`` with ``::-1`` at position n. 

294 

295 flip(m) corresponds to ``m[::-1,::-1,...,::-1]`` with ``::-1`` at all 

296 positions. 

297 

298 flip(m, (0, 1)) corresponds to ``m[::-1,::-1,...]`` with ``::-1`` at 

299 position 0 and position 1. 

300 

301 Examples 

302 -------- 

303 >>> A = np.arange(8).reshape((2,2,2)) 

304 >>> A 

305 array([[[0, 1], 

306 [2, 3]], 

307 [[4, 5], 

308 [6, 7]]]) 

309 >>> np.flip(A, 0) 

310 array([[[4, 5], 

311 [6, 7]], 

312 [[0, 1], 

313 [2, 3]]]) 

314 >>> np.flip(A, 1) 

315 array([[[2, 3], 

316 [0, 1]], 

317 [[6, 7], 

318 [4, 5]]]) 

319 >>> np.flip(A) 

320 array([[[7, 6], 

321 [5, 4]], 

322 [[3, 2], 

323 [1, 0]]]) 

324 >>> np.flip(A, (0, 2)) 

325 array([[[5, 4], 

326 [7, 6]], 

327 [[1, 0], 

328 [3, 2]]]) 

329 >>> A = np.random.randn(3,4,5) 

330 >>> np.all(np.flip(A,2) == A[:,:,::-1,...]) 

331 True 

332 """ 

333 if not hasattr(m, 'ndim'): 

334 m = asarray(m) 

335 if axis is None: 

336 indexer = (np.s_[::-1],) * m.ndim 

337 else: 

338 axis = _nx.normalize_axis_tuple(axis, m.ndim) 

339 indexer = [np.s_[:]] * m.ndim 

340 for ax in axis: 

341 indexer[ax] = np.s_[::-1] 

342 indexer = tuple(indexer) 

343 return m[indexer] 

344 

345 

346@set_module('numpy') 

347def iterable(y): 

348 """ 

349 Check whether or not an object can be iterated over. 

350 

351 Parameters 

352 ---------- 

353 y : object 

354 Input object. 

355 

356 Returns 

357 ------- 

358 b : bool 

359 Return ``True`` if the object has an iterator method or is a 

360 sequence and ``False`` otherwise. 

361 

362 

363 Examples 

364 -------- 

365 >>> np.iterable([1, 2, 3]) 

366 True 

367 >>> np.iterable(2) 

368 False 

369 

370 Notes 

371 ----- 

372 In most cases, the results of ``np.iterable(obj)`` are consistent with 

373 ``isinstance(obj, collections.abc.Iterable)``. One notable exception is 

374 the treatment of 0-dimensional arrays:: 

375 

376 >>> from collections.abc import Iterable 

377 >>> a = np.array(1.0) # 0-dimensional numpy array 

378 >>> isinstance(a, Iterable) 

379 True 

380 >>> np.iterable(a) 

381 False 

382 

383 """ 

384 try: 

385 iter(y) 

386 except TypeError: 

387 return False 

388 return True 

389 

390 

391def _average_dispatcher(a, axis=None, weights=None, returned=None, *, 

392 keepdims=None): 

393 return (a, weights) 

394 

395 

396@array_function_dispatch(_average_dispatcher) 

397def average(a, axis=None, weights=None, returned=False, *, 

398 keepdims=np._NoValue): 

399 """ 

400 Compute the weighted average along the specified axis. 

401 

402 Parameters 

403 ---------- 

404 a : array_like 

405 Array containing data to be averaged. If `a` is not an array, a 

406 conversion is attempted. 

407 axis : None or int or tuple of ints, optional 

408 Axis or axes along which to average `a`. The default, 

409 axis=None, will average over all of the elements of the input array. 

410 If axis is negative it counts from the last to the first axis. 

411 

412 .. versionadded:: 1.7.0 

413 

414 If axis is a tuple of ints, averaging is performed on all of the axes 

415 specified in the tuple instead of a single axis or all the axes as 

416 before. 

417 weights : array_like, optional 

418 An array of weights associated with the values in `a`. Each value in 

419 `a` contributes to the average according to its associated weight. 

420 The weights array can either be 1-D (in which case its length must be 

421 the size of `a` along the given axis) or of the same shape as `a`. 

422 If `weights=None`, then all data in `a` are assumed to have a 

423 weight equal to one. The 1-D calculation is:: 

424 

425 avg = sum(a * weights) / sum(weights) 

426 

427 The only constraint on `weights` is that `sum(weights)` must not be 0. 

428 returned : bool, optional 

429 Default is `False`. If `True`, the tuple (`average`, `sum_of_weights`) 

430 is returned, otherwise only the average is returned. 

431 If `weights=None`, `sum_of_weights` is equivalent to the number of 

432 elements over which the average is taken. 

433 keepdims : bool, optional 

434 If this is set to True, the axes which are reduced are left 

435 in the result as dimensions with size one. With this option, 

436 the result will broadcast correctly against the original `a`. 

437 *Note:* `keepdims` will not work with instances of `numpy.matrix` 

438 or other classes whose methods do not support `keepdims`. 

439 

440 .. versionadded:: 1.23.0 

441 

442 Returns 

443 ------- 

444 retval, [sum_of_weights] : array_type or double 

445 Return the average along the specified axis. When `returned` is `True`, 

446 return a tuple with the average as the first element and the sum 

447 of the weights as the second element. `sum_of_weights` is of the 

448 same type as `retval`. The result dtype follows a genereal pattern. 

449 If `weights` is None, the result dtype will be that of `a` , or ``float64`` 

450 if `a` is integral. Otherwise, if `weights` is not None and `a` is non- 

451 integral, the result type will be the type of lowest precision capable of 

452 representing values of both `a` and `weights`. If `a` happens to be 

453 integral, the previous rules still applies but the result dtype will 

454 at least be ``float64``. 

455 

456 Raises 

457 ------ 

458 ZeroDivisionError 

459 When all weights along axis are zero. See `numpy.ma.average` for a 

460 version robust to this type of error. 

461 TypeError 

462 When the length of 1D `weights` is not the same as the shape of `a` 

463 along axis. 

464 

465 See Also 

466 -------- 

467 mean 

468 

469 ma.average : average for masked arrays -- useful if your data contains 

470 "missing" values 

471 numpy.result_type : Returns the type that results from applying the 

472 numpy type promotion rules to the arguments. 

473 

474 Examples 

475 -------- 

476 >>> data = np.arange(1, 5) 

477 >>> data 

478 array([1, 2, 3, 4]) 

479 >>> np.average(data) 

480 2.5 

481 >>> np.average(np.arange(1, 11), weights=np.arange(10, 0, -1)) 

482 4.0 

483 

484 >>> data = np.arange(6).reshape((3, 2)) 

485 >>> data 

486 array([[0, 1], 

487 [2, 3], 

488 [4, 5]]) 

489 >>> np.average(data, axis=1, weights=[1./4, 3./4]) 

490 array([0.75, 2.75, 4.75]) 

491 >>> np.average(data, weights=[1./4, 3./4]) 

492 Traceback (most recent call last): 

493 ... 

494 TypeError: Axis must be specified when shapes of a and weights differ. 

495 

496 >>> a = np.ones(5, dtype=np.float128) 

497 >>> w = np.ones(5, dtype=np.complex64) 

498 >>> avg = np.average(a, weights=w) 

499 >>> print(avg.dtype) 

500 complex256 

501 

502 With ``keepdims=True``, the following result has shape (3, 1). 

503 

504 >>> np.average(data, axis=1, keepdims=True) 

505 array([[0.5], 

506 [2.5], 

507 [4.5]]) 

508 """ 

509 a = np.asanyarray(a) 

510 

511 if keepdims is np._NoValue: 

512 # Don't pass on the keepdims argument if one wasn't given. 

513 keepdims_kw = {} 

514 else: 

515 keepdims_kw = {'keepdims': keepdims} 

516 

517 if weights is None: 

518 avg = a.mean(axis, **keepdims_kw) 

519 avg_as_array = np.asanyarray(avg) 

520 scl = avg_as_array.dtype.type(a.size/avg_as_array.size) 

521 else: 

522 wgt = np.asanyarray(weights) 

523 

524 if issubclass(a.dtype.type, (np.integer, np.bool_)): 

525 result_dtype = np.result_type(a.dtype, wgt.dtype, 'f8') 

526 else: 

527 result_dtype = np.result_type(a.dtype, wgt.dtype) 

528 

529 # Sanity checks 

530 if a.shape != wgt.shape: 

531 if axis is None: 

532 raise TypeError( 

533 "Axis must be specified when shapes of a and weights " 

534 "differ.") 

535 if wgt.ndim != 1: 

536 raise TypeError( 

537 "1D weights expected when shapes of a and weights differ.") 

538 if wgt.shape[0] != a.shape[axis]: 

539 raise ValueError( 

540 "Length of weights not compatible with specified axis.") 

541 

542 # setup wgt to broadcast along axis 

543 wgt = np.broadcast_to(wgt, (a.ndim-1)*(1,) + wgt.shape) 

544 wgt = wgt.swapaxes(-1, axis) 

545 

546 scl = wgt.sum(axis=axis, dtype=result_dtype, **keepdims_kw) 

547 if np.any(scl == 0.0): 

548 raise ZeroDivisionError( 

549 "Weights sum to zero, can't be normalized") 

550 

551 avg = avg_as_array = np.multiply(a, wgt, 

552 dtype=result_dtype).sum(axis, **keepdims_kw) / scl 

553 

554 if returned: 

555 if scl.shape != avg_as_array.shape: 

556 scl = np.broadcast_to(scl, avg_as_array.shape).copy() 

557 return avg, scl 

558 else: 

559 return avg 

560 

561 

562@set_module('numpy') 

563def asarray_chkfinite(a, dtype=None, order=None): 

564 """Convert the input to an array, checking for NaNs or Infs. 

565 

566 Parameters 

567 ---------- 

568 a : array_like 

569 Input data, in any form that can be converted to an array. This 

570 includes lists, lists of tuples, tuples, tuples of tuples, tuples 

571 of lists and ndarrays. Success requires no NaNs or Infs. 

572 dtype : data-type, optional 

573 By default, the data-type is inferred from the input data. 

574 order : {'C', 'F', 'A', 'K'}, optional 

575 Memory layout. 'A' and 'K' depend on the order of input array a. 

576 'C' row-major (C-style), 

577 'F' column-major (Fortran-style) memory representation. 

578 'A' (any) means 'F' if `a` is Fortran contiguous, 'C' otherwise 

579 'K' (keep) preserve input order 

580 Defaults to 'C'. 

581 

582 Returns 

583 ------- 

584 out : ndarray 

585 Array interpretation of `a`. No copy is performed if the input 

586 is already an ndarray. If `a` is a subclass of ndarray, a base 

587 class ndarray is returned. 

588 

589 Raises 

590 ------ 

591 ValueError 

592 Raises ValueError if `a` contains NaN (Not a Number) or Inf (Infinity). 

593 

594 See Also 

595 -------- 

596 asarray : Create and array. 

597 asanyarray : Similar function which passes through subclasses. 

598 ascontiguousarray : Convert input to a contiguous array. 

599 asfarray : Convert input to a floating point ndarray. 

600 asfortranarray : Convert input to an ndarray with column-major 

601 memory order. 

602 fromiter : Create an array from an iterator. 

603 fromfunction : Construct an array by executing a function on grid 

604 positions. 

605 

606 Examples 

607 -------- 

608 Convert a list into an array. If all elements are finite 

609 ``asarray_chkfinite`` is identical to ``asarray``. 

610 

611 >>> a = [1, 2] 

612 >>> np.asarray_chkfinite(a, dtype=float) 

613 array([1., 2.]) 

614 

615 Raises ValueError if array_like contains Nans or Infs. 

616 

617 >>> a = [1, 2, np.inf] 

618 >>> try: 

619 ... np.asarray_chkfinite(a) 

620 ... except ValueError: 

621 ... print('ValueError') 

622 ... 

623 ValueError 

624 

625 """ 

626 a = asarray(a, dtype=dtype, order=order) 

627 if a.dtype.char in typecodes['AllFloat'] and not np.isfinite(a).all(): 

628 raise ValueError( 

629 "array must not contain infs or NaNs") 

630 return a 

631 

632 

633def _piecewise_dispatcher(x, condlist, funclist, *args, **kw): 

634 yield x 

635 # support the undocumented behavior of allowing scalars 

636 if np.iterable(condlist): 

637 yield from condlist 

638 

639 

640@array_function_dispatch(_piecewise_dispatcher) 

641def piecewise(x, condlist, funclist, *args, **kw): 

642 """ 

643 Evaluate a piecewise-defined function. 

644 

645 Given a set of conditions and corresponding functions, evaluate each 

646 function on the input data wherever its condition is true. 

647 

648 Parameters 

649 ---------- 

650 x : ndarray or scalar 

651 The input domain. 

652 condlist : list of bool arrays or bool scalars 

653 Each boolean array corresponds to a function in `funclist`. Wherever 

654 `condlist[i]` is True, `funclist[i](x)` is used as the output value. 

655 

656 Each boolean array in `condlist` selects a piece of `x`, 

657 and should therefore be of the same shape as `x`. 

658 

659 The length of `condlist` must correspond to that of `funclist`. 

660 If one extra function is given, i.e. if 

661 ``len(funclist) == len(condlist) + 1``, then that extra function 

662 is the default value, used wherever all conditions are false. 

663 funclist : list of callables, f(x,*args,**kw), or scalars 

664 Each function is evaluated over `x` wherever its corresponding 

665 condition is True. It should take a 1d array as input and give an 1d 

666 array or a scalar value as output. If, instead of a callable, 

667 a scalar is provided then a constant function (``lambda x: scalar``) is 

668 assumed. 

669 args : tuple, optional 

670 Any further arguments given to `piecewise` are passed to the functions 

671 upon execution, i.e., if called ``piecewise(..., ..., 1, 'a')``, then 

672 each function is called as ``f(x, 1, 'a')``. 

673 kw : dict, optional 

674 Keyword arguments used in calling `piecewise` are passed to the 

675 functions upon execution, i.e., if called 

676 ``piecewise(..., ..., alpha=1)``, then each function is called as 

677 ``f(x, alpha=1)``. 

678 

679 Returns 

680 ------- 

681 out : ndarray 

682 The output is the same shape and type as x and is found by 

683 calling the functions in `funclist` on the appropriate portions of `x`, 

684 as defined by the boolean arrays in `condlist`. Portions not covered 

685 by any condition have a default value of 0. 

686 

687 

688 See Also 

689 -------- 

690 choose, select, where 

691 

692 Notes 

693 ----- 

694 This is similar to choose or select, except that functions are 

695 evaluated on elements of `x` that satisfy the corresponding condition from 

696 `condlist`. 

697 

698 The result is:: 

699 

700 |-- 

701 |funclist[0](x[condlist[0]]) 

702 out = |funclist[1](x[condlist[1]]) 

703 |... 

704 |funclist[n2](x[condlist[n2]]) 

705 |-- 

706 

707 Examples 

708 -------- 

709 Define the sigma function, which is -1 for ``x < 0`` and +1 for ``x >= 0``. 

710 

711 >>> x = np.linspace(-2.5, 2.5, 6) 

712 >>> np.piecewise(x, [x < 0, x >= 0], [-1, 1]) 

713 array([-1., -1., -1., 1., 1., 1.]) 

714 

715 Define the absolute value, which is ``-x`` for ``x <0`` and ``x`` for 

716 ``x >= 0``. 

717 

718 >>> np.piecewise(x, [x < 0, x >= 0], [lambda x: -x, lambda x: x]) 

719 array([2.5, 1.5, 0.5, 0.5, 1.5, 2.5]) 

720 

721 Apply the same function to a scalar value. 

722 

723 >>> y = -2 

724 >>> np.piecewise(y, [y < 0, y >= 0], [lambda x: -x, lambda x: x]) 

725 array(2) 

726 

727 """ 

728 x = asanyarray(x) 

729 n2 = len(funclist) 

730 

731 # undocumented: single condition is promoted to a list of one condition 

732 if isscalar(condlist) or ( 

733 not isinstance(condlist[0], (list, ndarray)) and x.ndim != 0): 

734 condlist = [condlist] 

735 

736 condlist = asarray(condlist, dtype=bool) 

737 n = len(condlist) 

738 

739 if n == n2 - 1: # compute the "otherwise" condition. 

740 condelse = ~np.any(condlist, axis=0, keepdims=True) 

741 condlist = np.concatenate([condlist, condelse], axis=0) 

742 n += 1 

743 elif n != n2: 

744 raise ValueError( 

745 "with {} condition(s), either {} or {} functions are expected" 

746 .format(n, n, n+1) 

747 ) 

748 

749 y = zeros_like(x) 

750 for cond, func in zip(condlist, funclist): 

751 if not isinstance(func, collections.abc.Callable): 

752 y[cond] = func 

753 else: 

754 vals = x[cond] 

755 if vals.size > 0: 

756 y[cond] = func(vals, *args, **kw) 

757 

758 return y 

759 

760 

761def _select_dispatcher(condlist, choicelist, default=None): 

762 yield from condlist 

763 yield from choicelist 

764 

765 

766@array_function_dispatch(_select_dispatcher) 

767def select(condlist, choicelist, default=0): 

768 """ 

769 Return an array drawn from elements in choicelist, depending on conditions. 

770 

771 Parameters 

772 ---------- 

773 condlist : list of bool ndarrays 

774 The list of conditions which determine from which array in `choicelist` 

775 the output elements are taken. When multiple conditions are satisfied, 

776 the first one encountered in `condlist` is used. 

777 choicelist : list of ndarrays 

778 The list of arrays from which the output elements are taken. It has 

779 to be of the same length as `condlist`. 

780 default : scalar, optional 

781 The element inserted in `output` when all conditions evaluate to False. 

782 

783 Returns 

784 ------- 

785 output : ndarray 

786 The output at position m is the m-th element of the array in 

787 `choicelist` where the m-th element of the corresponding array in 

788 `condlist` is True. 

789 

790 See Also 

791 -------- 

792 where : Return elements from one of two arrays depending on condition. 

793 take, choose, compress, diag, diagonal 

794 

795 Examples 

796 -------- 

797 >>> x = np.arange(6) 

798 >>> condlist = [x<3, x>3] 

799 >>> choicelist = [x, x**2] 

800 >>> np.select(condlist, choicelist, 42) 

801 array([ 0, 1, 2, 42, 16, 25]) 

802 

803 >>> condlist = [x<=4, x>3] 

804 >>> choicelist = [x, x**2] 

805 >>> np.select(condlist, choicelist, 55) 

806 array([ 0, 1, 2, 3, 4, 25]) 

807 

808 """ 

809 # Check the size of condlist and choicelist are the same, or abort. 

810 if len(condlist) != len(choicelist): 

811 raise ValueError( 

812 'list of cases must be same length as list of conditions') 

813 

814 # Now that the dtype is known, handle the deprecated select([], []) case 

815 if len(condlist) == 0: 

816 raise ValueError("select with an empty condition list is not possible") 

817 

818 choicelist = [np.asarray(choice) for choice in choicelist] 

819 

820 try: 

821 intermediate_dtype = np.result_type(*choicelist) 

822 except TypeError as e: 

823 msg = f'Choicelist elements do not have a common dtype: {e}' 

824 raise TypeError(msg) from None 

825 default_array = np.asarray(default) 

826 choicelist.append(default_array) 

827 

828 # need to get the result type before broadcasting for correct scalar 

829 # behaviour 

830 try: 

831 dtype = np.result_type(intermediate_dtype, default_array) 

832 except TypeError as e: 

833 msg = f'Choicelists and default value do not have a common dtype: {e}' 

834 raise TypeError(msg) from None 

835 

836 # Convert conditions to arrays and broadcast conditions and choices 

837 # as the shape is needed for the result. Doing it separately optimizes 

838 # for example when all choices are scalars. 

839 condlist = np.broadcast_arrays(*condlist) 

840 choicelist = np.broadcast_arrays(*choicelist) 

841 

842 # If cond array is not an ndarray in boolean format or scalar bool, abort. 

843 for i, cond in enumerate(condlist): 

844 if cond.dtype.type is not np.bool_: 

845 raise TypeError( 

846 'invalid entry {} in condlist: should be boolean ndarray'.format(i)) 

847 

848 if choicelist[0].ndim == 0: 

849 # This may be common, so avoid the call. 

850 result_shape = condlist[0].shape 

851 else: 

852 result_shape = np.broadcast_arrays(condlist[0], choicelist[0])[0].shape 

853 

854 result = np.full(result_shape, choicelist[-1], dtype) 

855 

856 # Use np.copyto to burn each choicelist array onto result, using the 

857 # corresponding condlist as a boolean mask. This is done in reverse 

858 # order since the first choice should take precedence. 

859 choicelist = choicelist[-2::-1] 

860 condlist = condlist[::-1] 

861 for choice, cond in zip(choicelist, condlist): 

862 np.copyto(result, choice, where=cond) 

863 

864 return result 

865 

866 

867def _copy_dispatcher(a, order=None, subok=None): 

868 return (a,) 

869 

870 

871@array_function_dispatch(_copy_dispatcher) 

872def copy(a, order='K', subok=False): 

873 """ 

874 Return an array copy of the given object. 

875 

876 Parameters 

877 ---------- 

878 a : array_like 

879 Input data. 

880 order : {'C', 'F', 'A', 'K'}, optional 

881 Controls the memory layout of the copy. 'C' means C-order, 

882 'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous, 

883 'C' otherwise. 'K' means match the layout of `a` as closely 

884 as possible. (Note that this function and :meth:`ndarray.copy` are very 

885 similar, but have different default values for their order= 

886 arguments.) 

887 subok : bool, optional 

888 If True, then sub-classes will be passed-through, otherwise the 

889 returned array will be forced to be a base-class array (defaults to False). 

890 

891 .. versionadded:: 1.19.0 

892 

893 Returns 

894 ------- 

895 arr : ndarray 

896 Array interpretation of `a`. 

897 

898 See Also 

899 -------- 

900 ndarray.copy : Preferred method for creating an array copy 

901 

902 Notes 

903 ----- 

904 This is equivalent to: 

905 

906 >>> np.array(a, copy=True) #doctest: +SKIP 

907 

908 Examples 

909 -------- 

910 Create an array x, with a reference y and a copy z: 

911 

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

913 >>> y = x 

914 >>> z = np.copy(x) 

915 

916 Note that, when we modify x, y changes, but not z: 

917 

918 >>> x[0] = 10 

919 >>> x[0] == y[0] 

920 True 

921 >>> x[0] == z[0] 

922 False 

923 

924 Note that, np.copy clears previously set WRITEABLE=False flag. 

925 

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

927 >>> a.flags["WRITEABLE"] = False 

928 >>> b = np.copy(a) 

929 >>> b.flags["WRITEABLE"] 

930 True 

931 >>> b[0] = 3 

932 >>> b 

933 array([3, 2, 3]) 

934 

935 Note that np.copy is a shallow copy and will not copy object 

936 elements within arrays. This is mainly important for arrays 

937 containing Python objects. The new array will contain the 

938 same object which may lead to surprises if that object can 

939 be modified (is mutable): 

940 

941 >>> a = np.array([1, 'm', [2, 3, 4]], dtype=object) 

942 >>> b = np.copy(a) 

943 >>> b[2][0] = 10 

944 >>> a 

945 array([1, 'm', list([10, 3, 4])], dtype=object) 

946 

947 To ensure all elements within an ``object`` array are copied, 

948 use `copy.deepcopy`: 

949 

950 >>> import copy 

951 >>> a = np.array([1, 'm', [2, 3, 4]], dtype=object) 

952 >>> c = copy.deepcopy(a) 

953 >>> c[2][0] = 10 

954 >>> c 

955 array([1, 'm', list([10, 3, 4])], dtype=object) 

956 >>> a 

957 array([1, 'm', list([2, 3, 4])], dtype=object) 

958 

959 """ 

960 return array(a, order=order, subok=subok, copy=True) 

961 

962# Basic operations 

963 

964 

965def _gradient_dispatcher(f, *varargs, axis=None, edge_order=None): 

966 yield f 

967 yield from varargs 

968 

969 

970@array_function_dispatch(_gradient_dispatcher) 

971def gradient(f, *varargs, axis=None, edge_order=1): 

972 """ 

973 Return the gradient of an N-dimensional array. 

974 

975 The gradient is computed using second order accurate central differences 

976 in the interior points and either first or second order accurate one-sides 

977 (forward or backwards) differences at the boundaries. 

978 The returned gradient hence has the same shape as the input array. 

979 

980 Parameters 

981 ---------- 

982 f : array_like 

983 An N-dimensional array containing samples of a scalar function. 

984 varargs : list of scalar or array, optional 

985 Spacing between f values. Default unitary spacing for all dimensions. 

986 Spacing can be specified using: 

987 

988 1. single scalar to specify a sample distance for all dimensions. 

989 2. N scalars to specify a constant sample distance for each dimension. 

990 i.e. `dx`, `dy`, `dz`, ... 

991 3. N arrays to specify the coordinates of the values along each 

992 dimension of F. The length of the array must match the size of 

993 the corresponding dimension 

994 4. Any combination of N scalars/arrays with the meaning of 2. and 3. 

995 

996 If `axis` is given, the number of varargs must equal the number of axes. 

997 Default: 1. 

998 

999 edge_order : {1, 2}, optional 

1000 Gradient is calculated using N-th order accurate differences 

1001 at the boundaries. Default: 1. 

1002 

1003 .. versionadded:: 1.9.1 

1004 

1005 axis : None or int or tuple of ints, optional 

1006 Gradient is calculated only along the given axis or axes 

1007 The default (axis = None) is to calculate the gradient for all the axes 

1008 of the input array. axis may be negative, in which case it counts from 

1009 the last to the first axis. 

1010 

1011 .. versionadded:: 1.11.0 

1012 

1013 Returns 

1014 ------- 

1015 gradient : ndarray or list of ndarray 

1016 A list of ndarrays (or a single ndarray if there is only one dimension) 

1017 corresponding to the derivatives of f with respect to each dimension. 

1018 Each derivative has the same shape as f. 

1019 

1020 Examples 

1021 -------- 

1022 >>> f = np.array([1, 2, 4, 7, 11, 16], dtype=float) 

1023 >>> np.gradient(f) 

1024 array([1. , 1.5, 2.5, 3.5, 4.5, 5. ]) 

1025 >>> np.gradient(f, 2) 

1026 array([0.5 , 0.75, 1.25, 1.75, 2.25, 2.5 ]) 

1027 

1028 Spacing can be also specified with an array that represents the coordinates 

1029 of the values F along the dimensions. 

1030 For instance a uniform spacing: 

1031 

1032 >>> x = np.arange(f.size) 

1033 >>> np.gradient(f, x) 

1034 array([1. , 1.5, 2.5, 3.5, 4.5, 5. ]) 

1035 

1036 Or a non uniform one: 

1037 

1038 >>> x = np.array([0., 1., 1.5, 3.5, 4., 6.], dtype=float) 

1039 >>> np.gradient(f, x) 

1040 array([1. , 3. , 3.5, 6.7, 6.9, 2.5]) 

1041 

1042 For two dimensional arrays, the return will be two arrays ordered by 

1043 axis. In this example the first array stands for the gradient in 

1044 rows and the second one in columns direction: 

1045 

1046 >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=float)) 

1047 [array([[ 2., 2., -1.], 

1048 [ 2., 2., -1.]]), array([[1. , 2.5, 4. ], 

1049 [1. , 1. , 1. ]])] 

1050 

1051 In this example the spacing is also specified: 

1052 uniform for axis=0 and non uniform for axis=1 

1053 

1054 >>> dx = 2. 

1055 >>> y = [1., 1.5, 3.5] 

1056 >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=float), dx, y) 

1057 [array([[ 1. , 1. , -0.5], 

1058 [ 1. , 1. , -0.5]]), array([[2. , 2. , 2. ], 

1059 [2. , 1.7, 0.5]])] 

1060 

1061 It is possible to specify how boundaries are treated using `edge_order` 

1062 

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

1064 >>> f = x**2 

1065 >>> np.gradient(f, edge_order=1) 

1066 array([1., 2., 4., 6., 7.]) 

1067 >>> np.gradient(f, edge_order=2) 

1068 array([0., 2., 4., 6., 8.]) 

1069 

1070 The `axis` keyword can be used to specify a subset of axes of which the 

1071 gradient is calculated 

1072 

1073 >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=float), axis=0) 

1074 array([[ 2., 2., -1.], 

1075 [ 2., 2., -1.]]) 

1076 

1077 Notes 

1078 ----- 

1079 Assuming that :math:`f\\in C^{3}` (i.e., :math:`f` has at least 3 continuous 

1080 derivatives) and let :math:`h_{*}` be a non-homogeneous stepsize, we 

1081 minimize the "consistency error" :math:`\\eta_{i}` between the true gradient 

1082 and its estimate from a linear combination of the neighboring grid-points: 

1083 

1084 .. math:: 

1085 

1086 \\eta_{i} = f_{i}^{\\left(1\\right)} - 

1087 \\left[ \\alpha f\\left(x_{i}\\right) + 

1088 \\beta f\\left(x_{i} + h_{d}\\right) + 

1089 \\gamma f\\left(x_{i}-h_{s}\\right) 

1090 \\right] 

1091 

1092 By substituting :math:`f(x_{i} + h_{d})` and :math:`f(x_{i} - h_{s})` 

1093 with their Taylor series expansion, this translates into solving 

1094 the following the linear system: 

1095 

1096 .. math:: 

1097 

1098 \\left\\{ 

1099 \\begin{array}{r} 

1100 \\alpha+\\beta+\\gamma=0 \\\\ 

1101 \\beta h_{d}-\\gamma h_{s}=1 \\\\ 

1102 \\beta h_{d}^{2}+\\gamma h_{s}^{2}=0 

1103 \\end{array} 

1104 \\right. 

1105 

1106 The resulting approximation of :math:`f_{i}^{(1)}` is the following: 

1107 

1108 .. math:: 

1109 

1110 \\hat f_{i}^{(1)} = 

1111 \\frac{ 

1112 h_{s}^{2}f\\left(x_{i} + h_{d}\\right) 

1113 + \\left(h_{d}^{2} - h_{s}^{2}\\right)f\\left(x_{i}\\right) 

1114 - h_{d}^{2}f\\left(x_{i}-h_{s}\\right)} 

1115 { h_{s}h_{d}\\left(h_{d} + h_{s}\\right)} 

1116 + \\mathcal{O}\\left(\\frac{h_{d}h_{s}^{2} 

1117 + h_{s}h_{d}^{2}}{h_{d} 

1118 + h_{s}}\\right) 

1119 

1120 It is worth noting that if :math:`h_{s}=h_{d}` 

1121 (i.e., data are evenly spaced) 

1122 we find the standard second order approximation: 

1123 

1124 .. math:: 

1125 

1126 \\hat f_{i}^{(1)}= 

1127 \\frac{f\\left(x_{i+1}\\right) - f\\left(x_{i-1}\\right)}{2h} 

1128 + \\mathcal{O}\\left(h^{2}\\right) 

1129 

1130 With a similar procedure the forward/backward approximations used for 

1131 boundaries can be derived. 

1132 

1133 References 

1134 ---------- 

1135 .. [1] Quarteroni A., Sacco R., Saleri F. (2007) Numerical Mathematics 

1136 (Texts in Applied Mathematics). New York: Springer. 

1137 .. [2] Durran D. R. (1999) Numerical Methods for Wave Equations 

1138 in Geophysical Fluid Dynamics. New York: Springer. 

1139 .. [3] Fornberg B. (1988) Generation of Finite Difference Formulas on 

1140 Arbitrarily Spaced Grids, 

1141 Mathematics of Computation 51, no. 184 : 699-706. 

1142 `PDF <http://www.ams.org/journals/mcom/1988-51-184/ 

1143 S0025-5718-1988-0935077-0/S0025-5718-1988-0935077-0.pdf>`_. 

1144 """ 

1145 f = np.asanyarray(f) 

1146 N = f.ndim # number of dimensions 

1147 

1148 if axis is None: 

1149 axes = tuple(range(N)) 

1150 else: 

1151 axes = _nx.normalize_axis_tuple(axis, N) 

1152 

1153 len_axes = len(axes) 

1154 n = len(varargs) 

1155 if n == 0: 

1156 # no spacing argument - use 1 in all axes 

1157 dx = [1.0] * len_axes 

1158 elif n == 1 and np.ndim(varargs[0]) == 0: 

1159 # single scalar for all axes 

1160 dx = varargs * len_axes 

1161 elif n == len_axes: 

1162 # scalar or 1d array for each axis 

1163 dx = list(varargs) 

1164 for i, distances in enumerate(dx): 

1165 distances = np.asanyarray(distances) 

1166 if distances.ndim == 0: 

1167 continue 

1168 elif distances.ndim != 1: 

1169 raise ValueError("distances must be either scalars or 1d") 

1170 if len(distances) != f.shape[axes[i]]: 

1171 raise ValueError("when 1d, distances must match " 

1172 "the length of the corresponding dimension") 

1173 if np.issubdtype(distances.dtype, np.integer): 

1174 # Convert numpy integer types to float64 to avoid modular 

1175 # arithmetic in np.diff(distances). 

1176 distances = distances.astype(np.float64) 

1177 diffx = np.diff(distances) 

1178 # if distances are constant reduce to the scalar case 

1179 # since it brings a consistent speedup 

1180 if (diffx == diffx[0]).all(): 

1181 diffx = diffx[0] 

1182 dx[i] = diffx 

1183 else: 

1184 raise TypeError("invalid number of arguments") 

1185 

1186 if edge_order > 2: 

1187 raise ValueError("'edge_order' greater than 2 not supported") 

1188 

1189 # use central differences on interior and one-sided differences on the 

1190 # endpoints. This preserves second order-accuracy over the full domain. 

1191 

1192 outvals = [] 

1193 

1194 # create slice objects --- initially all are [:, :, ..., :] 

1195 slice1 = [slice(None)]*N 

1196 slice2 = [slice(None)]*N 

1197 slice3 = [slice(None)]*N 

1198 slice4 = [slice(None)]*N 

1199 

1200 otype = f.dtype 

1201 if otype.type is np.datetime64: 

1202 # the timedelta dtype with the same unit information 

1203 otype = np.dtype(otype.name.replace('datetime', 'timedelta')) 

1204 # view as timedelta to allow addition 

1205 f = f.view(otype) 

1206 elif otype.type is np.timedelta64: 

1207 pass 

1208 elif np.issubdtype(otype, np.inexact): 

1209 pass 

1210 else: 

1211 # All other types convert to floating point. 

1212 # First check if f is a numpy integer type; if so, convert f to float64 

1213 # to avoid modular arithmetic when computing the changes in f. 

1214 if np.issubdtype(otype, np.integer): 

1215 f = f.astype(np.float64) 

1216 otype = np.float64 

1217 

1218 for axis, ax_dx in zip(axes, dx): 

1219 if f.shape[axis] < edge_order + 1: 

1220 raise ValueError( 

1221 "Shape of array too small to calculate a numerical gradient, " 

1222 "at least (edge_order + 1) elements are required.") 

1223 # result allocation 

1224 out = np.empty_like(f, dtype=otype) 

1225 

1226 # spacing for the current axis 

1227 uniform_spacing = np.ndim(ax_dx) == 0 

1228 

1229 # Numerical differentiation: 2nd order interior 

1230 slice1[axis] = slice(1, -1) 

1231 slice2[axis] = slice(None, -2) 

1232 slice3[axis] = slice(1, -1) 

1233 slice4[axis] = slice(2, None) 

1234 

1235 if uniform_spacing: 

1236 out[tuple(slice1)] = (f[tuple(slice4)] - f[tuple(slice2)]) / (2. * ax_dx) 

1237 else: 

1238 dx1 = ax_dx[0:-1] 

1239 dx2 = ax_dx[1:] 

1240 a = -(dx2)/(dx1 * (dx1 + dx2)) 

1241 b = (dx2 - dx1) / (dx1 * dx2) 

1242 c = dx1 / (dx2 * (dx1 + dx2)) 

1243 # fix the shape for broadcasting 

1244 shape = np.ones(N, dtype=int) 

1245 shape[axis] = -1 

1246 a.shape = b.shape = c.shape = shape 

1247 # 1D equivalent -- out[1:-1] = a * f[:-2] + b * f[1:-1] + c * f[2:] 

1248 out[tuple(slice1)] = a * f[tuple(slice2)] + b * f[tuple(slice3)] + c * f[tuple(slice4)] 

1249 

1250 # Numerical differentiation: 1st order edges 

1251 if edge_order == 1: 

1252 slice1[axis] = 0 

1253 slice2[axis] = 1 

1254 slice3[axis] = 0 

1255 dx_0 = ax_dx if uniform_spacing else ax_dx[0] 

1256 # 1D equivalent -- out[0] = (f[1] - f[0]) / (x[1] - x[0]) 

1257 out[tuple(slice1)] = (f[tuple(slice2)] - f[tuple(slice3)]) / dx_0 

1258 

1259 slice1[axis] = -1 

1260 slice2[axis] = -1 

1261 slice3[axis] = -2 

1262 dx_n = ax_dx if uniform_spacing else ax_dx[-1] 

1263 # 1D equivalent -- out[-1] = (f[-1] - f[-2]) / (x[-1] - x[-2]) 

1264 out[tuple(slice1)] = (f[tuple(slice2)] - f[tuple(slice3)]) / dx_n 

1265 

1266 # Numerical differentiation: 2nd order edges 

1267 else: 

1268 slice1[axis] = 0 

1269 slice2[axis] = 0 

1270 slice3[axis] = 1 

1271 slice4[axis] = 2 

1272 if uniform_spacing: 

1273 a = -1.5 / ax_dx 

1274 b = 2. / ax_dx 

1275 c = -0.5 / ax_dx 

1276 else: 

1277 dx1 = ax_dx[0] 

1278 dx2 = ax_dx[1] 

1279 a = -(2. * dx1 + dx2)/(dx1 * (dx1 + dx2)) 

1280 b = (dx1 + dx2) / (dx1 * dx2) 

1281 c = - dx1 / (dx2 * (dx1 + dx2)) 

1282 # 1D equivalent -- out[0] = a * f[0] + b * f[1] + c * f[2] 

1283 out[tuple(slice1)] = a * f[tuple(slice2)] + b * f[tuple(slice3)] + c * f[tuple(slice4)] 

1284 

1285 slice1[axis] = -1 

1286 slice2[axis] = -3 

1287 slice3[axis] = -2 

1288 slice4[axis] = -1 

1289 if uniform_spacing: 

1290 a = 0.5 / ax_dx 

1291 b = -2. / ax_dx 

1292 c = 1.5 / ax_dx 

1293 else: 

1294 dx1 = ax_dx[-2] 

1295 dx2 = ax_dx[-1] 

1296 a = (dx2) / (dx1 * (dx1 + dx2)) 

1297 b = - (dx2 + dx1) / (dx1 * dx2) 

1298 c = (2. * dx2 + dx1) / (dx2 * (dx1 + dx2)) 

1299 # 1D equivalent -- out[-1] = a * f[-3] + b * f[-2] + c * f[-1] 

1300 out[tuple(slice1)] = a * f[tuple(slice2)] + b * f[tuple(slice3)] + c * f[tuple(slice4)] 

1301 

1302 outvals.append(out) 

1303 

1304 # reset the slice object in this dimension to ":" 

1305 slice1[axis] = slice(None) 

1306 slice2[axis] = slice(None) 

1307 slice3[axis] = slice(None) 

1308 slice4[axis] = slice(None) 

1309 

1310 if len_axes == 1: 

1311 return outvals[0] 

1312 else: 

1313 return outvals 

1314 

1315 

1316def _diff_dispatcher(a, n=None, axis=None, prepend=None, append=None): 

1317 return (a, prepend, append) 

1318 

1319 

1320@array_function_dispatch(_diff_dispatcher) 

1321def diff(a, n=1, axis=-1, prepend=np._NoValue, append=np._NoValue): 

1322 """ 

1323 Calculate the n-th discrete difference along the given axis. 

1324 

1325 The first difference is given by ``out[i] = a[i+1] - a[i]`` along 

1326 the given axis, higher differences are calculated by using `diff` 

1327 recursively. 

1328 

1329 Parameters 

1330 ---------- 

1331 a : array_like 

1332 Input array 

1333 n : int, optional 

1334 The number of times values are differenced. If zero, the input 

1335 is returned as-is. 

1336 axis : int, optional 

1337 The axis along which the difference is taken, default is the 

1338 last axis. 

1339 prepend, append : array_like, optional 

1340 Values to prepend or append to `a` along axis prior to 

1341 performing the difference. Scalar values are expanded to 

1342 arrays with length 1 in the direction of axis and the shape 

1343 of the input array in along all other axes. Otherwise the 

1344 dimension and shape must match `a` except along axis. 

1345 

1346 .. versionadded:: 1.16.0 

1347 

1348 Returns 

1349 ------- 

1350 diff : ndarray 

1351 The n-th differences. The shape of the output is the same as `a` 

1352 except along `axis` where the dimension is smaller by `n`. The 

1353 type of the output is the same as the type of the difference 

1354 between any two elements of `a`. This is the same as the type of 

1355 `a` in most cases. A notable exception is `datetime64`, which 

1356 results in a `timedelta64` output array. 

1357 

1358 See Also 

1359 -------- 

1360 gradient, ediff1d, cumsum 

1361 

1362 Notes 

1363 ----- 

1364 Type is preserved for boolean arrays, so the result will contain 

1365 `False` when consecutive elements are the same and `True` when they 

1366 differ. 

1367 

1368 For unsigned integer arrays, the results will also be unsigned. This 

1369 should not be surprising, as the result is consistent with 

1370 calculating the difference directly: 

1371 

1372 >>> u8_arr = np.array([1, 0], dtype=np.uint8) 

1373 >>> np.diff(u8_arr) 

1374 array([255], dtype=uint8) 

1375 >>> u8_arr[1,...] - u8_arr[0,...] 

1376 255 

1377 

1378 If this is not desirable, then the array should be cast to a larger 

1379 integer type first: 

1380 

1381 >>> i16_arr = u8_arr.astype(np.int16) 

1382 >>> np.diff(i16_arr) 

1383 array([-1], dtype=int16) 

1384 

1385 Examples 

1386 -------- 

1387 >>> x = np.array([1, 2, 4, 7, 0]) 

1388 >>> np.diff(x) 

1389 array([ 1, 2, 3, -7]) 

1390 >>> np.diff(x, n=2) 

1391 array([ 1, 1, -10]) 

1392 

1393 >>> x = np.array([[1, 3, 6, 10], [0, 5, 6, 8]]) 

1394 >>> np.diff(x) 

1395 array([[2, 3, 4], 

1396 [5, 1, 2]]) 

1397 >>> np.diff(x, axis=0) 

1398 array([[-1, 2, 0, -2]]) 

1399 

1400 >>> x = np.arange('1066-10-13', '1066-10-16', dtype=np.datetime64) 

1401 >>> np.diff(x) 

1402 array([1, 1], dtype='timedelta64[D]') 

1403 

1404 """ 

1405 if n == 0: 

1406 return a 

1407 if n < 0: 

1408 raise ValueError( 

1409 "order must be non-negative but got " + repr(n)) 

1410 

1411 a = asanyarray(a) 

1412 nd = a.ndim 

1413 if nd == 0: 

1414 raise ValueError("diff requires input that is at least one dimensional") 

1415 axis = normalize_axis_index(axis, nd) 

1416 

1417 combined = [] 

1418 if prepend is not np._NoValue: 

1419 prepend = np.asanyarray(prepend) 

1420 if prepend.ndim == 0: 

1421 shape = list(a.shape) 

1422 shape[axis] = 1 

1423 prepend = np.broadcast_to(prepend, tuple(shape)) 

1424 combined.append(prepend) 

1425 

1426 combined.append(a) 

1427 

1428 if append is not np._NoValue: 

1429 append = np.asanyarray(append) 

1430 if append.ndim == 0: 

1431 shape = list(a.shape) 

1432 shape[axis] = 1 

1433 append = np.broadcast_to(append, tuple(shape)) 

1434 combined.append(append) 

1435 

1436 if len(combined) > 1: 

1437 a = np.concatenate(combined, axis) 

1438 

1439 slice1 = [slice(None)] * nd 

1440 slice2 = [slice(None)] * nd 

1441 slice1[axis] = slice(1, None) 

1442 slice2[axis] = slice(None, -1) 

1443 slice1 = tuple(slice1) 

1444 slice2 = tuple(slice2) 

1445 

1446 op = not_equal if a.dtype == np.bool_ else subtract 

1447 for _ in range(n): 

1448 a = op(a[slice1], a[slice2]) 

1449 

1450 return a 

1451 

1452 

1453def _interp_dispatcher(x, xp, fp, left=None, right=None, period=None): 

1454 return (x, xp, fp) 

1455 

1456 

1457@array_function_dispatch(_interp_dispatcher) 

1458def interp(x, xp, fp, left=None, right=None, period=None): 

1459 """ 

1460 One-dimensional linear interpolation for monotonically increasing sample points. 

1461 

1462 Returns the one-dimensional piecewise linear interpolant to a function 

1463 with given discrete data points (`xp`, `fp`), evaluated at `x`. 

1464 

1465 Parameters 

1466 ---------- 

1467 x : array_like 

1468 The x-coordinates at which to evaluate the interpolated values. 

1469 

1470 xp : 1-D sequence of floats 

1471 The x-coordinates of the data points, must be increasing if argument 

1472 `period` is not specified. Otherwise, `xp` is internally sorted after 

1473 normalizing the periodic boundaries with ``xp = xp % period``. 

1474 

1475 fp : 1-D sequence of float or complex 

1476 The y-coordinates of the data points, same length as `xp`. 

1477 

1478 left : optional float or complex corresponding to fp 

1479 Value to return for `x < xp[0]`, default is `fp[0]`. 

1480 

1481 right : optional float or complex corresponding to fp 

1482 Value to return for `x > xp[-1]`, default is `fp[-1]`. 

1483 

1484 period : None or float, optional 

1485 A period for the x-coordinates. This parameter allows the proper 

1486 interpolation of angular x-coordinates. Parameters `left` and `right` 

1487 are ignored if `period` is specified. 

1488 

1489 .. versionadded:: 1.10.0 

1490 

1491 Returns 

1492 ------- 

1493 y : float or complex (corresponding to fp) or ndarray 

1494 The interpolated values, same shape as `x`. 

1495 

1496 Raises 

1497 ------ 

1498 ValueError 

1499 If `xp` and `fp` have different length 

1500 If `xp` or `fp` are not 1-D sequences 

1501 If `period == 0` 

1502 

1503 See Also 

1504 -------- 

1505 scipy.interpolate 

1506 

1507 Warnings 

1508 -------- 

1509 The x-coordinate sequence is expected to be increasing, but this is not 

1510 explicitly enforced. However, if the sequence `xp` is non-increasing, 

1511 interpolation results are meaningless. 

1512 

1513 Note that, since NaN is unsortable, `xp` also cannot contain NaNs. 

1514 

1515 A simple check for `xp` being strictly increasing is:: 

1516 

1517 np.all(np.diff(xp) > 0) 

1518 

1519 Examples 

1520 -------- 

1521 >>> xp = [1, 2, 3] 

1522 >>> fp = [3, 2, 0] 

1523 >>> np.interp(2.5, xp, fp) 

1524 1.0 

1525 >>> np.interp([0, 1, 1.5, 2.72, 3.14], xp, fp) 

1526 array([3. , 3. , 2.5 , 0.56, 0. ]) 

1527 >>> UNDEF = -99.0 

1528 >>> np.interp(3.14, xp, fp, right=UNDEF) 

1529 -99.0 

1530 

1531 Plot an interpolant to the sine function: 

1532 

1533 >>> x = np.linspace(0, 2*np.pi, 10) 

1534 >>> y = np.sin(x) 

1535 >>> xvals = np.linspace(0, 2*np.pi, 50) 

1536 >>> yinterp = np.interp(xvals, x, y) 

1537 >>> import matplotlib.pyplot as plt 

1538 >>> plt.plot(x, y, 'o') 

1539 [<matplotlib.lines.Line2D object at 0x...>] 

1540 >>> plt.plot(xvals, yinterp, '-x') 

1541 [<matplotlib.lines.Line2D object at 0x...>] 

1542 >>> plt.show() 

1543 

1544 Interpolation with periodic x-coordinates: 

1545 

1546 >>> x = [-180, -170, -185, 185, -10, -5, 0, 365] 

1547 >>> xp = [190, -190, 350, -350] 

1548 >>> fp = [5, 10, 3, 4] 

1549 >>> np.interp(x, xp, fp, period=360) 

1550 array([7.5 , 5. , 8.75, 6.25, 3. , 3.25, 3.5 , 3.75]) 

1551 

1552 Complex interpolation: 

1553 

1554 >>> x = [1.5, 4.0] 

1555 >>> xp = [2,3,5] 

1556 >>> fp = [1.0j, 0, 2+3j] 

1557 >>> np.interp(x, xp, fp) 

1558 array([0.+1.j , 1.+1.5j]) 

1559 

1560 """ 

1561 

1562 fp = np.asarray(fp) 

1563 

1564 if np.iscomplexobj(fp): 

1565 interp_func = compiled_interp_complex 

1566 input_dtype = np.complex128 

1567 else: 

1568 interp_func = compiled_interp 

1569 input_dtype = np.float64 

1570 

1571 if period is not None: 

1572 if period == 0: 

1573 raise ValueError("period must be a non-zero value") 

1574 period = abs(period) 

1575 left = None 

1576 right = None 

1577 

1578 x = np.asarray(x, dtype=np.float64) 

1579 xp = np.asarray(xp, dtype=np.float64) 

1580 fp = np.asarray(fp, dtype=input_dtype) 

1581 

1582 if xp.ndim != 1 or fp.ndim != 1: 

1583 raise ValueError("Data points must be 1-D sequences") 

1584 if xp.shape[0] != fp.shape[0]: 

1585 raise ValueError("fp and xp are not of the same length") 

1586 # normalizing periodic boundaries 

1587 x = x % period 

1588 xp = xp % period 

1589 asort_xp = np.argsort(xp) 

1590 xp = xp[asort_xp] 

1591 fp = fp[asort_xp] 

1592 xp = np.concatenate((xp[-1:]-period, xp, xp[0:1]+period)) 

1593 fp = np.concatenate((fp[-1:], fp, fp[0:1])) 

1594 

1595 return interp_func(x, xp, fp, left, right) 

1596 

1597 

1598def _angle_dispatcher(z, deg=None): 

1599 return (z,) 

1600 

1601 

1602@array_function_dispatch(_angle_dispatcher) 

1603def angle(z, deg=False): 

1604 """ 

1605 Return the angle of the complex argument. 

1606 

1607 Parameters 

1608 ---------- 

1609 z : array_like 

1610 A complex number or sequence of complex numbers. 

1611 deg : bool, optional 

1612 Return angle in degrees if True, radians if False (default). 

1613 

1614 Returns 

1615 ------- 

1616 angle : ndarray or scalar 

1617 The counterclockwise angle from the positive real axis on the complex 

1618 plane in the range ``(-pi, pi]``, with dtype as numpy.float64. 

1619 

1620 .. versionchanged:: 1.16.0 

1621 This function works on subclasses of ndarray like `ma.array`. 

1622 

1623 See Also 

1624 -------- 

1625 arctan2 

1626 absolute 

1627 

1628 Notes 

1629 ----- 

1630 Although the angle of the complex number 0 is undefined, ``numpy.angle(0)`` 

1631 returns the value 0. 

1632 

1633 Examples 

1634 -------- 

1635 >>> np.angle([1.0, 1.0j, 1+1j]) # in radians 

1636 array([ 0. , 1.57079633, 0.78539816]) # may vary 

1637 >>> np.angle(1+1j, deg=True) # in degrees 

1638 45.0 

1639 

1640 """ 

1641 z = asanyarray(z) 

1642 if issubclass(z.dtype.type, _nx.complexfloating): 

1643 zimag = z.imag 

1644 zreal = z.real 

1645 else: 

1646 zimag = 0 

1647 zreal = z 

1648 

1649 a = arctan2(zimag, zreal) 

1650 if deg: 

1651 a *= 180/pi 

1652 return a 

1653 

1654 

1655def _unwrap_dispatcher(p, discont=None, axis=None, *, period=None): 

1656 return (p,) 

1657 

1658 

1659@array_function_dispatch(_unwrap_dispatcher) 

1660def unwrap(p, discont=None, axis=-1, *, period=2*pi): 

1661 r""" 

1662 Unwrap by taking the complement of large deltas with respect to the period. 

1663 

1664 This unwraps a signal `p` by changing elements which have an absolute 

1665 difference from their predecessor of more than ``max(discont, period/2)`` 

1666 to their `period`-complementary values. 

1667 

1668 For the default case where `period` is :math:`2\pi` and `discont` is 

1669 :math:`\pi`, this unwraps a radian phase `p` such that adjacent differences 

1670 are never greater than :math:`\pi` by adding :math:`2k\pi` for some 

1671 integer :math:`k`. 

1672 

1673 Parameters 

1674 ---------- 

1675 p : array_like 

1676 Input array. 

1677 discont : float, optional 

1678 Maximum discontinuity between values, default is ``period/2``. 

1679 Values below ``period/2`` are treated as if they were ``period/2``. 

1680 To have an effect different from the default, `discont` should be 

1681 larger than ``period/2``. 

1682 axis : int, optional 

1683 Axis along which unwrap will operate, default is the last axis. 

1684 period : float, optional 

1685 Size of the range over which the input wraps. By default, it is 

1686 ``2 pi``. 

1687 

1688 .. versionadded:: 1.21.0 

1689 

1690 Returns 

1691 ------- 

1692 out : ndarray 

1693 Output array. 

1694 

1695 See Also 

1696 -------- 

1697 rad2deg, deg2rad 

1698 

1699 Notes 

1700 ----- 

1701 If the discontinuity in `p` is smaller than ``period/2``, 

1702 but larger than `discont`, no unwrapping is done because taking 

1703 the complement would only make the discontinuity larger. 

1704 

1705 Examples 

1706 -------- 

1707 >>> phase = np.linspace(0, np.pi, num=5) 

1708 >>> phase[3:] += np.pi 

1709 >>> phase 

1710 array([ 0. , 0.78539816, 1.57079633, 5.49778714, 6.28318531]) # may vary 

1711 >>> np.unwrap(phase) 

1712 array([ 0. , 0.78539816, 1.57079633, -0.78539816, 0. ]) # may vary 

1713 >>> np.unwrap([0, 1, 2, -1, 0], period=4) 

1714 array([0, 1, 2, 3, 4]) 

1715 >>> np.unwrap([ 1, 2, 3, 4, 5, 6, 1, 2, 3], period=6) 

1716 array([1, 2, 3, 4, 5, 6, 7, 8, 9]) 

1717 >>> np.unwrap([2, 3, 4, 5, 2, 3, 4, 5], period=4) 

1718 array([2, 3, 4, 5, 6, 7, 8, 9]) 

1719 >>> phase_deg = np.mod(np.linspace(0 ,720, 19), 360) - 180 

1720 >>> np.unwrap(phase_deg, period=360) 

1721 array([-180., -140., -100., -60., -20., 20., 60., 100., 140., 

1722 180., 220., 260., 300., 340., 380., 420., 460., 500., 

1723 540.]) 

1724 """ 

1725 p = asarray(p) 

1726 nd = p.ndim 

1727 dd = diff(p, axis=axis) 

1728 if discont is None: 

1729 discont = period/2 

1730 slice1 = [slice(None, None)]*nd # full slices 

1731 slice1[axis] = slice(1, None) 

1732 slice1 = tuple(slice1) 

1733 dtype = np.result_type(dd, period) 

1734 if _nx.issubdtype(dtype, _nx.integer): 

1735 interval_high, rem = divmod(period, 2) 

1736 boundary_ambiguous = rem == 0 

1737 else: 

1738 interval_high = period / 2 

1739 boundary_ambiguous = True 

1740 interval_low = -interval_high 

1741 ddmod = mod(dd - interval_low, period) + interval_low 

1742 if boundary_ambiguous: 

1743 # for `mask = (abs(dd) == period/2)`, the above line made 

1744 # `ddmod[mask] == -period/2`. correct these such that 

1745 # `ddmod[mask] == sign(dd[mask])*period/2`. 

1746 _nx.copyto(ddmod, interval_high, 

1747 where=(ddmod == interval_low) & (dd > 0)) 

1748 ph_correct = ddmod - dd 

1749 _nx.copyto(ph_correct, 0, where=abs(dd) < discont) 

1750 up = array(p, copy=True, dtype=dtype) 

1751 up[slice1] = p[slice1] + ph_correct.cumsum(axis) 

1752 return up 

1753 

1754 

1755def _sort_complex(a): 

1756 return (a,) 

1757 

1758 

1759@array_function_dispatch(_sort_complex) 

1760def sort_complex(a): 

1761 """ 

1762 Sort a complex array using the real part first, then the imaginary part. 

1763 

1764 Parameters 

1765 ---------- 

1766 a : array_like 

1767 Input array 

1768 

1769 Returns 

1770 ------- 

1771 out : complex ndarray 

1772 Always returns a sorted complex array. 

1773 

1774 Examples 

1775 -------- 

1776 >>> np.sort_complex([5, 3, 6, 2, 1]) 

1777 array([1.+0.j, 2.+0.j, 3.+0.j, 5.+0.j, 6.+0.j]) 

1778 

1779 >>> np.sort_complex([1 + 2j, 2 - 1j, 3 - 2j, 3 - 3j, 3 + 5j]) 

1780 array([1.+2.j, 2.-1.j, 3.-3.j, 3.-2.j, 3.+5.j]) 

1781 

1782 """ 

1783 b = array(a, copy=True) 

1784 b.sort() 

1785 if not issubclass(b.dtype.type, _nx.complexfloating): 

1786 if b.dtype.char in 'bhBH': 

1787 return b.astype('F') 

1788 elif b.dtype.char == 'g': 

1789 return b.astype('G') 

1790 else: 

1791 return b.astype('D') 

1792 else: 

1793 return b 

1794 

1795 

1796def _trim_zeros(filt, trim=None): 

1797 return (filt,) 

1798 

1799 

1800@array_function_dispatch(_trim_zeros) 

1801def trim_zeros(filt, trim='fb'): 

1802 """ 

1803 Trim the leading and/or trailing zeros from a 1-D array or sequence. 

1804 

1805 Parameters 

1806 ---------- 

1807 filt : 1-D array or sequence 

1808 Input array. 

1809 trim : str, optional 

1810 A string with 'f' representing trim from front and 'b' to trim from 

1811 back. Default is 'fb', trim zeros from both front and back of the 

1812 array. 

1813 

1814 Returns 

1815 ------- 

1816 trimmed : 1-D array or sequence 

1817 The result of trimming the input. The input data type is preserved. 

1818 

1819 Examples 

1820 -------- 

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

1822 >>> np.trim_zeros(a) 

1823 array([1, 2, 3, 0, 2, 1]) 

1824 

1825 >>> np.trim_zeros(a, 'b') 

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

1827 

1828 The input data type is preserved, list/tuple in means list/tuple out. 

1829 

1830 >>> np.trim_zeros([0, 1, 2, 0]) 

1831 [1, 2] 

1832 

1833 """ 

1834 

1835 first = 0 

1836 trim = trim.upper() 

1837 if 'F' in trim: 

1838 for i in filt: 

1839 if i != 0.: 

1840 break 

1841 else: 

1842 first = first + 1 

1843 last = len(filt) 

1844 if 'B' in trim: 

1845 for i in filt[::-1]: 

1846 if i != 0.: 

1847 break 

1848 else: 

1849 last = last - 1 

1850 return filt[first:last] 

1851 

1852 

1853def _extract_dispatcher(condition, arr): 

1854 return (condition, arr) 

1855 

1856 

1857@array_function_dispatch(_extract_dispatcher) 

1858def extract(condition, arr): 

1859 """ 

1860 Return the elements of an array that satisfy some condition. 

1861 

1862 This is equivalent to ``np.compress(ravel(condition), ravel(arr))``. If 

1863 `condition` is boolean ``np.extract`` is equivalent to ``arr[condition]``. 

1864 

1865 Note that `place` does the exact opposite of `extract`. 

1866 

1867 Parameters 

1868 ---------- 

1869 condition : array_like 

1870 An array whose nonzero or True entries indicate the elements of `arr` 

1871 to extract. 

1872 arr : array_like 

1873 Input array of the same size as `condition`. 

1874 

1875 Returns 

1876 ------- 

1877 extract : ndarray 

1878 Rank 1 array of values from `arr` where `condition` is True. 

1879 

1880 See Also 

1881 -------- 

1882 take, put, copyto, compress, place 

1883 

1884 Examples 

1885 -------- 

1886 >>> arr = np.arange(12).reshape((3, 4)) 

1887 >>> arr 

1888 array([[ 0, 1, 2, 3], 

1889 [ 4, 5, 6, 7], 

1890 [ 8, 9, 10, 11]]) 

1891 >>> condition = np.mod(arr, 3)==0 

1892 >>> condition 

1893 array([[ True, False, False, True], 

1894 [False, False, True, False], 

1895 [False, True, False, False]]) 

1896 >>> np.extract(condition, arr) 

1897 array([0, 3, 6, 9]) 

1898 

1899 

1900 If `condition` is boolean: 

1901 

1902 >>> arr[condition] 

1903 array([0, 3, 6, 9]) 

1904 

1905 """ 

1906 return _nx.take(ravel(arr), nonzero(ravel(condition))[0]) 

1907 

1908 

1909def _place_dispatcher(arr, mask, vals): 

1910 return (arr, mask, vals) 

1911 

1912 

1913@array_function_dispatch(_place_dispatcher) 

1914def place(arr, mask, vals): 

1915 """ 

1916 Change elements of an array based on conditional and input values. 

1917 

1918 Similar to ``np.copyto(arr, vals, where=mask)``, the difference is that 

1919 `place` uses the first N elements of `vals`, where N is the number of 

1920 True values in `mask`, while `copyto` uses the elements where `mask` 

1921 is True. 

1922 

1923 Note that `extract` does the exact opposite of `place`. 

1924 

1925 Parameters 

1926 ---------- 

1927 arr : ndarray 

1928 Array to put data into. 

1929 mask : array_like 

1930 Boolean mask array. Must have the same size as `a`. 

1931 vals : 1-D sequence 

1932 Values to put into `a`. Only the first N elements are used, where 

1933 N is the number of True values in `mask`. If `vals` is smaller 

1934 than N, it will be repeated, and if elements of `a` are to be masked, 

1935 this sequence must be non-empty. 

1936 

1937 See Also 

1938 -------- 

1939 copyto, put, take, extract 

1940 

1941 Examples 

1942 -------- 

1943 >>> arr = np.arange(6).reshape(2, 3) 

1944 >>> np.place(arr, arr>2, [44, 55]) 

1945 >>> arr 

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

1947 [44, 55, 44]]) 

1948 

1949 """ 

1950 if not isinstance(arr, np.ndarray): 

1951 raise TypeError("argument 1 must be numpy.ndarray, " 

1952 "not {name}".format(name=type(arr).__name__)) 

1953 

1954 return _insert(arr, mask, vals) 

1955 

1956 

1957def disp(mesg, device=None, linefeed=True): 

1958 """ 

1959 Display a message on a device. 

1960 

1961 Parameters 

1962 ---------- 

1963 mesg : str 

1964 Message to display. 

1965 device : object 

1966 Device to write message. If None, defaults to ``sys.stdout`` which is 

1967 very similar to ``print``. `device` needs to have ``write()`` and 

1968 ``flush()`` methods. 

1969 linefeed : bool, optional 

1970 Option whether to print a line feed or not. Defaults to True. 

1971 

1972 Raises 

1973 ------ 

1974 AttributeError 

1975 If `device` does not have a ``write()`` or ``flush()`` method. 

1976 

1977 Examples 

1978 -------- 

1979 Besides ``sys.stdout``, a file-like object can also be used as it has 

1980 both required methods: 

1981 

1982 >>> from io import StringIO 

1983 >>> buf = StringIO() 

1984 >>> np.disp(u'"Display" in a file', device=buf) 

1985 >>> buf.getvalue() 

1986 '"Display" in a file\\n' 

1987 

1988 """ 

1989 if device is None: 

1990 device = sys.stdout 

1991 if linefeed: 

1992 device.write('%s\n' % mesg) 

1993 else: 

1994 device.write('%s' % mesg) 

1995 device.flush() 

1996 return 

1997 

1998 

1999# See https://docs.scipy.org/doc/numpy/reference/c-api.generalized-ufuncs.html 

2000_DIMENSION_NAME = r'\w+' 

2001_CORE_DIMENSION_LIST = '(?:{0:}(?:,{0:})*)?'.format(_DIMENSION_NAME) 

2002_ARGUMENT = r'\({}\)'.format(_CORE_DIMENSION_LIST) 

2003_ARGUMENT_LIST = '{0:}(?:,{0:})*'.format(_ARGUMENT) 

2004_SIGNATURE = '^{0:}->{0:}$'.format(_ARGUMENT_LIST) 

2005 

2006 

2007def _parse_gufunc_signature(signature): 

2008 """ 

2009 Parse string signatures for a generalized universal function. 

2010 

2011 Arguments 

2012 --------- 

2013 signature : string 

2014 Generalized universal function signature, e.g., ``(m,n),(n,p)->(m,p)`` 

2015 for ``np.matmul``. 

2016 

2017 Returns 

2018 ------- 

2019 Tuple of input and output core dimensions parsed from the signature, each 

2020 of the form List[Tuple[str, ...]]. 

2021 """ 

2022 signature = re.sub(r'\s+', '', signature) 

2023 

2024 if not re.match(_SIGNATURE, signature): 

2025 raise ValueError( 

2026 'not a valid gufunc signature: {}'.format(signature)) 

2027 return tuple([tuple(re.findall(_DIMENSION_NAME, arg)) 

2028 for arg in re.findall(_ARGUMENT, arg_list)] 

2029 for arg_list in signature.split('->')) 

2030 

2031 

2032def _update_dim_sizes(dim_sizes, arg, core_dims): 

2033 """ 

2034 Incrementally check and update core dimension sizes for a single argument. 

2035 

2036 Arguments 

2037 --------- 

2038 dim_sizes : Dict[str, int] 

2039 Sizes of existing core dimensions. Will be updated in-place. 

2040 arg : ndarray 

2041 Argument to examine. 

2042 core_dims : Tuple[str, ...] 

2043 Core dimensions for this argument. 

2044 """ 

2045 if not core_dims: 

2046 return 

2047 

2048 num_core_dims = len(core_dims) 

2049 if arg.ndim < num_core_dims: 

2050 raise ValueError( 

2051 '%d-dimensional argument does not have enough ' 

2052 'dimensions for all core dimensions %r' 

2053 % (arg.ndim, core_dims)) 

2054 

2055 core_shape = arg.shape[-num_core_dims:] 

2056 for dim, size in zip(core_dims, core_shape): 

2057 if dim in dim_sizes: 

2058 if size != dim_sizes[dim]: 

2059 raise ValueError( 

2060 'inconsistent size for core dimension %r: %r vs %r' 

2061 % (dim, size, dim_sizes[dim])) 

2062 else: 

2063 dim_sizes[dim] = size 

2064 

2065 

2066def _parse_input_dimensions(args, input_core_dims): 

2067 """ 

2068 Parse broadcast and core dimensions for vectorize with a signature. 

2069 

2070 Arguments 

2071 --------- 

2072 args : Tuple[ndarray, ...] 

2073 Tuple of input arguments to examine. 

2074 input_core_dims : List[Tuple[str, ...]] 

2075 List of core dimensions corresponding to each input. 

2076 

2077 Returns 

2078 ------- 

2079 broadcast_shape : Tuple[int, ...] 

2080 Common shape to broadcast all non-core dimensions to. 

2081 dim_sizes : Dict[str, int] 

2082 Common sizes for named core dimensions. 

2083 """ 

2084 broadcast_args = [] 

2085 dim_sizes = {} 

2086 for arg, core_dims in zip(args, input_core_dims): 

2087 _update_dim_sizes(dim_sizes, arg, core_dims) 

2088 ndim = arg.ndim - len(core_dims) 

2089 dummy_array = np.lib.stride_tricks.as_strided(0, arg.shape[:ndim]) 

2090 broadcast_args.append(dummy_array) 

2091 broadcast_shape = np.lib.stride_tricks._broadcast_shape(*broadcast_args) 

2092 return broadcast_shape, dim_sizes 

2093 

2094 

2095def _calculate_shapes(broadcast_shape, dim_sizes, list_of_core_dims): 

2096 """Helper for calculating broadcast shapes with core dimensions.""" 

2097 return [broadcast_shape + tuple(dim_sizes[dim] for dim in core_dims) 

2098 for core_dims in list_of_core_dims] 

2099 

2100 

2101def _create_arrays(broadcast_shape, dim_sizes, list_of_core_dims, dtypes, 

2102 results=None): 

2103 """Helper for creating output arrays in vectorize.""" 

2104 shapes = _calculate_shapes(broadcast_shape, dim_sizes, list_of_core_dims) 

2105 if dtypes is None: 

2106 dtypes = [None] * len(shapes) 

2107 if results is None: 

2108 arrays = tuple(np.empty(shape=shape, dtype=dtype) 

2109 for shape, dtype in zip(shapes, dtypes)) 

2110 else: 

2111 arrays = tuple(np.empty_like(result, shape=shape, dtype=dtype) 

2112 for result, shape, dtype 

2113 in zip(results, shapes, dtypes)) 

2114 return arrays 

2115 

2116 

2117@set_module('numpy') 

2118class vectorize: 

2119 """ 

2120 vectorize(pyfunc, otypes=None, doc=None, excluded=None, cache=False, 

2121 signature=None) 

2122 

2123 Generalized function class. 

2124 

2125 Define a vectorized function which takes a nested sequence of objects or 

2126 numpy arrays as inputs and returns a single numpy array or a tuple of numpy 

2127 arrays. The vectorized function evaluates `pyfunc` over successive tuples 

2128 of the input arrays like the python map function, except it uses the 

2129 broadcasting rules of numpy. 

2130 

2131 The data type of the output of `vectorized` is determined by calling 

2132 the function with the first element of the input. This can be avoided 

2133 by specifying the `otypes` argument. 

2134 

2135 Parameters 

2136 ---------- 

2137 pyfunc : callable 

2138 A python function or method. 

2139 otypes : str or list of dtypes, optional 

2140 The output data type. It must be specified as either a string of 

2141 typecode characters or a list of data type specifiers. There should 

2142 be one data type specifier for each output. 

2143 doc : str, optional 

2144 The docstring for the function. If None, the docstring will be the 

2145 ``pyfunc.__doc__``. 

2146 excluded : set, optional 

2147 Set of strings or integers representing the positional or keyword 

2148 arguments for which the function will not be vectorized. These will be 

2149 passed directly to `pyfunc` unmodified. 

2150 

2151 .. versionadded:: 1.7.0 

2152 

2153 cache : bool, optional 

2154 If `True`, then cache the first function call that determines the number 

2155 of outputs if `otypes` is not provided. 

2156 

2157 .. versionadded:: 1.7.0 

2158 

2159 signature : string, optional 

2160 Generalized universal function signature, e.g., ``(m,n),(n)->(m)`` for 

2161 vectorized matrix-vector multiplication. If provided, ``pyfunc`` will 

2162 be called with (and expected to return) arrays with shapes given by the 

2163 size of corresponding core dimensions. By default, ``pyfunc`` is 

2164 assumed to take scalars as input and output. 

2165 

2166 .. versionadded:: 1.12.0 

2167 

2168 Returns 

2169 ------- 

2170 vectorized : callable 

2171 Vectorized function. 

2172 

2173 See Also 

2174 -------- 

2175 frompyfunc : Takes an arbitrary Python function and returns a ufunc 

2176 

2177 Notes 

2178 ----- 

2179 The `vectorize` function is provided primarily for convenience, not for 

2180 performance. The implementation is essentially a for loop. 

2181 

2182 If `otypes` is not specified, then a call to the function with the 

2183 first argument will be used to determine the number of outputs. The 

2184 results of this call will be cached if `cache` is `True` to prevent 

2185 calling the function twice. However, to implement the cache, the 

2186 original function must be wrapped which will slow down subsequent 

2187 calls, so only do this if your function is expensive. 

2188 

2189 The new keyword argument interface and `excluded` argument support 

2190 further degrades performance. 

2191 

2192 References 

2193 ---------- 

2194 .. [1] :doc:`/reference/c-api/generalized-ufuncs` 

2195 

2196 Examples 

2197 -------- 

2198 >>> def myfunc(a, b): 

2199 ... "Return a-b if a>b, otherwise return a+b" 

2200 ... if a > b: 

2201 ... return a - b 

2202 ... else: 

2203 ... return a + b 

2204 

2205 >>> vfunc = np.vectorize(myfunc) 

2206 >>> vfunc([1, 2, 3, 4], 2) 

2207 array([3, 4, 1, 2]) 

2208 

2209 The docstring is taken from the input function to `vectorize` unless it 

2210 is specified: 

2211 

2212 >>> vfunc.__doc__ 

2213 'Return a-b if a>b, otherwise return a+b' 

2214 >>> vfunc = np.vectorize(myfunc, doc='Vectorized `myfunc`') 

2215 >>> vfunc.__doc__ 

2216 'Vectorized `myfunc`' 

2217 

2218 The output type is determined by evaluating the first element of the input, 

2219 unless it is specified: 

2220 

2221 >>> out = vfunc([1, 2, 3, 4], 2) 

2222 >>> type(out[0]) 

2223 <class 'numpy.int64'> 

2224 >>> vfunc = np.vectorize(myfunc, otypes=[float]) 

2225 >>> out = vfunc([1, 2, 3, 4], 2) 

2226 >>> type(out[0]) 

2227 <class 'numpy.float64'> 

2228 

2229 The `excluded` argument can be used to prevent vectorizing over certain 

2230 arguments. This can be useful for array-like arguments of a fixed length 

2231 such as the coefficients for a polynomial as in `polyval`: 

2232 

2233 >>> def mypolyval(p, x): 

2234 ... _p = list(p) 

2235 ... res = _p.pop(0) 

2236 ... while _p: 

2237 ... res = res*x + _p.pop(0) 

2238 ... return res 

2239 >>> vpolyval = np.vectorize(mypolyval, excluded=['p']) 

2240 >>> vpolyval(p=[1, 2, 3], x=[0, 1]) 

2241 array([3, 6]) 

2242 

2243 Positional arguments may also be excluded by specifying their position: 

2244 

2245 >>> vpolyval.excluded.add(0) 

2246 >>> vpolyval([1, 2, 3], x=[0, 1]) 

2247 array([3, 6]) 

2248 

2249 The `signature` argument allows for vectorizing functions that act on 

2250 non-scalar arrays of fixed length. For example, you can use it for a 

2251 vectorized calculation of Pearson correlation coefficient and its p-value: 

2252 

2253 >>> import scipy.stats 

2254 >>> pearsonr = np.vectorize(scipy.stats.pearsonr, 

2255 ... signature='(n),(n)->(),()') 

2256 >>> pearsonr([[0, 1, 2, 3]], [[1, 2, 3, 4], [4, 3, 2, 1]]) 

2257 (array([ 1., -1.]), array([ 0., 0.])) 

2258 

2259 Or for a vectorized convolution: 

2260 

2261 >>> convolve = np.vectorize(np.convolve, signature='(n),(m)->(k)') 

2262 >>> convolve(np.eye(4), [1, 2, 1]) 

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

2264 [0., 1., 2., 1., 0., 0.], 

2265 [0., 0., 1., 2., 1., 0.], 

2266 [0., 0., 0., 1., 2., 1.]]) 

2267 

2268 """ 

2269 def __init__(self, pyfunc, otypes=None, doc=None, excluded=None, 

2270 cache=False, signature=None): 

2271 self.pyfunc = pyfunc 

2272 self.cache = cache 

2273 self.signature = signature 

2274 self._ufunc = {} # Caching to improve default performance 

2275 

2276 if doc is None: 

2277 self.__doc__ = pyfunc.__doc__ 

2278 else: 

2279 self.__doc__ = doc 

2280 

2281 if isinstance(otypes, str): 

2282 for char in otypes: 

2283 if char not in typecodes['All']: 

2284 raise ValueError("Invalid otype specified: %s" % (char,)) 

2285 elif iterable(otypes): 

2286 otypes = ''.join([_nx.dtype(x).char for x in otypes]) 

2287 elif otypes is not None: 

2288 raise ValueError("Invalid otype specification") 

2289 self.otypes = otypes 

2290 

2291 # Excluded variable support 

2292 if excluded is None: 

2293 excluded = set() 

2294 self.excluded = set(excluded) 

2295 

2296 if signature is not None: 

2297 self._in_and_out_core_dims = _parse_gufunc_signature(signature) 

2298 else: 

2299 self._in_and_out_core_dims = None 

2300 

2301 def __call__(self, *args, **kwargs): 

2302 """ 

2303 Return arrays with the results of `pyfunc` broadcast (vectorized) over 

2304 `args` and `kwargs` not in `excluded`. 

2305 """ 

2306 excluded = self.excluded 

2307 if not kwargs and not excluded: 

2308 func = self.pyfunc 

2309 vargs = args 

2310 else: 

2311 # The wrapper accepts only positional arguments: we use `names` and 

2312 # `inds` to mutate `the_args` and `kwargs` to pass to the original 

2313 # function. 

2314 nargs = len(args) 

2315 

2316 names = [_n for _n in kwargs if _n not in excluded] 

2317 inds = [_i for _i in range(nargs) if _i not in excluded] 

2318 the_args = list(args) 

2319 

2320 def func(*vargs): 

2321 for _n, _i in enumerate(inds): 

2322 the_args[_i] = vargs[_n] 

2323 kwargs.update(zip(names, vargs[len(inds):])) 

2324 return self.pyfunc(*the_args, **kwargs) 

2325 

2326 vargs = [args[_i] for _i in inds] 

2327 vargs.extend([kwargs[_n] for _n in names]) 

2328 

2329 return self._vectorize_call(func=func, args=vargs) 

2330 

2331 def _get_ufunc_and_otypes(self, func, args): 

2332 """Return (ufunc, otypes).""" 

2333 # frompyfunc will fail if args is empty 

2334 if not args: 

2335 raise ValueError('args can not be empty') 

2336 

2337 if self.otypes is not None: 

2338 otypes = self.otypes 

2339 

2340 # self._ufunc is a dictionary whose keys are the number of 

2341 # arguments (i.e. len(args)) and whose values are ufuncs created 

2342 # by frompyfunc. len(args) can be different for different calls if 

2343 # self.pyfunc has parameters with default values. We only use the 

2344 # cache when func is self.pyfunc, which occurs when the call uses 

2345 # only positional arguments and no arguments are excluded. 

2346 

2347 nin = len(args) 

2348 nout = len(self.otypes) 

2349 if func is not self.pyfunc or nin not in self._ufunc: 

2350 ufunc = frompyfunc(func, nin, nout) 

2351 else: 

2352 ufunc = None # We'll get it from self._ufunc 

2353 if func is self.pyfunc: 

2354 ufunc = self._ufunc.setdefault(nin, ufunc) 

2355 else: 

2356 # Get number of outputs and output types by calling the function on 

2357 # the first entries of args. We also cache the result to prevent 

2358 # the subsequent call when the ufunc is evaluated. 

2359 # Assumes that ufunc first evaluates the 0th elements in the input 

2360 # arrays (the input values are not checked to ensure this) 

2361 args = [asarray(arg) for arg in args] 

2362 if builtins.any(arg.size == 0 for arg in args): 

2363 raise ValueError('cannot call `vectorize` on size 0 inputs ' 

2364 'unless `otypes` is set') 

2365 

2366 inputs = [arg.flat[0] for arg in args] 

2367 outputs = func(*inputs) 

2368 

2369 # Performance note: profiling indicates that -- for simple 

2370 # functions at least -- this wrapping can almost double the 

2371 # execution time. 

2372 # Hence we make it optional. 

2373 if self.cache: 

2374 _cache = [outputs] 

2375 

2376 def _func(*vargs): 

2377 if _cache: 

2378 return _cache.pop() 

2379 else: 

2380 return func(*vargs) 

2381 else: 

2382 _func = func 

2383 

2384 if isinstance(outputs, tuple): 

2385 nout = len(outputs) 

2386 else: 

2387 nout = 1 

2388 outputs = (outputs,) 

2389 

2390 otypes = ''.join([asarray(outputs[_k]).dtype.char 

2391 for _k in range(nout)]) 

2392 

2393 # Performance note: profiling indicates that creating the ufunc is 

2394 # not a significant cost compared with wrapping so it seems not 

2395 # worth trying to cache this. 

2396 ufunc = frompyfunc(_func, len(args), nout) 

2397 

2398 return ufunc, otypes 

2399 

2400 def _vectorize_call(self, func, args): 

2401 """Vectorized call to `func` over positional `args`.""" 

2402 if self.signature is not None: 

2403 res = self._vectorize_call_with_signature(func, args) 

2404 elif not args: 

2405 res = func() 

2406 else: 

2407 ufunc, otypes = self._get_ufunc_and_otypes(func=func, args=args) 

2408 

2409 # Convert args to object arrays first 

2410 inputs = [asanyarray(a, dtype=object) for a in args] 

2411 

2412 outputs = ufunc(*inputs) 

2413 

2414 if ufunc.nout == 1: 

2415 res = asanyarray(outputs, dtype=otypes[0]) 

2416 else: 

2417 res = tuple([asanyarray(x, dtype=t) 

2418 for x, t in zip(outputs, otypes)]) 

2419 return res 

2420 

2421 def _vectorize_call_with_signature(self, func, args): 

2422 """Vectorized call over positional arguments with a signature.""" 

2423 input_core_dims, output_core_dims = self._in_and_out_core_dims 

2424 

2425 if len(args) != len(input_core_dims): 

2426 raise TypeError('wrong number of positional arguments: ' 

2427 'expected %r, got %r' 

2428 % (len(input_core_dims), len(args))) 

2429 args = tuple(asanyarray(arg) for arg in args) 

2430 

2431 broadcast_shape, dim_sizes = _parse_input_dimensions( 

2432 args, input_core_dims) 

2433 input_shapes = _calculate_shapes(broadcast_shape, dim_sizes, 

2434 input_core_dims) 

2435 args = [np.broadcast_to(arg, shape, subok=True) 

2436 for arg, shape in zip(args, input_shapes)] 

2437 

2438 outputs = None 

2439 otypes = self.otypes 

2440 nout = len(output_core_dims) 

2441 

2442 for index in np.ndindex(*broadcast_shape): 

2443 results = func(*(arg[index] for arg in args)) 

2444 

2445 n_results = len(results) if isinstance(results, tuple) else 1 

2446 

2447 if nout != n_results: 

2448 raise ValueError( 

2449 'wrong number of outputs from pyfunc: expected %r, got %r' 

2450 % (nout, n_results)) 

2451 

2452 if nout == 1: 

2453 results = (results,) 

2454 

2455 if outputs is None: 

2456 for result, core_dims in zip(results, output_core_dims): 

2457 _update_dim_sizes(dim_sizes, result, core_dims) 

2458 

2459 outputs = _create_arrays(broadcast_shape, dim_sizes, 

2460 output_core_dims, otypes, results) 

2461 

2462 for output, result in zip(outputs, results): 

2463 output[index] = result 

2464 

2465 if outputs is None: 

2466 # did not call the function even once 

2467 if otypes is None: 

2468 raise ValueError('cannot call `vectorize` on size 0 inputs ' 

2469 'unless `otypes` is set') 

2470 if builtins.any(dim not in dim_sizes 

2471 for dims in output_core_dims 

2472 for dim in dims): 

2473 raise ValueError('cannot call `vectorize` with a signature ' 

2474 'including new output dimensions on size 0 ' 

2475 'inputs') 

2476 outputs = _create_arrays(broadcast_shape, dim_sizes, 

2477 output_core_dims, otypes) 

2478 

2479 return outputs[0] if nout == 1 else outputs 

2480 

2481 

2482def _cov_dispatcher(m, y=None, rowvar=None, bias=None, ddof=None, 

2483 fweights=None, aweights=None, *, dtype=None): 

2484 return (m, y, fweights, aweights) 

2485 

2486 

2487@array_function_dispatch(_cov_dispatcher) 

2488def cov(m, y=None, rowvar=True, bias=False, ddof=None, fweights=None, 

2489 aweights=None, *, dtype=None): 

2490 """ 

2491 Estimate a covariance matrix, given data and weights. 

2492 

2493 Covariance indicates the level to which two variables vary together. 

2494 If we examine N-dimensional samples, :math:`X = [x_1, x_2, ... x_N]^T`, 

2495 then the covariance matrix element :math:`C_{ij}` is the covariance of 

2496 :math:`x_i` and :math:`x_j`. The element :math:`C_{ii}` is the variance 

2497 of :math:`x_i`. 

2498 

2499 See the notes for an outline of the algorithm. 

2500 

2501 Parameters 

2502 ---------- 

2503 m : array_like 

2504 A 1-D or 2-D array containing multiple variables and observations. 

2505 Each row of `m` represents a variable, and each column a single 

2506 observation of all those variables. Also see `rowvar` below. 

2507 y : array_like, optional 

2508 An additional set of variables and observations. `y` has the same form 

2509 as that of `m`. 

2510 rowvar : bool, optional 

2511 If `rowvar` is True (default), then each row represents a 

2512 variable, with observations in the columns. Otherwise, the relationship 

2513 is transposed: each column represents a variable, while the rows 

2514 contain observations. 

2515 bias : bool, optional 

2516 Default normalization (False) is by ``(N - 1)``, where ``N`` is the 

2517 number of observations given (unbiased estimate). If `bias` is True, 

2518 then normalization is by ``N``. These values can be overridden by using 

2519 the keyword ``ddof`` in numpy versions >= 1.5. 

2520 ddof : int, optional 

2521 If not ``None`` the default value implied by `bias` is overridden. 

2522 Note that ``ddof=1`` will return the unbiased estimate, even if both 

2523 `fweights` and `aweights` are specified, and ``ddof=0`` will return 

2524 the simple average. See the notes for the details. The default value 

2525 is ``None``. 

2526 

2527 .. versionadded:: 1.5 

2528 fweights : array_like, int, optional 

2529 1-D array of integer frequency weights; the number of times each 

2530 observation vector should be repeated. 

2531 

2532 .. versionadded:: 1.10 

2533 aweights : array_like, optional 

2534 1-D array of observation vector weights. These relative weights are 

2535 typically large for observations considered "important" and smaller for 

2536 observations considered less "important". If ``ddof=0`` the array of 

2537 weights can be used to assign probabilities to observation vectors. 

2538 

2539 .. versionadded:: 1.10 

2540 dtype : data-type, optional 

2541 Data-type of the result. By default, the return data-type will have 

2542 at least `numpy.float64` precision. 

2543 

2544 .. versionadded:: 1.20 

2545 

2546 Returns 

2547 ------- 

2548 out : ndarray 

2549 The covariance matrix of the variables. 

2550 

2551 See Also 

2552 -------- 

2553 corrcoef : Normalized covariance matrix 

2554 

2555 Notes 

2556 ----- 

2557 Assume that the observations are in the columns of the observation 

2558 array `m` and let ``f = fweights`` and ``a = aweights`` for brevity. The 

2559 steps to compute the weighted covariance are as follows:: 

2560 

2561 >>> m = np.arange(10, dtype=np.float64) 

2562 >>> f = np.arange(10) * 2 

2563 >>> a = np.arange(10) ** 2. 

2564 >>> ddof = 1 

2565 >>> w = f * a 

2566 >>> v1 = np.sum(w) 

2567 >>> v2 = np.sum(w * a) 

2568 >>> m -= np.sum(m * w, axis=None, keepdims=True) / v1 

2569 >>> cov = np.dot(m * w, m.T) * v1 / (v1**2 - ddof * v2) 

2570 

2571 Note that when ``a == 1``, the normalization factor 

2572 ``v1 / (v1**2 - ddof * v2)`` goes over to ``1 / (np.sum(f) - ddof)`` 

2573 as it should. 

2574 

2575 Examples 

2576 -------- 

2577 Consider two variables, :math:`x_0` and :math:`x_1`, which 

2578 correlate perfectly, but in opposite directions: 

2579 

2580 >>> x = np.array([[0, 2], [1, 1], [2, 0]]).T 

2581 >>> x 

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

2583 [2, 1, 0]]) 

2584 

2585 Note how :math:`x_0` increases while :math:`x_1` decreases. The covariance 

2586 matrix shows this clearly: 

2587 

2588 >>> np.cov(x) 

2589 array([[ 1., -1.], 

2590 [-1., 1.]]) 

2591 

2592 Note that element :math:`C_{0,1}`, which shows the correlation between 

2593 :math:`x_0` and :math:`x_1`, is negative. 

2594 

2595 Further, note how `x` and `y` are combined: 

2596 

2597 >>> x = [-2.1, -1, 4.3] 

2598 >>> y = [3, 1.1, 0.12] 

2599 >>> X = np.stack((x, y), axis=0) 

2600 >>> np.cov(X) 

2601 array([[11.71 , -4.286 ], # may vary 

2602 [-4.286 , 2.144133]]) 

2603 >>> np.cov(x, y) 

2604 array([[11.71 , -4.286 ], # may vary 

2605 [-4.286 , 2.144133]]) 

2606 >>> np.cov(x) 

2607 array(11.71) 

2608 

2609 """ 

2610 # Check inputs 

2611 if ddof is not None and ddof != int(ddof): 

2612 raise ValueError( 

2613 "ddof must be integer") 

2614 

2615 # Handles complex arrays too 

2616 m = np.asarray(m) 

2617 if m.ndim > 2: 

2618 raise ValueError("m has more than 2 dimensions") 

2619 

2620 if y is not None: 

2621 y = np.asarray(y) 

2622 if y.ndim > 2: 

2623 raise ValueError("y has more than 2 dimensions") 

2624 

2625 if dtype is None: 

2626 if y is None: 

2627 dtype = np.result_type(m, np.float64) 

2628 else: 

2629 dtype = np.result_type(m, y, np.float64) 

2630 

2631 X = array(m, ndmin=2, dtype=dtype) 

2632 if not rowvar and X.shape[0] != 1: 

2633 X = X.T 

2634 if X.shape[0] == 0: 

2635 return np.array([]).reshape(0, 0) 

2636 if y is not None: 

2637 y = array(y, copy=False, ndmin=2, dtype=dtype) 

2638 if not rowvar and y.shape[0] != 1: 

2639 y = y.T 

2640 X = np.concatenate((X, y), axis=0) 

2641 

2642 if ddof is None: 

2643 if bias == 0: 

2644 ddof = 1 

2645 else: 

2646 ddof = 0 

2647 

2648 # Get the product of frequencies and weights 

2649 w = None 

2650 if fweights is not None: 

2651 fweights = np.asarray(fweights, dtype=float) 

2652 if not np.all(fweights == np.around(fweights)): 

2653 raise TypeError( 

2654 "fweights must be integer") 

2655 if fweights.ndim > 1: 

2656 raise RuntimeError( 

2657 "cannot handle multidimensional fweights") 

2658 if fweights.shape[0] != X.shape[1]: 

2659 raise RuntimeError( 

2660 "incompatible numbers of samples and fweights") 

2661 if any(fweights < 0): 

2662 raise ValueError( 

2663 "fweights cannot be negative") 

2664 w = fweights 

2665 if aweights is not None: 

2666 aweights = np.asarray(aweights, dtype=float) 

2667 if aweights.ndim > 1: 

2668 raise RuntimeError( 

2669 "cannot handle multidimensional aweights") 

2670 if aweights.shape[0] != X.shape[1]: 

2671 raise RuntimeError( 

2672 "incompatible numbers of samples and aweights") 

2673 if any(aweights < 0): 

2674 raise ValueError( 

2675 "aweights cannot be negative") 

2676 if w is None: 

2677 w = aweights 

2678 else: 

2679 w *= aweights 

2680 

2681 avg, w_sum = average(X, axis=1, weights=w, returned=True) 

2682 w_sum = w_sum[0] 

2683 

2684 # Determine the normalization 

2685 if w is None: 

2686 fact = X.shape[1] - ddof 

2687 elif ddof == 0: 

2688 fact = w_sum 

2689 elif aweights is None: 

2690 fact = w_sum - ddof 

2691 else: 

2692 fact = w_sum - ddof*sum(w*aweights)/w_sum 

2693 

2694 if fact <= 0: 

2695 warnings.warn("Degrees of freedom <= 0 for slice", 

2696 RuntimeWarning, stacklevel=3) 

2697 fact = 0.0 

2698 

2699 X -= avg[:, None] 

2700 if w is None: 

2701 X_T = X.T 

2702 else: 

2703 X_T = (X*w).T 

2704 c = dot(X, X_T.conj()) 

2705 c *= np.true_divide(1, fact) 

2706 return c.squeeze() 

2707 

2708 

2709def _corrcoef_dispatcher(x, y=None, rowvar=None, bias=None, ddof=None, *, 

2710 dtype=None): 

2711 return (x, y) 

2712 

2713 

2714@array_function_dispatch(_corrcoef_dispatcher) 

2715def corrcoef(x, y=None, rowvar=True, bias=np._NoValue, ddof=np._NoValue, *, 

2716 dtype=None): 

2717 """ 

2718 Return Pearson product-moment correlation coefficients. 

2719 

2720 Please refer to the documentation for `cov` for more detail. The 

2721 relationship between the correlation coefficient matrix, `R`, and the 

2722 covariance matrix, `C`, is 

2723 

2724 .. math:: R_{ij} = \\frac{ C_{ij} } { \\sqrt{ C_{ii} C_{jj} } } 

2725 

2726 The values of `R` are between -1 and 1, inclusive. 

2727 

2728 Parameters 

2729 ---------- 

2730 x : array_like 

2731 A 1-D or 2-D array containing multiple variables and observations. 

2732 Each row of `x` represents a variable, and each column a single 

2733 observation of all those variables. Also see `rowvar` below. 

2734 y : array_like, optional 

2735 An additional set of variables and observations. `y` has the same 

2736 shape as `x`. 

2737 rowvar : bool, optional 

2738 If `rowvar` is True (default), then each row represents a 

2739 variable, with observations in the columns. Otherwise, the relationship 

2740 is transposed: each column represents a variable, while the rows 

2741 contain observations. 

2742 bias : _NoValue, optional 

2743 Has no effect, do not use. 

2744 

2745 .. deprecated:: 1.10.0 

2746 ddof : _NoValue, optional 

2747 Has no effect, do not use. 

2748 

2749 .. deprecated:: 1.10.0 

2750 dtype : data-type, optional 

2751 Data-type of the result. By default, the return data-type will have 

2752 at least `numpy.float64` precision. 

2753 

2754 .. versionadded:: 1.20 

2755 

2756 Returns 

2757 ------- 

2758 R : ndarray 

2759 The correlation coefficient matrix of the variables. 

2760 

2761 See Also 

2762 -------- 

2763 cov : Covariance matrix 

2764 

2765 Notes 

2766 ----- 

2767 Due to floating point rounding the resulting array may not be Hermitian, 

2768 the diagonal elements may not be 1, and the elements may not satisfy the 

2769 inequality abs(a) <= 1. The real and imaginary parts are clipped to the 

2770 interval [-1, 1] in an attempt to improve on that situation but is not 

2771 much help in the complex case. 

2772 

2773 This function accepts but discards arguments `bias` and `ddof`. This is 

2774 for backwards compatibility with previous versions of this function. These 

2775 arguments had no effect on the return values of the function and can be 

2776 safely ignored in this and previous versions of numpy. 

2777 

2778 Examples 

2779 -------- 

2780 In this example we generate two random arrays, ``xarr`` and ``yarr``, and 

2781 compute the row-wise and column-wise Pearson correlation coefficients, 

2782 ``R``. Since ``rowvar`` is true by default, we first find the row-wise 

2783 Pearson correlation coefficients between the variables of ``xarr``. 

2784 

2785 >>> import numpy as np 

2786 >>> rng = np.random.default_rng(seed=42) 

2787 >>> xarr = rng.random((3, 3)) 

2788 >>> xarr 

2789 array([[0.77395605, 0.43887844, 0.85859792], 

2790 [0.69736803, 0.09417735, 0.97562235], 

2791 [0.7611397 , 0.78606431, 0.12811363]]) 

2792 >>> R1 = np.corrcoef(xarr) 

2793 >>> R1 

2794 array([[ 1. , 0.99256089, -0.68080986], 

2795 [ 0.99256089, 1. , -0.76492172], 

2796 [-0.68080986, -0.76492172, 1. ]]) 

2797 

2798 If we add another set of variables and observations ``yarr``, we can 

2799 compute the row-wise Pearson correlation coefficients between the 

2800 variables in ``xarr`` and ``yarr``. 

2801 

2802 >>> yarr = rng.random((3, 3)) 

2803 >>> yarr 

2804 array([[0.45038594, 0.37079802, 0.92676499], 

2805 [0.64386512, 0.82276161, 0.4434142 ], 

2806 [0.22723872, 0.55458479, 0.06381726]]) 

2807 >>> R2 = np.corrcoef(xarr, yarr) 

2808 >>> R2 

2809 array([[ 1. , 0.99256089, -0.68080986, 0.75008178, -0.934284 , 

2810 -0.99004057], 

2811 [ 0.99256089, 1. , -0.76492172, 0.82502011, -0.97074098, 

2812 -0.99981569], 

2813 [-0.68080986, -0.76492172, 1. , -0.99507202, 0.89721355, 

2814 0.77714685], 

2815 [ 0.75008178, 0.82502011, -0.99507202, 1. , -0.93657855, 

2816 -0.83571711], 

2817 [-0.934284 , -0.97074098, 0.89721355, -0.93657855, 1. , 

2818 0.97517215], 

2819 [-0.99004057, -0.99981569, 0.77714685, -0.83571711, 0.97517215, 

2820 1. ]]) 

2821 

2822 Finally if we use the option ``rowvar=False``, the columns are now 

2823 being treated as the variables and we will find the column-wise Pearson 

2824 correlation coefficients between variables in ``xarr`` and ``yarr``. 

2825 

2826 >>> R3 = np.corrcoef(xarr, yarr, rowvar=False) 

2827 >>> R3 

2828 array([[ 1. , 0.77598074, -0.47458546, -0.75078643, -0.9665554 , 

2829 0.22423734], 

2830 [ 0.77598074, 1. , -0.92346708, -0.99923895, -0.58826587, 

2831 -0.44069024], 

2832 [-0.47458546, -0.92346708, 1. , 0.93773029, 0.23297648, 

2833 0.75137473], 

2834 [-0.75078643, -0.99923895, 0.93773029, 1. , 0.55627469, 

2835 0.47536961], 

2836 [-0.9665554 , -0.58826587, 0.23297648, 0.55627469, 1. , 

2837 -0.46666491], 

2838 [ 0.22423734, -0.44069024, 0.75137473, 0.47536961, -0.46666491, 

2839 1. ]]) 

2840 

2841 """ 

2842 if bias is not np._NoValue or ddof is not np._NoValue: 

2843 # 2015-03-15, 1.10 

2844 warnings.warn('bias and ddof have no effect and are deprecated', 

2845 DeprecationWarning, stacklevel=3) 

2846 c = cov(x, y, rowvar, dtype=dtype) 

2847 try: 

2848 d = diag(c) 

2849 except ValueError: 

2850 # scalar covariance 

2851 # nan if incorrect value (nan, inf, 0), 1 otherwise 

2852 return c / c 

2853 stddev = sqrt(d.real) 

2854 c /= stddev[:, None] 

2855 c /= stddev[None, :] 

2856 

2857 # Clip real and imaginary parts to [-1, 1]. This does not guarantee 

2858 # abs(a[i,j]) <= 1 for complex arrays, but is the best we can do without 

2859 # excessive work. 

2860 np.clip(c.real, -1, 1, out=c.real) 

2861 if np.iscomplexobj(c): 

2862 np.clip(c.imag, -1, 1, out=c.imag) 

2863 

2864 return c 

2865 

2866 

2867@set_module('numpy') 

2868def blackman(M): 

2869 """ 

2870 Return the Blackman window. 

2871 

2872 The Blackman window is a taper formed by using the first three 

2873 terms of a summation of cosines. It was designed to have close to the 

2874 minimal leakage possible. It is close to optimal, only slightly worse 

2875 than a Kaiser window. 

2876 

2877 Parameters 

2878 ---------- 

2879 M : int 

2880 Number of points in the output window. If zero or less, an empty 

2881 array is returned. 

2882 

2883 Returns 

2884 ------- 

2885 out : ndarray 

2886 The window, with the maximum value normalized to one (the value one 

2887 appears only if the number of samples is odd). 

2888 

2889 See Also 

2890 -------- 

2891 bartlett, hamming, hanning, kaiser 

2892 

2893 Notes 

2894 ----- 

2895 The Blackman window is defined as 

2896 

2897 .. math:: w(n) = 0.42 - 0.5 \\cos(2\\pi n/M) + 0.08 \\cos(4\\pi n/M) 

2898 

2899 Most references to the Blackman window come from the signal processing 

2900 literature, where it is used as one of many windowing functions for 

2901 smoothing values. It is also known as an apodization (which means 

2902 "removing the foot", i.e. smoothing discontinuities at the beginning 

2903 and end of the sampled signal) or tapering function. It is known as a 

2904 "near optimal" tapering function, almost as good (by some measures) 

2905 as the kaiser window. 

2906 

2907 References 

2908 ---------- 

2909 Blackman, R.B. and Tukey, J.W., (1958) The measurement of power spectra, 

2910 Dover Publications, New York. 

2911 

2912 Oppenheim, A.V., and R.W. Schafer. Discrete-Time Signal Processing. 

2913 Upper Saddle River, NJ: Prentice-Hall, 1999, pp. 468-471. 

2914 

2915 Examples 

2916 -------- 

2917 >>> import matplotlib.pyplot as plt 

2918 >>> np.blackman(12) 

2919 array([-1.38777878e-17, 3.26064346e-02, 1.59903635e-01, # may vary 

2920 4.14397981e-01, 7.36045180e-01, 9.67046769e-01, 

2921 9.67046769e-01, 7.36045180e-01, 4.14397981e-01, 

2922 1.59903635e-01, 3.26064346e-02, -1.38777878e-17]) 

2923 

2924 Plot the window and the frequency response: 

2925 

2926 >>> from numpy.fft import fft, fftshift 

2927 >>> window = np.blackman(51) 

2928 >>> plt.plot(window) 

2929 [<matplotlib.lines.Line2D object at 0x...>] 

2930 >>> plt.title("Blackman window") 

2931 Text(0.5, 1.0, 'Blackman window') 

2932 >>> plt.ylabel("Amplitude") 

2933 Text(0, 0.5, 'Amplitude') 

2934 >>> plt.xlabel("Sample") 

2935 Text(0.5, 0, 'Sample') 

2936 >>> plt.show() 

2937 

2938 >>> plt.figure() 

2939 <Figure size 640x480 with 0 Axes> 

2940 >>> A = fft(window, 2048) / 25.5 

2941 >>> mag = np.abs(fftshift(A)) 

2942 >>> freq = np.linspace(-0.5, 0.5, len(A)) 

2943 >>> with np.errstate(divide='ignore', invalid='ignore'): 

2944 ... response = 20 * np.log10(mag) 

2945 ... 

2946 >>> response = np.clip(response, -100, 100) 

2947 >>> plt.plot(freq, response) 

2948 [<matplotlib.lines.Line2D object at 0x...>] 

2949 >>> plt.title("Frequency response of Blackman window") 

2950 Text(0.5, 1.0, 'Frequency response of Blackman window') 

2951 >>> plt.ylabel("Magnitude [dB]") 

2952 Text(0, 0.5, 'Magnitude [dB]') 

2953 >>> plt.xlabel("Normalized frequency [cycles per sample]") 

2954 Text(0.5, 0, 'Normalized frequency [cycles per sample]') 

2955 >>> _ = plt.axis('tight') 

2956 >>> plt.show() 

2957 

2958 """ 

2959 if M < 1: 

2960 return array([], dtype=np.result_type(M, 0.0)) 

2961 if M == 1: 

2962 return ones(1, dtype=np.result_type(M, 0.0)) 

2963 n = arange(1-M, M, 2) 

2964 return 0.42 + 0.5*cos(pi*n/(M-1)) + 0.08*cos(2.0*pi*n/(M-1)) 

2965 

2966 

2967@set_module('numpy') 

2968def bartlett(M): 

2969 """ 

2970 Return the Bartlett window. 

2971 

2972 The Bartlett window is very similar to a triangular window, except 

2973 that the end points are at zero. It is often used in signal 

2974 processing for tapering a signal, without generating too much 

2975 ripple in the frequency domain. 

2976 

2977 Parameters 

2978 ---------- 

2979 M : int 

2980 Number of points in the output window. If zero or less, an 

2981 empty array is returned. 

2982 

2983 Returns 

2984 ------- 

2985 out : array 

2986 The triangular window, with the maximum value normalized to one 

2987 (the value one appears only if the number of samples is odd), with 

2988 the first and last samples equal to zero. 

2989 

2990 See Also 

2991 -------- 

2992 blackman, hamming, hanning, kaiser 

2993 

2994 Notes 

2995 ----- 

2996 The Bartlett window is defined as 

2997 

2998 .. math:: w(n) = \\frac{2}{M-1} \\left( 

2999 \\frac{M-1}{2} - \\left|n - \\frac{M-1}{2}\\right| 

3000 \\right) 

3001 

3002 Most references to the Bartlett window come from the signal processing 

3003 literature, where it is used as one of many windowing functions for 

3004 smoothing values. Note that convolution with this window produces linear 

3005 interpolation. It is also known as an apodization (which means "removing 

3006 the foot", i.e. smoothing discontinuities at the beginning and end of the 

3007 sampled signal) or tapering function. The Fourier transform of the 

3008 Bartlett window is the product of two sinc functions. Note the excellent 

3009 discussion in Kanasewich [2]_. 

3010 

3011 References 

3012 ---------- 

3013 .. [1] M.S. Bartlett, "Periodogram Analysis and Continuous Spectra", 

3014 Biometrika 37, 1-16, 1950. 

3015 .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", 

3016 The University of Alberta Press, 1975, pp. 109-110. 

3017 .. [3] A.V. Oppenheim and R.W. Schafer, "Discrete-Time Signal 

3018 Processing", Prentice-Hall, 1999, pp. 468-471. 

3019 .. [4] Wikipedia, "Window function", 

3020 https://en.wikipedia.org/wiki/Window_function 

3021 .. [5] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling, 

3022 "Numerical Recipes", Cambridge University Press, 1986, page 429. 

3023 

3024 Examples 

3025 -------- 

3026 >>> import matplotlib.pyplot as plt 

3027 >>> np.bartlett(12) 

3028 array([ 0. , 0.18181818, 0.36363636, 0.54545455, 0.72727273, # may vary 

3029 0.90909091, 0.90909091, 0.72727273, 0.54545455, 0.36363636, 

3030 0.18181818, 0. ]) 

3031 

3032 Plot the window and its frequency response (requires SciPy and matplotlib): 

3033 

3034 >>> from numpy.fft import fft, fftshift 

3035 >>> window = np.bartlett(51) 

3036 >>> plt.plot(window) 

3037 [<matplotlib.lines.Line2D object at 0x...>] 

3038 >>> plt.title("Bartlett window") 

3039 Text(0.5, 1.0, 'Bartlett window') 

3040 >>> plt.ylabel("Amplitude") 

3041 Text(0, 0.5, 'Amplitude') 

3042 >>> plt.xlabel("Sample") 

3043 Text(0.5, 0, 'Sample') 

3044 >>> plt.show() 

3045 

3046 >>> plt.figure() 

3047 <Figure size 640x480 with 0 Axes> 

3048 >>> A = fft(window, 2048) / 25.5 

3049 >>> mag = np.abs(fftshift(A)) 

3050 >>> freq = np.linspace(-0.5, 0.5, len(A)) 

3051 >>> with np.errstate(divide='ignore', invalid='ignore'): 

3052 ... response = 20 * np.log10(mag) 

3053 ... 

3054 >>> response = np.clip(response, -100, 100) 

3055 >>> plt.plot(freq, response) 

3056 [<matplotlib.lines.Line2D object at 0x...>] 

3057 >>> plt.title("Frequency response of Bartlett window") 

3058 Text(0.5, 1.0, 'Frequency response of Bartlett window') 

3059 >>> plt.ylabel("Magnitude [dB]") 

3060 Text(0, 0.5, 'Magnitude [dB]') 

3061 >>> plt.xlabel("Normalized frequency [cycles per sample]") 

3062 Text(0.5, 0, 'Normalized frequency [cycles per sample]') 

3063 >>> _ = plt.axis('tight') 

3064 >>> plt.show() 

3065 

3066 """ 

3067 if M < 1: 

3068 return array([], dtype=np.result_type(M, 0.0)) 

3069 if M == 1: 

3070 return ones(1, dtype=np.result_type(M, 0.0)) 

3071 n = arange(1-M, M, 2) 

3072 return where(less_equal(n, 0), 1 + n/(M-1), 1 - n/(M-1)) 

3073 

3074 

3075@set_module('numpy') 

3076def hanning(M): 

3077 """ 

3078 Return the Hanning window. 

3079 

3080 The Hanning window is a taper formed by using a weighted cosine. 

3081 

3082 Parameters 

3083 ---------- 

3084 M : int 

3085 Number of points in the output window. If zero or less, an 

3086 empty array is returned. 

3087 

3088 Returns 

3089 ------- 

3090 out : ndarray, shape(M,) 

3091 The window, with the maximum value normalized to one (the value 

3092 one appears only if `M` is odd). 

3093 

3094 See Also 

3095 -------- 

3096 bartlett, blackman, hamming, kaiser 

3097 

3098 Notes 

3099 ----- 

3100 The Hanning window is defined as 

3101 

3102 .. math:: w(n) = 0.5 - 0.5\\cos\\left(\\frac{2\\pi{n}}{M-1}\\right) 

3103 \\qquad 0 \\leq n \\leq M-1 

3104 

3105 The Hanning was named for Julius von Hann, an Austrian meteorologist. 

3106 It is also known as the Cosine Bell. Some authors prefer that it be 

3107 called a Hann window, to help avoid confusion with the very similar 

3108 Hamming window. 

3109 

3110 Most references to the Hanning window come from the signal processing 

3111 literature, where it is used as one of many windowing functions for 

3112 smoothing values. It is also known as an apodization (which means 

3113 "removing the foot", i.e. smoothing discontinuities at the beginning 

3114 and end of the sampled signal) or tapering function. 

3115 

3116 References 

3117 ---------- 

3118 .. [1] Blackman, R.B. and Tukey, J.W., (1958) The measurement of power 

3119 spectra, Dover Publications, New York. 

3120 .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", 

3121 The University of Alberta Press, 1975, pp. 106-108. 

3122 .. [3] Wikipedia, "Window function", 

3123 https://en.wikipedia.org/wiki/Window_function 

3124 .. [4] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling, 

3125 "Numerical Recipes", Cambridge University Press, 1986, page 425. 

3126 

3127 Examples 

3128 -------- 

3129 >>> np.hanning(12) 

3130 array([0. , 0.07937323, 0.29229249, 0.57115742, 0.82743037, 

3131 0.97974649, 0.97974649, 0.82743037, 0.57115742, 0.29229249, 

3132 0.07937323, 0. ]) 

3133 

3134 Plot the window and its frequency response: 

3135 

3136 >>> import matplotlib.pyplot as plt 

3137 >>> from numpy.fft import fft, fftshift 

3138 >>> window = np.hanning(51) 

3139 >>> plt.plot(window) 

3140 [<matplotlib.lines.Line2D object at 0x...>] 

3141 >>> plt.title("Hann window") 

3142 Text(0.5, 1.0, 'Hann window') 

3143 >>> plt.ylabel("Amplitude") 

3144 Text(0, 0.5, 'Amplitude') 

3145 >>> plt.xlabel("Sample") 

3146 Text(0.5, 0, 'Sample') 

3147 >>> plt.show() 

3148 

3149 >>> plt.figure() 

3150 <Figure size 640x480 with 0 Axes> 

3151 >>> A = fft(window, 2048) / 25.5 

3152 >>> mag = np.abs(fftshift(A)) 

3153 >>> freq = np.linspace(-0.5, 0.5, len(A)) 

3154 >>> with np.errstate(divide='ignore', invalid='ignore'): 

3155 ... response = 20 * np.log10(mag) 

3156 ... 

3157 >>> response = np.clip(response, -100, 100) 

3158 >>> plt.plot(freq, response) 

3159 [<matplotlib.lines.Line2D object at 0x...>] 

3160 >>> plt.title("Frequency response of the Hann window") 

3161 Text(0.5, 1.0, 'Frequency response of the Hann window') 

3162 >>> plt.ylabel("Magnitude [dB]") 

3163 Text(0, 0.5, 'Magnitude [dB]') 

3164 >>> plt.xlabel("Normalized frequency [cycles per sample]") 

3165 Text(0.5, 0, 'Normalized frequency [cycles per sample]') 

3166 >>> plt.axis('tight') 

3167 ... 

3168 >>> plt.show() 

3169 

3170 """ 

3171 if M < 1: 

3172 return array([], dtype=np.result_type(M, 0.0)) 

3173 if M == 1: 

3174 return ones(1, dtype=np.result_type(M, 0.0)) 

3175 n = arange(1-M, M, 2) 

3176 return 0.5 + 0.5*cos(pi*n/(M-1)) 

3177 

3178 

3179@set_module('numpy') 

3180def hamming(M): 

3181 """ 

3182 Return the Hamming window. 

3183 

3184 The Hamming window is a taper formed by using a weighted cosine. 

3185 

3186 Parameters 

3187 ---------- 

3188 M : int 

3189 Number of points in the output window. If zero or less, an 

3190 empty array is returned. 

3191 

3192 Returns 

3193 ------- 

3194 out : ndarray 

3195 The window, with the maximum value normalized to one (the value 

3196 one appears only if the number of samples is odd). 

3197 

3198 See Also 

3199 -------- 

3200 bartlett, blackman, hanning, kaiser 

3201 

3202 Notes 

3203 ----- 

3204 The Hamming window is defined as 

3205 

3206 .. math:: w(n) = 0.54 - 0.46\\cos\\left(\\frac{2\\pi{n}}{M-1}\\right) 

3207 \\qquad 0 \\leq n \\leq M-1 

3208 

3209 The Hamming was named for R. W. Hamming, an associate of J. W. Tukey 

3210 and is described in Blackman and Tukey. It was recommended for 

3211 smoothing the truncated autocovariance function in the time domain. 

3212 Most references to the Hamming window come from the signal processing 

3213 literature, where it is used as one of many windowing functions for 

3214 smoothing values. It is also known as an apodization (which means 

3215 "removing the foot", i.e. smoothing discontinuities at the beginning 

3216 and end of the sampled signal) or tapering function. 

3217 

3218 References 

3219 ---------- 

3220 .. [1] Blackman, R.B. and Tukey, J.W., (1958) The measurement of power 

3221 spectra, Dover Publications, New York. 

3222 .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", The 

3223 University of Alberta Press, 1975, pp. 109-110. 

3224 .. [3] Wikipedia, "Window function", 

3225 https://en.wikipedia.org/wiki/Window_function 

3226 .. [4] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling, 

3227 "Numerical Recipes", Cambridge University Press, 1986, page 425. 

3228 

3229 Examples 

3230 -------- 

3231 >>> np.hamming(12) 

3232 array([ 0.08 , 0.15302337, 0.34890909, 0.60546483, 0.84123594, # may vary 

3233 0.98136677, 0.98136677, 0.84123594, 0.60546483, 0.34890909, 

3234 0.15302337, 0.08 ]) 

3235 

3236 Plot the window and the frequency response: 

3237 

3238 >>> import matplotlib.pyplot as plt 

3239 >>> from numpy.fft import fft, fftshift 

3240 >>> window = np.hamming(51) 

3241 >>> plt.plot(window) 

3242 [<matplotlib.lines.Line2D object at 0x...>] 

3243 >>> plt.title("Hamming window") 

3244 Text(0.5, 1.0, 'Hamming window') 

3245 >>> plt.ylabel("Amplitude") 

3246 Text(0, 0.5, 'Amplitude') 

3247 >>> plt.xlabel("Sample") 

3248 Text(0.5, 0, 'Sample') 

3249 >>> plt.show() 

3250 

3251 >>> plt.figure() 

3252 <Figure size 640x480 with 0 Axes> 

3253 >>> A = fft(window, 2048) / 25.5 

3254 >>> mag = np.abs(fftshift(A)) 

3255 >>> freq = np.linspace(-0.5, 0.5, len(A)) 

3256 >>> response = 20 * np.log10(mag) 

3257 >>> response = np.clip(response, -100, 100) 

3258 >>> plt.plot(freq, response) 

3259 [<matplotlib.lines.Line2D object at 0x...>] 

3260 >>> plt.title("Frequency response of Hamming window") 

3261 Text(0.5, 1.0, 'Frequency response of Hamming window') 

3262 >>> plt.ylabel("Magnitude [dB]") 

3263 Text(0, 0.5, 'Magnitude [dB]') 

3264 >>> plt.xlabel("Normalized frequency [cycles per sample]") 

3265 Text(0.5, 0, 'Normalized frequency [cycles per sample]') 

3266 >>> plt.axis('tight') 

3267 ... 

3268 >>> plt.show() 

3269 

3270 """ 

3271 if M < 1: 

3272 return array([], dtype=np.result_type(M, 0.0)) 

3273 if M == 1: 

3274 return ones(1, dtype=np.result_type(M, 0.0)) 

3275 n = arange(1-M, M, 2) 

3276 return 0.54 + 0.46*cos(pi*n/(M-1)) 

3277 

3278 

3279## Code from cephes for i0 

3280 

3281_i0A = [ 

3282 -4.41534164647933937950E-18, 

3283 3.33079451882223809783E-17, 

3284 -2.43127984654795469359E-16, 

3285 1.71539128555513303061E-15, 

3286 -1.16853328779934516808E-14, 

3287 7.67618549860493561688E-14, 

3288 -4.85644678311192946090E-13, 

3289 2.95505266312963983461E-12, 

3290 -1.72682629144155570723E-11, 

3291 9.67580903537323691224E-11, 

3292 -5.18979560163526290666E-10, 

3293 2.65982372468238665035E-9, 

3294 -1.30002500998624804212E-8, 

3295 6.04699502254191894932E-8, 

3296 -2.67079385394061173391E-7, 

3297 1.11738753912010371815E-6, 

3298 -4.41673835845875056359E-6, 

3299 1.64484480707288970893E-5, 

3300 -5.75419501008210370398E-5, 

3301 1.88502885095841655729E-4, 

3302 -5.76375574538582365885E-4, 

3303 1.63947561694133579842E-3, 

3304 -4.32430999505057594430E-3, 

3305 1.05464603945949983183E-2, 

3306 -2.37374148058994688156E-2, 

3307 4.93052842396707084878E-2, 

3308 -9.49010970480476444210E-2, 

3309 1.71620901522208775349E-1, 

3310 -3.04682672343198398683E-1, 

3311 6.76795274409476084995E-1 

3312 ] 

3313 

3314_i0B = [ 

3315 -7.23318048787475395456E-18, 

3316 -4.83050448594418207126E-18, 

3317 4.46562142029675999901E-17, 

3318 3.46122286769746109310E-17, 

3319 -2.82762398051658348494E-16, 

3320 -3.42548561967721913462E-16, 

3321 1.77256013305652638360E-15, 

3322 3.81168066935262242075E-15, 

3323 -9.55484669882830764870E-15, 

3324 -4.15056934728722208663E-14, 

3325 1.54008621752140982691E-14, 

3326 3.85277838274214270114E-13, 

3327 7.18012445138366623367E-13, 

3328 -1.79417853150680611778E-12, 

3329 -1.32158118404477131188E-11, 

3330 -3.14991652796324136454E-11, 

3331 1.18891471078464383424E-11, 

3332 4.94060238822496958910E-10, 

3333 3.39623202570838634515E-9, 

3334 2.26666899049817806459E-8, 

3335 2.04891858946906374183E-7, 

3336 2.89137052083475648297E-6, 

3337 6.88975834691682398426E-5, 

3338 3.36911647825569408990E-3, 

3339 8.04490411014108831608E-1 

3340 ] 

3341 

3342 

3343def _chbevl(x, vals): 

3344 b0 = vals[0] 

3345 b1 = 0.0 

3346 

3347 for i in range(1, len(vals)): 

3348 b2 = b1 

3349 b1 = b0 

3350 b0 = x*b1 - b2 + vals[i] 

3351 

3352 return 0.5*(b0 - b2) 

3353 

3354 

3355def _i0_1(x): 

3356 return exp(x) * _chbevl(x/2.0-2, _i0A) 

3357 

3358 

3359def _i0_2(x): 

3360 return exp(x) * _chbevl(32.0/x - 2.0, _i0B) / sqrt(x) 

3361 

3362 

3363def _i0_dispatcher(x): 

3364 return (x,) 

3365 

3366 

3367@array_function_dispatch(_i0_dispatcher) 

3368def i0(x): 

3369 """ 

3370 Modified Bessel function of the first kind, order 0. 

3371 

3372 Usually denoted :math:`I_0`. 

3373 

3374 Parameters 

3375 ---------- 

3376 x : array_like of float 

3377 Argument of the Bessel function. 

3378 

3379 Returns 

3380 ------- 

3381 out : ndarray, shape = x.shape, dtype = float 

3382 The modified Bessel function evaluated at each of the elements of `x`. 

3383 

3384 See Also 

3385 -------- 

3386 scipy.special.i0, scipy.special.iv, scipy.special.ive 

3387 

3388 Notes 

3389 ----- 

3390 The scipy implementation is recommended over this function: it is a 

3391 proper ufunc written in C, and more than an order of magnitude faster. 

3392 

3393 We use the algorithm published by Clenshaw [1]_ and referenced by 

3394 Abramowitz and Stegun [2]_, for which the function domain is 

3395 partitioned into the two intervals [0,8] and (8,inf), and Chebyshev 

3396 polynomial expansions are employed in each interval. Relative error on 

3397 the domain [0,30] using IEEE arithmetic is documented [3]_ as having a 

3398 peak of 5.8e-16 with an rms of 1.4e-16 (n = 30000). 

3399 

3400 References 

3401 ---------- 

3402 .. [1] C. W. Clenshaw, "Chebyshev series for mathematical functions", in 

3403 *National Physical Laboratory Mathematical Tables*, vol. 5, London: 

3404 Her Majesty's Stationery Office, 1962. 

3405 .. [2] M. Abramowitz and I. A. Stegun, *Handbook of Mathematical 

3406 Functions*, 10th printing, New York: Dover, 1964, pp. 379. 

3407 https://personal.math.ubc.ca/~cbm/aands/page_379.htm 

3408 .. [3] https://metacpan.org/pod/distribution/Math-Cephes/lib/Math/Cephes.pod#i0:-Modified-Bessel-function-of-order-zero 

3409 

3410 Examples 

3411 -------- 

3412 >>> np.i0(0.) 

3413 array(1.0) 

3414 >>> np.i0([0, 1, 2, 3]) 

3415 array([1. , 1.26606588, 2.2795853 , 4.88079259]) 

3416 

3417 """ 

3418 x = np.asanyarray(x) 

3419 if x.dtype.kind == 'c': 

3420 raise TypeError("i0 not supported for complex values") 

3421 if x.dtype.kind != 'f': 

3422 x = x.astype(float) 

3423 x = np.abs(x) 

3424 return piecewise(x, [x <= 8.0], [_i0_1, _i0_2]) 

3425 

3426## End of cephes code for i0 

3427 

3428 

3429@set_module('numpy') 

3430def kaiser(M, beta): 

3431 """ 

3432 Return the Kaiser window. 

3433 

3434 The Kaiser window is a taper formed by using a Bessel function. 

3435 

3436 Parameters 

3437 ---------- 

3438 M : int 

3439 Number of points in the output window. If zero or less, an 

3440 empty array is returned. 

3441 beta : float 

3442 Shape parameter for window. 

3443 

3444 Returns 

3445 ------- 

3446 out : array 

3447 The window, with the maximum value normalized to one (the value 

3448 one appears only if the number of samples is odd). 

3449 

3450 See Also 

3451 -------- 

3452 bartlett, blackman, hamming, hanning 

3453 

3454 Notes 

3455 ----- 

3456 The Kaiser window is defined as 

3457 

3458 .. math:: w(n) = I_0\\left( \\beta \\sqrt{1-\\frac{4n^2}{(M-1)^2}} 

3459 \\right)/I_0(\\beta) 

3460 

3461 with 

3462 

3463 .. math:: \\quad -\\frac{M-1}{2} \\leq n \\leq \\frac{M-1}{2}, 

3464 

3465 where :math:`I_0` is the modified zeroth-order Bessel function. 

3466 

3467 The Kaiser was named for Jim Kaiser, who discovered a simple 

3468 approximation to the DPSS window based on Bessel functions. The Kaiser 

3469 window is a very good approximation to the Digital Prolate Spheroidal 

3470 Sequence, or Slepian window, which is the transform which maximizes the 

3471 energy in the main lobe of the window relative to total energy. 

3472 

3473 The Kaiser can approximate many other windows by varying the beta 

3474 parameter. 

3475 

3476 ==== ======================= 

3477 beta Window shape 

3478 ==== ======================= 

3479 0 Rectangular 

3480 5 Similar to a Hamming 

3481 6 Similar to a Hanning 

3482 8.6 Similar to a Blackman 

3483 ==== ======================= 

3484 

3485 A beta value of 14 is probably a good starting point. Note that as beta 

3486 gets large, the window narrows, and so the number of samples needs to be 

3487 large enough to sample the increasingly narrow spike, otherwise NaNs will 

3488 get returned. 

3489 

3490 Most references to the Kaiser window come from the signal processing 

3491 literature, where it is used as one of many windowing functions for 

3492 smoothing values. It is also known as an apodization (which means 

3493 "removing the foot", i.e. smoothing discontinuities at the beginning 

3494 and end of the sampled signal) or tapering function. 

3495 

3496 References 

3497 ---------- 

3498 .. [1] J. F. Kaiser, "Digital Filters" - Ch 7 in "Systems analysis by 

3499 digital computer", Editors: F.F. Kuo and J.F. Kaiser, p 218-285. 

3500 John Wiley and Sons, New York, (1966). 

3501 .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", The 

3502 University of Alberta Press, 1975, pp. 177-178. 

3503 .. [3] Wikipedia, "Window function", 

3504 https://en.wikipedia.org/wiki/Window_function 

3505 

3506 Examples 

3507 -------- 

3508 >>> import matplotlib.pyplot as plt 

3509 >>> np.kaiser(12, 14) 

3510 array([7.72686684e-06, 3.46009194e-03, 4.65200189e-02, # may vary 

3511 2.29737120e-01, 5.99885316e-01, 9.45674898e-01, 

3512 9.45674898e-01, 5.99885316e-01, 2.29737120e-01, 

3513 4.65200189e-02, 3.46009194e-03, 7.72686684e-06]) 

3514 

3515 

3516 Plot the window and the frequency response: 

3517 

3518 >>> from numpy.fft import fft, fftshift 

3519 >>> window = np.kaiser(51, 14) 

3520 >>> plt.plot(window) 

3521 [<matplotlib.lines.Line2D object at 0x...>] 

3522 >>> plt.title("Kaiser window") 

3523 Text(0.5, 1.0, 'Kaiser window') 

3524 >>> plt.ylabel("Amplitude") 

3525 Text(0, 0.5, 'Amplitude') 

3526 >>> plt.xlabel("Sample") 

3527 Text(0.5, 0, 'Sample') 

3528 >>> plt.show() 

3529 

3530 >>> plt.figure() 

3531 <Figure size 640x480 with 0 Axes> 

3532 >>> A = fft(window, 2048) / 25.5 

3533 >>> mag = np.abs(fftshift(A)) 

3534 >>> freq = np.linspace(-0.5, 0.5, len(A)) 

3535 >>> response = 20 * np.log10(mag) 

3536 >>> response = np.clip(response, -100, 100) 

3537 >>> plt.plot(freq, response) 

3538 [<matplotlib.lines.Line2D object at 0x...>] 

3539 >>> plt.title("Frequency response of Kaiser window") 

3540 Text(0.5, 1.0, 'Frequency response of Kaiser window') 

3541 >>> plt.ylabel("Magnitude [dB]") 

3542 Text(0, 0.5, 'Magnitude [dB]') 

3543 >>> plt.xlabel("Normalized frequency [cycles per sample]") 

3544 Text(0.5, 0, 'Normalized frequency [cycles per sample]') 

3545 >>> plt.axis('tight') 

3546 (-0.5, 0.5, -100.0, ...) # may vary 

3547 >>> plt.show() 

3548 

3549 """ 

3550 if M == 1: 

3551 return np.ones(1, dtype=np.result_type(M, 0.0)) 

3552 n = arange(0, M) 

3553 alpha = (M-1)/2.0 

3554 return i0(beta * sqrt(1-((n-alpha)/alpha)**2.0))/i0(float(beta)) 

3555 

3556 

3557def _sinc_dispatcher(x): 

3558 return (x,) 

3559 

3560 

3561@array_function_dispatch(_sinc_dispatcher) 

3562def sinc(x): 

3563 r""" 

3564 Return the normalized sinc function. 

3565 

3566 The sinc function is equal to :math:`\sin(\pi x)/(\pi x)` for any argument 

3567 :math:`x\ne 0`. ``sinc(0)`` takes the limit value 1, making ``sinc`` not 

3568 only everywhere continuous but also infinitely differentiable. 

3569 

3570 .. note:: 

3571 

3572 Note the normalization factor of ``pi`` used in the definition. 

3573 This is the most commonly used definition in signal processing. 

3574 Use ``sinc(x / np.pi)`` to obtain the unnormalized sinc function 

3575 :math:`\sin(x)/x` that is more common in mathematics. 

3576 

3577 Parameters 

3578 ---------- 

3579 x : ndarray 

3580 Array (possibly multi-dimensional) of values for which to calculate 

3581 ``sinc(x)``. 

3582 

3583 Returns 

3584 ------- 

3585 out : ndarray 

3586 ``sinc(x)``, which has the same shape as the input. 

3587 

3588 Notes 

3589 ----- 

3590 The name sinc is short for "sine cardinal" or "sinus cardinalis". 

3591 

3592 The sinc function is used in various signal processing applications, 

3593 including in anti-aliasing, in the construction of a Lanczos resampling 

3594 filter, and in interpolation. 

3595 

3596 For bandlimited interpolation of discrete-time signals, the ideal 

3597 interpolation kernel is proportional to the sinc function. 

3598 

3599 References 

3600 ---------- 

3601 .. [1] Weisstein, Eric W. "Sinc Function." From MathWorld--A Wolfram Web 

3602 Resource. http://mathworld.wolfram.com/SincFunction.html 

3603 .. [2] Wikipedia, "Sinc function", 

3604 https://en.wikipedia.org/wiki/Sinc_function 

3605 

3606 Examples 

3607 -------- 

3608 >>> import matplotlib.pyplot as plt 

3609 >>> x = np.linspace(-4, 4, 41) 

3610 >>> np.sinc(x) 

3611 array([-3.89804309e-17, -4.92362781e-02, -8.40918587e-02, # may vary 

3612 -8.90384387e-02, -5.84680802e-02, 3.89804309e-17, 

3613 6.68206631e-02, 1.16434881e-01, 1.26137788e-01, 

3614 8.50444803e-02, -3.89804309e-17, -1.03943254e-01, 

3615 -1.89206682e-01, -2.16236208e-01, -1.55914881e-01, 

3616 3.89804309e-17, 2.33872321e-01, 5.04551152e-01, 

3617 7.56826729e-01, 9.35489284e-01, 1.00000000e+00, 

3618 9.35489284e-01, 7.56826729e-01, 5.04551152e-01, 

3619 2.33872321e-01, 3.89804309e-17, -1.55914881e-01, 

3620 -2.16236208e-01, -1.89206682e-01, -1.03943254e-01, 

3621 -3.89804309e-17, 8.50444803e-02, 1.26137788e-01, 

3622 1.16434881e-01, 6.68206631e-02, 3.89804309e-17, 

3623 -5.84680802e-02, -8.90384387e-02, -8.40918587e-02, 

3624 -4.92362781e-02, -3.89804309e-17]) 

3625 

3626 >>> plt.plot(x, np.sinc(x)) 

3627 [<matplotlib.lines.Line2D object at 0x...>] 

3628 >>> plt.title("Sinc Function") 

3629 Text(0.5, 1.0, 'Sinc Function') 

3630 >>> plt.ylabel("Amplitude") 

3631 Text(0, 0.5, 'Amplitude') 

3632 >>> plt.xlabel("X") 

3633 Text(0.5, 0, 'X') 

3634 >>> plt.show() 

3635 

3636 """ 

3637 x = np.asanyarray(x) 

3638 y = pi * where(x == 0, 1.0e-20, x) 

3639 return sin(y)/y 

3640 

3641 

3642def _msort_dispatcher(a): 

3643 return (a,) 

3644 

3645 

3646@array_function_dispatch(_msort_dispatcher) 

3647def msort(a): 

3648 """ 

3649 Return a copy of an array sorted along the first axis. 

3650 

3651 .. deprecated:: 1.24 

3652 

3653 msort is deprecated, use ``np.sort(a, axis=0)`` instead. 

3654 

3655 Parameters 

3656 ---------- 

3657 a : array_like 

3658 Array to be sorted. 

3659 

3660 Returns 

3661 ------- 

3662 sorted_array : ndarray 

3663 Array of the same type and shape as `a`. 

3664 

3665 See Also 

3666 -------- 

3667 sort 

3668 

3669 Notes 

3670 ----- 

3671 ``np.msort(a)`` is equivalent to ``np.sort(a, axis=0)``. 

3672 

3673 Examples 

3674 -------- 

3675 >>> a = np.array([[1, 4], [3, 1]]) 

3676 >>> np.msort(a) # sort along the first axis 

3677 array([[1, 1], 

3678 [3, 4]]) 

3679 

3680 """ 

3681 # 2022-10-20 1.24 

3682 warnings.warn( 

3683 "msort is deprecated, use np.sort(a, axis=0) instead", 

3684 DeprecationWarning, 

3685 stacklevel=3, 

3686 ) 

3687 b = array(a, subok=True, copy=True) 

3688 b.sort(0) 

3689 return b 

3690 

3691 

3692def _ureduce(a, func, keepdims=False, **kwargs): 

3693 """ 

3694 Internal Function. 

3695 Call `func` with `a` as first argument swapping the axes to use extended 

3696 axis on functions that don't support it natively. 

3697 

3698 Returns result and a.shape with axis dims set to 1. 

3699 

3700 Parameters 

3701 ---------- 

3702 a : array_like 

3703 Input array or object that can be converted to an array. 

3704 func : callable 

3705 Reduction function capable of receiving a single axis argument. 

3706 It is called with `a` as first argument followed by `kwargs`. 

3707 kwargs : keyword arguments 

3708 additional keyword arguments to pass to `func`. 

3709 

3710 Returns 

3711 ------- 

3712 result : tuple 

3713 Result of func(a, **kwargs) and a.shape with axis dims set to 1 

3714 which can be used to reshape the result to the same shape a ufunc with 

3715 keepdims=True would produce. 

3716 

3717 """ 

3718 a = np.asanyarray(a) 

3719 axis = kwargs.get('axis', None) 

3720 out = kwargs.get('out', None) 

3721 

3722 if keepdims is np._NoValue: 

3723 keepdims = False 

3724 

3725 nd = a.ndim 

3726 if axis is not None: 

3727 axis = _nx.normalize_axis_tuple(axis, nd) 

3728 

3729 if keepdims: 

3730 if out is not None: 

3731 index_out = tuple( 

3732 0 if i in axis else slice(None) for i in range(nd)) 

3733 kwargs['out'] = out[(Ellipsis, ) + index_out] 

3734 

3735 if len(axis) == 1: 

3736 kwargs['axis'] = axis[0] 

3737 else: 

3738 keep = set(range(nd)) - set(axis) 

3739 nkeep = len(keep) 

3740 # swap axis that should not be reduced to front 

3741 for i, s in enumerate(sorted(keep)): 

3742 a = a.swapaxes(i, s) 

3743 # merge reduced axis 

3744 a = a.reshape(a.shape[:nkeep] + (-1,)) 

3745 kwargs['axis'] = -1 

3746 else: 

3747 if keepdims: 

3748 if out is not None: 

3749 index_out = (0, ) * nd 

3750 kwargs['out'] = out[(Ellipsis, ) + index_out] 

3751 

3752 r = func(a, **kwargs) 

3753 

3754 if out is not None: 

3755 return out 

3756 

3757 if keepdims: 

3758 if axis is None: 

3759 index_r = (np.newaxis, ) * nd 

3760 else: 

3761 index_r = tuple( 

3762 np.newaxis if i in axis else slice(None) 

3763 for i in range(nd)) 

3764 r = r[(Ellipsis, ) + index_r] 

3765 

3766 return r 

3767 

3768 

3769def _median_dispatcher( 

3770 a, axis=None, out=None, overwrite_input=None, keepdims=None): 

3771 return (a, out) 

3772 

3773 

3774@array_function_dispatch(_median_dispatcher) 

3775def median(a, axis=None, out=None, overwrite_input=False, keepdims=False): 

3776 """ 

3777 Compute the median along the specified axis. 

3778 

3779 Returns the median of the array elements. 

3780 

3781 Parameters 

3782 ---------- 

3783 a : array_like 

3784 Input array or object that can be converted to an array. 

3785 axis : {int, sequence of int, None}, optional 

3786 Axis or axes along which the medians are computed. The default 

3787 is to compute the median along a flattened version of the array. 

3788 A sequence of axes is supported since version 1.9.0. 

3789 out : ndarray, optional 

3790 Alternative output array in which to place the result. It must 

3791 have the same shape and buffer length as the expected output, 

3792 but the type (of the output) will be cast if necessary. 

3793 overwrite_input : bool, optional 

3794 If True, then allow use of memory of input array `a` for 

3795 calculations. The input array will be modified by the call to 

3796 `median`. This will save memory when you do not need to preserve 

3797 the contents of the input array. Treat the input as undefined, 

3798 but it will probably be fully or partially sorted. Default is 

3799 False. If `overwrite_input` is ``True`` and `a` is not already an 

3800 `ndarray`, an error will be raised. 

3801 keepdims : bool, optional 

3802 If this is set to True, the axes which are reduced are left 

3803 in the result as dimensions with size one. With this option, 

3804 the result will broadcast correctly against the original `arr`. 

3805 

3806 .. versionadded:: 1.9.0 

3807 

3808 Returns 

3809 ------- 

3810 median : ndarray 

3811 A new array holding the result. If the input contains integers 

3812 or floats smaller than ``float64``, then the output data-type is 

3813 ``np.float64``. Otherwise, the data-type of the output is the 

3814 same as that of the input. If `out` is specified, that array is 

3815 returned instead. 

3816 

3817 See Also 

3818 -------- 

3819 mean, percentile 

3820 

3821 Notes 

3822 ----- 

3823 Given a vector ``V`` of length ``N``, the median of ``V`` is the 

3824 middle value of a sorted copy of ``V``, ``V_sorted`` - i 

3825 e., ``V_sorted[(N-1)/2]``, when ``N`` is odd, and the average of the 

3826 two middle values of ``V_sorted`` when ``N`` is even. 

3827 

3828 Examples 

3829 -------- 

3830 >>> a = np.array([[10, 7, 4], [3, 2, 1]]) 

3831 >>> a 

3832 array([[10, 7, 4], 

3833 [ 3, 2, 1]]) 

3834 >>> np.median(a) 

3835 3.5 

3836 >>> np.median(a, axis=0) 

3837 array([6.5, 4.5, 2.5]) 

3838 >>> np.median(a, axis=1) 

3839 array([7., 2.]) 

3840 >>> m = np.median(a, axis=0) 

3841 >>> out = np.zeros_like(m) 

3842 >>> np.median(a, axis=0, out=m) 

3843 array([6.5, 4.5, 2.5]) 

3844 >>> m 

3845 array([6.5, 4.5, 2.5]) 

3846 >>> b = a.copy() 

3847 >>> np.median(b, axis=1, overwrite_input=True) 

3848 array([7., 2.]) 

3849 >>> assert not np.all(a==b) 

3850 >>> b = a.copy() 

3851 >>> np.median(b, axis=None, overwrite_input=True) 

3852 3.5 

3853 >>> assert not np.all(a==b) 

3854 

3855 """ 

3856 return _ureduce(a, func=_median, keepdims=keepdims, axis=axis, out=out, 

3857 overwrite_input=overwrite_input) 

3858 

3859 

3860def _median(a, axis=None, out=None, overwrite_input=False): 

3861 # can't be reasonably be implemented in terms of percentile as we have to 

3862 # call mean to not break astropy 

3863 a = np.asanyarray(a) 

3864 

3865 # Set the partition indexes 

3866 if axis is None: 

3867 sz = a.size 

3868 else: 

3869 sz = a.shape[axis] 

3870 if sz % 2 == 0: 

3871 szh = sz // 2 

3872 kth = [szh - 1, szh] 

3873 else: 

3874 kth = [(sz - 1) // 2] 

3875 # Check if the array contains any nan's 

3876 if np.issubdtype(a.dtype, np.inexact): 

3877 kth.append(-1) 

3878 

3879 if overwrite_input: 

3880 if axis is None: 

3881 part = a.ravel() 

3882 part.partition(kth) 

3883 else: 

3884 a.partition(kth, axis=axis) 

3885 part = a 

3886 else: 

3887 part = partition(a, kth, axis=axis) 

3888 

3889 if part.shape == (): 

3890 # make 0-D arrays work 

3891 return part.item() 

3892 if axis is None: 

3893 axis = 0 

3894 

3895 indexer = [slice(None)] * part.ndim 

3896 index = part.shape[axis] // 2 

3897 if part.shape[axis] % 2 == 1: 

3898 # index with slice to allow mean (below) to work 

3899 indexer[axis] = slice(index, index+1) 

3900 else: 

3901 indexer[axis] = slice(index-1, index+1) 

3902 indexer = tuple(indexer) 

3903 

3904 # Use mean in both odd and even case to coerce data type, 

3905 # using out array if needed. 

3906 rout = mean(part[indexer], axis=axis, out=out) 

3907 # Check if the array contains any nan's 

3908 if np.issubdtype(a.dtype, np.inexact) and sz > 0: 

3909 # If nans are possible, warn and replace by nans like mean would. 

3910 rout = np.lib.utils._median_nancheck(part, rout, axis) 

3911 

3912 return rout 

3913 

3914 

3915def _percentile_dispatcher(a, q, axis=None, out=None, overwrite_input=None, 

3916 method=None, keepdims=None, *, interpolation=None): 

3917 return (a, q, out) 

3918 

3919 

3920@array_function_dispatch(_percentile_dispatcher) 

3921def percentile(a, 

3922 q, 

3923 axis=None, 

3924 out=None, 

3925 overwrite_input=False, 

3926 method="linear", 

3927 keepdims=False, 

3928 *, 

3929 interpolation=None): 

3930 """ 

3931 Compute the q-th percentile of the data along the specified axis. 

3932 

3933 Returns the q-th percentile(s) of the array elements. 

3934 

3935 Parameters 

3936 ---------- 

3937 a : array_like 

3938 Input array or object that can be converted to an array. 

3939 q : array_like of float 

3940 Percentile or sequence of percentiles to compute, which must be between 

3941 0 and 100 inclusive. 

3942 axis : {int, tuple of int, None}, optional 

3943 Axis or axes along which the percentiles are computed. The 

3944 default is to compute the percentile(s) along a flattened 

3945 version of the array. 

3946 

3947 .. versionchanged:: 1.9.0 

3948 A tuple of axes is supported 

3949 out : ndarray, optional 

3950 Alternative output array in which to place the result. It must 

3951 have the same shape and buffer length as the expected output, 

3952 but the type (of the output) will be cast if necessary. 

3953 overwrite_input : bool, optional 

3954 If True, then allow the input array `a` to be modified by intermediate 

3955 calculations, to save memory. In this case, the contents of the input 

3956 `a` after this function completes is undefined. 

3957 method : str, optional 

3958 This parameter specifies the method to use for estimating the 

3959 percentile. There are many different methods, some unique to NumPy. 

3960 See the notes for explanation. The options sorted by their R type 

3961 as summarized in the H&F paper [1]_ are: 

3962 

3963 1. 'inverted_cdf' 

3964 2. 'averaged_inverted_cdf' 

3965 3. 'closest_observation' 

3966 4. 'interpolated_inverted_cdf' 

3967 5. 'hazen' 

3968 6. 'weibull' 

3969 7. 'linear' (default) 

3970 8. 'median_unbiased' 

3971 9. 'normal_unbiased' 

3972 

3973 The first three methods are discontinuous. NumPy further defines the 

3974 following discontinuous variations of the default 'linear' (7.) option: 

3975 

3976 * 'lower' 

3977 * 'higher', 

3978 * 'midpoint' 

3979 * 'nearest' 

3980 

3981 .. versionchanged:: 1.22.0 

3982 This argument was previously called "interpolation" and only 

3983 offered the "linear" default and last four options. 

3984 

3985 keepdims : bool, optional 

3986 If this is set to True, the axes which are reduced are left in 

3987 the result as dimensions with size one. With this option, the 

3988 result will broadcast correctly against the original array `a`. 

3989 

3990 .. versionadded:: 1.9.0 

3991 

3992 interpolation : str, optional 

3993 Deprecated name for the method keyword argument. 

3994 

3995 .. deprecated:: 1.22.0 

3996 

3997 Returns 

3998 ------- 

3999 percentile : scalar or ndarray 

4000 If `q` is a single percentile and `axis=None`, then the result 

4001 is a scalar. If multiple percentiles are given, first axis of 

4002 the result corresponds to the percentiles. The other axes are 

4003 the axes that remain after the reduction of `a`. If the input 

4004 contains integers or floats smaller than ``float64``, the output 

4005 data-type is ``float64``. Otherwise, the output data-type is the 

4006 same as that of the input. If `out` is specified, that array is 

4007 returned instead. 

4008 

4009 See Also 

4010 -------- 

4011 mean 

4012 median : equivalent to ``percentile(..., 50)`` 

4013 nanpercentile 

4014 quantile : equivalent to percentile, except q in the range [0, 1]. 

4015 

4016 Notes 

4017 ----- 

4018 Given a vector ``V`` of length ``n``, the q-th percentile of ``V`` is 

4019 the value ``q/100`` of the way from the minimum to the maximum in a 

4020 sorted copy of ``V``. The values and distances of the two nearest 

4021 neighbors as well as the `method` parameter will determine the 

4022 percentile if the normalized ranking does not match the location of 

4023 ``q`` exactly. This function is the same as the median if ``q=50``, the 

4024 same as the minimum if ``q=0`` and the same as the maximum if 

4025 ``q=100``. 

4026 

4027 The optional `method` parameter specifies the method to use when the 

4028 desired percentile lies between two indexes ``i`` and ``j = i + 1``. 

4029 In that case, we first determine ``i + g``, a virtual index that lies 

4030 between ``i`` and ``j``, where ``i`` is the floor and ``g`` is the 

4031 fractional part of the index. The final result is, then, an interpolation 

4032 of ``a[i]`` and ``a[j]`` based on ``g``. During the computation of ``g``, 

4033 ``i`` and ``j`` are modified using correction constants ``alpha`` and 

4034 ``beta`` whose choices depend on the ``method`` used. Finally, note that 

4035 since Python uses 0-based indexing, the code subtracts another 1 from the 

4036 index internally. 

4037 

4038 The following formula determines the virtual index ``i + g``, the location  

4039 of the percentile in the sorted sample: 

4040 

4041 .. math:: 

4042 i + g = (q / 100) * ( n - alpha - beta + 1 ) + alpha 

4043 

4044 The different methods then work as follows 

4045 

4046 inverted_cdf: 

4047 method 1 of H&F [1]_. 

4048 This method gives discontinuous results: 

4049 

4050 * if g > 0 ; then take j 

4051 * if g = 0 ; then take i 

4052 

4053 averaged_inverted_cdf: 

4054 method 2 of H&F [1]_. 

4055 This method give discontinuous results: 

4056 

4057 * if g > 0 ; then take j 

4058 * if g = 0 ; then average between bounds 

4059 

4060 closest_observation: 

4061 method 3 of H&F [1]_. 

4062 This method give discontinuous results: 

4063 

4064 * if g > 0 ; then take j 

4065 * if g = 0 and index is odd ; then take j 

4066 * if g = 0 and index is even ; then take i 

4067 

4068 interpolated_inverted_cdf: 

4069 method 4 of H&F [1]_. 

4070 This method give continuous results using: 

4071 

4072 * alpha = 0 

4073 * beta = 1 

4074 

4075 hazen: 

4076 method 5 of H&F [1]_. 

4077 This method give continuous results using: 

4078 

4079 * alpha = 1/2 

4080 * beta = 1/2 

4081 

4082 weibull: 

4083 method 6 of H&F [1]_. 

4084 This method give continuous results using: 

4085 

4086 * alpha = 0 

4087 * beta = 0 

4088 

4089 linear: 

4090 method 7 of H&F [1]_. 

4091 This method give continuous results using: 

4092 

4093 * alpha = 1 

4094 * beta = 1 

4095 

4096 median_unbiased: 

4097 method 8 of H&F [1]_. 

4098 This method is probably the best method if the sample 

4099 distribution function is unknown (see reference). 

4100 This method give continuous results using: 

4101 

4102 * alpha = 1/3 

4103 * beta = 1/3 

4104 

4105 normal_unbiased: 

4106 method 9 of H&F [1]_. 

4107 This method is probably the best method if the sample 

4108 distribution function is known to be normal. 

4109 This method give continuous results using: 

4110 

4111 * alpha = 3/8 

4112 * beta = 3/8 

4113 

4114 lower: 

4115 NumPy method kept for backwards compatibility. 

4116 Takes ``i`` as the interpolation point. 

4117 

4118 higher: 

4119 NumPy method kept for backwards compatibility. 

4120 Takes ``j`` as the interpolation point. 

4121 

4122 nearest: 

4123 NumPy method kept for backwards compatibility. 

4124 Takes ``i`` or ``j``, whichever is nearest. 

4125 

4126 midpoint: 

4127 NumPy method kept for backwards compatibility. 

4128 Uses ``(i + j) / 2``. 

4129 

4130 Examples 

4131 -------- 

4132 >>> a = np.array([[10, 7, 4], [3, 2, 1]]) 

4133 >>> a 

4134 array([[10, 7, 4], 

4135 [ 3, 2, 1]]) 

4136 >>> np.percentile(a, 50) 

4137 3.5 

4138 >>> np.percentile(a, 50, axis=0) 

4139 array([6.5, 4.5, 2.5]) 

4140 >>> np.percentile(a, 50, axis=1) 

4141 array([7., 2.]) 

4142 >>> np.percentile(a, 50, axis=1, keepdims=True) 

4143 array([[7.], 

4144 [2.]]) 

4145 

4146 >>> m = np.percentile(a, 50, axis=0) 

4147 >>> out = np.zeros_like(m) 

4148 >>> np.percentile(a, 50, axis=0, out=out) 

4149 array([6.5, 4.5, 2.5]) 

4150 >>> m 

4151 array([6.5, 4.5, 2.5]) 

4152 

4153 >>> b = a.copy() 

4154 >>> np.percentile(b, 50, axis=1, overwrite_input=True) 

4155 array([7., 2.]) 

4156 >>> assert not np.all(a == b) 

4157 

4158 The different methods can be visualized graphically: 

4159 

4160 .. plot:: 

4161 

4162 import matplotlib.pyplot as plt 

4163 

4164 a = np.arange(4) 

4165 p = np.linspace(0, 100, 6001) 

4166 ax = plt.gca() 

4167 lines = [ 

4168 ('linear', '-', 'C0'), 

4169 ('inverted_cdf', ':', 'C1'), 

4170 # Almost the same as `inverted_cdf`: 

4171 ('averaged_inverted_cdf', '-.', 'C1'), 

4172 ('closest_observation', ':', 'C2'), 

4173 ('interpolated_inverted_cdf', '--', 'C1'), 

4174 ('hazen', '--', 'C3'), 

4175 ('weibull', '-.', 'C4'), 

4176 ('median_unbiased', '--', 'C5'), 

4177 ('normal_unbiased', '-.', 'C6'), 

4178 ] 

4179 for method, style, color in lines: 

4180 ax.plot( 

4181 p, np.percentile(a, p, method=method), 

4182 label=method, linestyle=style, color=color) 

4183 ax.set( 

4184 title='Percentiles for different methods and data: ' + str(a), 

4185 xlabel='Percentile', 

4186 ylabel='Estimated percentile value', 

4187 yticks=a) 

4188 ax.legend() 

4189 plt.show() 

4190 

4191 References 

4192 ---------- 

4193 .. [1] R. J. Hyndman and Y. Fan, 

4194 "Sample quantiles in statistical packages," 

4195 The American Statistician, 50(4), pp. 361-365, 1996 

4196 

4197 """ 

4198 if interpolation is not None: 

4199 method = _check_interpolation_as_method( 

4200 method, interpolation, "percentile") 

4201 q = np.true_divide(q, 100) 

4202 q = asanyarray(q) # undo any decay that the ufunc performed (see gh-13105) 

4203 if not _quantile_is_valid(q): 

4204 raise ValueError("Percentiles must be in the range [0, 100]") 

4205 return _quantile_unchecked( 

4206 a, q, axis, out, overwrite_input, method, keepdims) 

4207 

4208 

4209def _quantile_dispatcher(a, q, axis=None, out=None, overwrite_input=None, 

4210 method=None, keepdims=None, *, interpolation=None): 

4211 return (a, q, out) 

4212 

4213 

4214@array_function_dispatch(_quantile_dispatcher) 

4215def quantile(a, 

4216 q, 

4217 axis=None, 

4218 out=None, 

4219 overwrite_input=False, 

4220 method="linear", 

4221 keepdims=False, 

4222 *, 

4223 interpolation=None): 

4224 """ 

4225 Compute the q-th quantile of the data along the specified axis. 

4226 

4227 .. versionadded:: 1.15.0 

4228 

4229 Parameters 

4230 ---------- 

4231 a : array_like 

4232 Input array or object that can be converted to an array. 

4233 q : array_like of float 

4234 Quantile or sequence of quantiles to compute, which must be between 

4235 0 and 1 inclusive. 

4236 axis : {int, tuple of int, None}, optional 

4237 Axis or axes along which the quantiles are computed. The default is 

4238 to compute the quantile(s) along a flattened version of the array. 

4239 out : ndarray, optional 

4240 Alternative output array in which to place the result. It must have 

4241 the same shape and buffer length as the expected output, but the 

4242 type (of the output) will be cast if necessary. 

4243 overwrite_input : bool, optional 

4244 If True, then allow the input array `a` to be modified by 

4245 intermediate calculations, to save memory. In this case, the 

4246 contents of the input `a` after this function completes is 

4247 undefined. 

4248 method : str, optional 

4249 This parameter specifies the method to use for estimating the 

4250 quantile. There are many different methods, some unique to NumPy. 

4251 See the notes for explanation. The options sorted by their R type 

4252 as summarized in the H&F paper [1]_ are: 

4253 

4254 1. 'inverted_cdf' 

4255 2. 'averaged_inverted_cdf' 

4256 3. 'closest_observation' 

4257 4. 'interpolated_inverted_cdf' 

4258 5. 'hazen' 

4259 6. 'weibull' 

4260 7. 'linear' (default) 

4261 8. 'median_unbiased' 

4262 9. 'normal_unbiased' 

4263 

4264 The first three methods are discontinuous. NumPy further defines the 

4265 following discontinuous variations of the default 'linear' (7.) option: 

4266 

4267 * 'lower' 

4268 * 'higher', 

4269 * 'midpoint' 

4270 * 'nearest' 

4271 

4272 .. versionchanged:: 1.22.0 

4273 This argument was previously called "interpolation" and only 

4274 offered the "linear" default and last four options. 

4275 

4276 keepdims : bool, optional 

4277 If this is set to True, the axes which are reduced are left in 

4278 the result as dimensions with size one. With this option, the 

4279 result will broadcast correctly against the original array `a`. 

4280 

4281 interpolation : str, optional 

4282 Deprecated name for the method keyword argument. 

4283 

4284 .. deprecated:: 1.22.0 

4285 

4286 Returns 

4287 ------- 

4288 quantile : scalar or ndarray 

4289 If `q` is a single quantile and `axis=None`, then the result 

4290 is a scalar. If multiple quantiles are given, first axis of 

4291 the result corresponds to the quantiles. The other axes are 

4292 the axes that remain after the reduction of `a`. If the input 

4293 contains integers or floats smaller than ``float64``, the output 

4294 data-type is ``float64``. Otherwise, the output data-type is the 

4295 same as that of the input. If `out` is specified, that array is 

4296 returned instead. 

4297 

4298 See Also 

4299 -------- 

4300 mean 

4301 percentile : equivalent to quantile, but with q in the range [0, 100]. 

4302 median : equivalent to ``quantile(..., 0.5)`` 

4303 nanquantile 

4304 

4305 Notes 

4306 ----- 

4307 Given a vector ``V`` of length ``n``, the q-th quantile of ``V`` is 

4308 the value ``q`` of the way from the minimum to the maximum in a 

4309 sorted copy of ``V``. The values and distances of the two nearest 

4310 neighbors as well as the `method` parameter will determine the 

4311 quantile if the normalized ranking does not match the location of 

4312 ``q`` exactly. This function is the same as the median if ``q=0.5``, the 

4313 same as the minimum if ``q=0.0`` and the same as the maximum if 

4314 ``q=1.0``. 

4315 

4316 The optional `method` parameter specifies the method to use when the 

4317 desired quantile lies between two indexes ``i`` and ``j = i + 1``. 

4318 In that case, we first determine ``i + g``, a virtual index that lies 

4319 between ``i`` and ``j``, where ``i`` is the floor and ``g`` is the 

4320 fractional part of the index. The final result is, then, an interpolation 

4321 of ``a[i]`` and ``a[j]`` based on ``g``. During the computation of ``g``, 

4322 ``i`` and ``j`` are modified using correction constants ``alpha`` and 

4323 ``beta`` whose choices depend on the ``method`` used. Finally, note that 

4324 since Python uses 0-based indexing, the code subtracts another 1 from the 

4325 index internally. 

4326 

4327 The following formula determines the virtual index ``i + g``, the location  

4328 of the quantile in the sorted sample: 

4329 

4330 .. math:: 

4331 i + g = q * ( n - alpha - beta + 1 ) + alpha 

4332 

4333 The different methods then work as follows 

4334 

4335 inverted_cdf: 

4336 method 1 of H&F [1]_. 

4337 This method gives discontinuous results: 

4338 

4339 * if g > 0 ; then take j 

4340 * if g = 0 ; then take i 

4341 

4342 averaged_inverted_cdf: 

4343 method 2 of H&F [1]_. 

4344 This method gives discontinuous results: 

4345 

4346 * if g > 0 ; then take j 

4347 * if g = 0 ; then average between bounds 

4348 

4349 closest_observation: 

4350 method 3 of H&F [1]_. 

4351 This method gives discontinuous results: 

4352 

4353 * if g > 0 ; then take j 

4354 * if g = 0 and index is odd ; then take j 

4355 * if g = 0 and index is even ; then take i 

4356 

4357 interpolated_inverted_cdf: 

4358 method 4 of H&F [1]_. 

4359 This method gives continuous results using: 

4360 

4361 * alpha = 0 

4362 * beta = 1 

4363 

4364 hazen: 

4365 method 5 of H&F [1]_. 

4366 This method gives continuous results using: 

4367 

4368 * alpha = 1/2 

4369 * beta = 1/2 

4370 

4371 weibull: 

4372 method 6 of H&F [1]_. 

4373 This method gives continuous results using: 

4374 

4375 * alpha = 0 

4376 * beta = 0 

4377 

4378 linear: 

4379 method 7 of H&F [1]_. 

4380 This method gives continuous results using: 

4381 

4382 * alpha = 1 

4383 * beta = 1 

4384 

4385 median_unbiased: 

4386 method 8 of H&F [1]_. 

4387 This method is probably the best method if the sample 

4388 distribution function is unknown (see reference). 

4389 This method gives continuous results using: 

4390 

4391 * alpha = 1/3 

4392 * beta = 1/3 

4393 

4394 normal_unbiased: 

4395 method 9 of H&F [1]_. 

4396 This method is probably the best method if the sample 

4397 distribution function is known to be normal. 

4398 This method gives continuous results using: 

4399 

4400 * alpha = 3/8 

4401 * beta = 3/8 

4402 

4403 lower: 

4404 NumPy method kept for backwards compatibility. 

4405 Takes ``i`` as the interpolation point. 

4406 

4407 higher: 

4408 NumPy method kept for backwards compatibility. 

4409 Takes ``j`` as the interpolation point. 

4410 

4411 nearest: 

4412 NumPy method kept for backwards compatibility. 

4413 Takes ``i`` or ``j``, whichever is nearest. 

4414 

4415 midpoint: 

4416 NumPy method kept for backwards compatibility. 

4417 Uses ``(i + j) / 2``. 

4418 

4419 Examples 

4420 -------- 

4421 >>> a = np.array([[10, 7, 4], [3, 2, 1]]) 

4422 >>> a 

4423 array([[10, 7, 4], 

4424 [ 3, 2, 1]]) 

4425 >>> np.quantile(a, 0.5) 

4426 3.5 

4427 >>> np.quantile(a, 0.5, axis=0) 

4428 array([6.5, 4.5, 2.5]) 

4429 >>> np.quantile(a, 0.5, axis=1) 

4430 array([7., 2.]) 

4431 >>> np.quantile(a, 0.5, axis=1, keepdims=True) 

4432 array([[7.], 

4433 [2.]]) 

4434 >>> m = np.quantile(a, 0.5, axis=0) 

4435 >>> out = np.zeros_like(m) 

4436 >>> np.quantile(a, 0.5, axis=0, out=out) 

4437 array([6.5, 4.5, 2.5]) 

4438 >>> m 

4439 array([6.5, 4.5, 2.5]) 

4440 >>> b = a.copy() 

4441 >>> np.quantile(b, 0.5, axis=1, overwrite_input=True) 

4442 array([7., 2.]) 

4443 >>> assert not np.all(a == b) 

4444 

4445 See also `numpy.percentile` for a visualization of most methods. 

4446 

4447 References 

4448 ---------- 

4449 .. [1] R. J. Hyndman and Y. Fan, 

4450 "Sample quantiles in statistical packages," 

4451 The American Statistician, 50(4), pp. 361-365, 1996 

4452 

4453 """ 

4454 if interpolation is not None: 

4455 method = _check_interpolation_as_method( 

4456 method, interpolation, "quantile") 

4457 

4458 q = np.asanyarray(q) 

4459 if not _quantile_is_valid(q): 

4460 raise ValueError("Quantiles must be in the range [0, 1]") 

4461 return _quantile_unchecked( 

4462 a, q, axis, out, overwrite_input, method, keepdims) 

4463 

4464 

4465def _quantile_unchecked(a, 

4466 q, 

4467 axis=None, 

4468 out=None, 

4469 overwrite_input=False, 

4470 method="linear", 

4471 keepdims=False): 

4472 """Assumes that q is in [0, 1], and is an ndarray""" 

4473 return _ureduce(a, 

4474 func=_quantile_ureduce_func, 

4475 q=q, 

4476 keepdims=keepdims, 

4477 axis=axis, 

4478 out=out, 

4479 overwrite_input=overwrite_input, 

4480 method=method) 

4481 

4482 

4483def _quantile_is_valid(q): 

4484 # avoid expensive reductions, relevant for arrays with < O(1000) elements 

4485 if q.ndim == 1 and q.size < 10: 

4486 for i in range(q.size): 

4487 if not (0.0 <= q[i] <= 1.0): 

4488 return False 

4489 else: 

4490 if not (np.all(0 <= q) and np.all(q <= 1)): 

4491 return False 

4492 return True 

4493 

4494 

4495def _check_interpolation_as_method(method, interpolation, fname): 

4496 # Deprecated NumPy 1.22, 2021-11-08 

4497 warnings.warn( 

4498 f"the `interpolation=` argument to {fname} was renamed to " 

4499 "`method=`, which has additional options.\n" 

4500 "Users of the modes 'nearest', 'lower', 'higher', or " 

4501 "'midpoint' are encouraged to review the method they used. " 

4502 "(Deprecated NumPy 1.22)", 

4503 DeprecationWarning, stacklevel=4) 

4504 if method != "linear": 

4505 # sanity check, we assume this basically never happens 

4506 raise TypeError( 

4507 "You shall not pass both `method` and `interpolation`!\n" 

4508 "(`interpolation` is Deprecated in favor of `method`)") 

4509 return interpolation 

4510 

4511 

4512def _compute_virtual_index(n, quantiles, alpha: float, beta: float): 

4513 """ 

4514 Compute the floating point indexes of an array for the linear 

4515 interpolation of quantiles. 

4516 n : array_like 

4517 The sample sizes. 

4518 quantiles : array_like 

4519 The quantiles values. 

4520 alpha : float 

4521 A constant used to correct the index computed. 

4522 beta : float 

4523 A constant used to correct the index computed. 

4524 

4525 alpha and beta values depend on the chosen method 

4526 (see quantile documentation) 

4527 

4528 Reference: 

4529 Hyndman&Fan paper "Sample Quantiles in Statistical Packages", 

4530 DOI: 10.1080/00031305.1996.10473566 

4531 """ 

4532 return n * quantiles + ( 

4533 alpha + quantiles * (1 - alpha - beta) 

4534 ) - 1 

4535 

4536 

4537def _get_gamma(virtual_indexes, previous_indexes, method): 

4538 """ 

4539 Compute gamma (a.k.a 'm' or 'weight') for the linear interpolation 

4540 of quantiles. 

4541 

4542 virtual_indexes : array_like 

4543 The indexes where the percentile is supposed to be found in the sorted 

4544 sample. 

4545 previous_indexes : array_like 

4546 The floor values of virtual_indexes. 

4547 interpolation : dict 

4548 The interpolation method chosen, which may have a specific rule 

4549 modifying gamma. 

4550 

4551 gamma is usually the fractional part of virtual_indexes but can be modified 

4552 by the interpolation method. 

4553 """ 

4554 gamma = np.asanyarray(virtual_indexes - previous_indexes) 

4555 gamma = method["fix_gamma"](gamma, virtual_indexes) 

4556 return np.asanyarray(gamma) 

4557 

4558 

4559def _lerp(a, b, t, out=None): 

4560 """ 

4561 Compute the linear interpolation weighted by gamma on each point of 

4562 two same shape array. 

4563 

4564 a : array_like 

4565 Left bound. 

4566 b : array_like 

4567 Right bound. 

4568 t : array_like 

4569 The interpolation weight. 

4570 out : array_like 

4571 Output array. 

4572 """ 

4573 diff_b_a = subtract(b, a) 

4574 # asanyarray is a stop-gap until gh-13105 

4575 lerp_interpolation = asanyarray(add(a, diff_b_a * t, out=out)) 

4576 subtract(b, diff_b_a * (1 - t), out=lerp_interpolation, where=t >= 0.5) 

4577 if lerp_interpolation.ndim == 0 and out is None: 

4578 lerp_interpolation = lerp_interpolation[()] # unpack 0d arrays 

4579 return lerp_interpolation 

4580 

4581 

4582def _get_gamma_mask(shape, default_value, conditioned_value, where): 

4583 out = np.full(shape, default_value) 

4584 np.copyto(out, conditioned_value, where=where, casting="unsafe") 

4585 return out 

4586 

4587 

4588def _discret_interpolation_to_boundaries(index, gamma_condition_fun): 

4589 previous = np.floor(index) 

4590 next = previous + 1 

4591 gamma = index - previous 

4592 res = _get_gamma_mask(shape=index.shape, 

4593 default_value=next, 

4594 conditioned_value=previous, 

4595 where=gamma_condition_fun(gamma, index) 

4596 ).astype(np.intp) 

4597 # Some methods can lead to out-of-bound integers, clip them: 

4598 res[res < 0] = 0 

4599 return res 

4600 

4601 

4602def _closest_observation(n, quantiles): 

4603 gamma_fun = lambda gamma, index: (gamma == 0) & (np.floor(index) % 2 == 0) 

4604 return _discret_interpolation_to_boundaries((n * quantiles) - 1 - 0.5, 

4605 gamma_fun) 

4606 

4607 

4608def _inverted_cdf(n, quantiles): 

4609 gamma_fun = lambda gamma, _: (gamma == 0) 

4610 return _discret_interpolation_to_boundaries((n * quantiles) - 1, 

4611 gamma_fun) 

4612 

4613 

4614def _quantile_ureduce_func( 

4615 a: np.array, 

4616 q: np.array, 

4617 axis: int = None, 

4618 out=None, 

4619 overwrite_input: bool = False, 

4620 method="linear", 

4621) -> np.array: 

4622 if q.ndim > 2: 

4623 # The code below works fine for nd, but it might not have useful 

4624 # semantics. For now, keep the supported dimensions the same as it was 

4625 # before. 

4626 raise ValueError("q must be a scalar or 1d") 

4627 if overwrite_input: 

4628 if axis is None: 

4629 axis = 0 

4630 arr = a.ravel() 

4631 else: 

4632 arr = a 

4633 else: 

4634 if axis is None: 

4635 axis = 0 

4636 arr = a.flatten() 

4637 else: 

4638 arr = a.copy() 

4639 result = _quantile(arr, 

4640 quantiles=q, 

4641 axis=axis, 

4642 method=method, 

4643 out=out) 

4644 return result 

4645 

4646 

4647def _get_indexes(arr, virtual_indexes, valid_values_count): 

4648 """ 

4649 Get the valid indexes of arr neighbouring virtual_indexes. 

4650 Note 

4651 This is a companion function to linear interpolation of 

4652 Quantiles 

4653 

4654 Returns 

4655 ------- 

4656 (previous_indexes, next_indexes): Tuple 

4657 A Tuple of virtual_indexes neighbouring indexes 

4658 """ 

4659 previous_indexes = np.asanyarray(np.floor(virtual_indexes)) 

4660 next_indexes = np.asanyarray(previous_indexes + 1) 

4661 indexes_above_bounds = virtual_indexes >= valid_values_count - 1 

4662 # When indexes is above max index, take the max value of the array 

4663 if indexes_above_bounds.any(): 

4664 previous_indexes[indexes_above_bounds] = -1 

4665 next_indexes[indexes_above_bounds] = -1 

4666 # When indexes is below min index, take the min value of the array 

4667 indexes_below_bounds = virtual_indexes < 0 

4668 if indexes_below_bounds.any(): 

4669 previous_indexes[indexes_below_bounds] = 0 

4670 next_indexes[indexes_below_bounds] = 0 

4671 if np.issubdtype(arr.dtype, np.inexact): 

4672 # After the sort, slices having NaNs will have for last element a NaN 

4673 virtual_indexes_nans = np.isnan(virtual_indexes) 

4674 if virtual_indexes_nans.any(): 

4675 previous_indexes[virtual_indexes_nans] = -1 

4676 next_indexes[virtual_indexes_nans] = -1 

4677 previous_indexes = previous_indexes.astype(np.intp) 

4678 next_indexes = next_indexes.astype(np.intp) 

4679 return previous_indexes, next_indexes 

4680 

4681 

4682def _quantile( 

4683 arr: np.array, 

4684 quantiles: np.array, 

4685 axis: int = -1, 

4686 method="linear", 

4687 out=None, 

4688): 

4689 """ 

4690 Private function that doesn't support extended axis or keepdims. 

4691 These methods are extended to this function using _ureduce 

4692 See nanpercentile for parameter usage 

4693 It computes the quantiles of the array for the given axis. 

4694 A linear interpolation is performed based on the `interpolation`. 

4695 

4696 By default, the method is "linear" where alpha == beta == 1 which 

4697 performs the 7th method of Hyndman&Fan. 

4698 With "median_unbiased" we get alpha == beta == 1/3 

4699 thus the 8th method of Hyndman&Fan. 

4700 """ 

4701 # --- Setup 

4702 arr = np.asanyarray(arr) 

4703 values_count = arr.shape[axis] 

4704 # The dimensions of `q` are prepended to the output shape, so we need the 

4705 # axis being sampled from `arr` to be last. 

4706 DATA_AXIS = 0 

4707 if axis != DATA_AXIS: # But moveaxis is slow, so only call it if axis!=0. 

4708 arr = np.moveaxis(arr, axis, destination=DATA_AXIS) 

4709 # --- Computation of indexes 

4710 # Index where to find the value in the sorted array. 

4711 # Virtual because it is a floating point value, not an valid index. 

4712 # The nearest neighbours are used for interpolation 

4713 try: 

4714 method = _QuantileMethods[method] 

4715 except KeyError: 

4716 raise ValueError( 

4717 f"{method!r} is not a valid method. Use one of: " 

4718 f"{_QuantileMethods.keys()}") from None 

4719 virtual_indexes = method["get_virtual_index"](values_count, quantiles) 

4720 virtual_indexes = np.asanyarray(virtual_indexes) 

4721 if np.issubdtype(virtual_indexes.dtype, np.integer): 

4722 # No interpolation needed, take the points along axis 

4723 if np.issubdtype(arr.dtype, np.inexact): 

4724 # may contain nan, which would sort to the end 

4725 arr.partition(concatenate((virtual_indexes.ravel(), [-1])), axis=0) 

4726 slices_having_nans = np.isnan(arr[-1]) 

4727 else: 

4728 # cannot contain nan 

4729 arr.partition(virtual_indexes.ravel(), axis=0) 

4730 slices_having_nans = np.array(False, dtype=bool) 

4731 result = take(arr, virtual_indexes, axis=0, out=out) 

4732 else: 

4733 previous_indexes, next_indexes = _get_indexes(arr, 

4734 virtual_indexes, 

4735 values_count) 

4736 # --- Sorting 

4737 arr.partition( 

4738 np.unique(np.concatenate(([0, -1], 

4739 previous_indexes.ravel(), 

4740 next_indexes.ravel(), 

4741 ))), 

4742 axis=DATA_AXIS) 

4743 if np.issubdtype(arr.dtype, np.inexact): 

4744 slices_having_nans = np.isnan( 

4745 take(arr, indices=-1, axis=DATA_AXIS) 

4746 ) 

4747 else: 

4748 slices_having_nans = None 

4749 # --- Get values from indexes 

4750 previous = np.take(arr, previous_indexes, axis=DATA_AXIS) 

4751 next = np.take(arr, next_indexes, axis=DATA_AXIS) 

4752 # --- Linear interpolation 

4753 gamma = _get_gamma(virtual_indexes, previous_indexes, method) 

4754 result_shape = virtual_indexes.shape + (1,) * (arr.ndim - 1) 

4755 gamma = gamma.reshape(result_shape) 

4756 result = _lerp(previous, 

4757 next, 

4758 gamma, 

4759 out=out) 

4760 if np.any(slices_having_nans): 

4761 if result.ndim == 0 and out is None: 

4762 # can't write to a scalar 

4763 result = arr.dtype.type(np.nan) 

4764 else: 

4765 result[..., slices_having_nans] = np.nan 

4766 return result 

4767 

4768 

4769def _trapz_dispatcher(y, x=None, dx=None, axis=None): 

4770 return (y, x) 

4771 

4772 

4773@array_function_dispatch(_trapz_dispatcher) 

4774def trapz(y, x=None, dx=1.0, axis=-1): 

4775 r""" 

4776 Integrate along the given axis using the composite trapezoidal rule. 

4777 

4778 If `x` is provided, the integration happens in sequence along its 

4779 elements - they are not sorted. 

4780 

4781 Integrate `y` (`x`) along each 1d slice on the given axis, compute 

4782 :math:`\int y(x) dx`. 

4783 When `x` is specified, this integrates along the parametric curve, 

4784 computing :math:`\int_t y(t) dt = 

4785 \int_t y(t) \left.\frac{dx}{dt}\right|_{x=x(t)} dt`. 

4786 

4787 Parameters 

4788 ---------- 

4789 y : array_like 

4790 Input array to integrate. 

4791 x : array_like, optional 

4792 The sample points corresponding to the `y` values. If `x` is None, 

4793 the sample points are assumed to be evenly spaced `dx` apart. The 

4794 default is None. 

4795 dx : scalar, optional 

4796 The spacing between sample points when `x` is None. The default is 1. 

4797 axis : int, optional 

4798 The axis along which to integrate. 

4799 

4800 Returns 

4801 ------- 

4802 trapz : float or ndarray 

4803 Definite integral of `y` = n-dimensional array as approximated along 

4804 a single axis by the trapezoidal rule. If `y` is a 1-dimensional array, 

4805 then the result is a float. If `n` is greater than 1, then the result 

4806 is an `n`-1 dimensional array. 

4807 

4808 See Also 

4809 -------- 

4810 sum, cumsum 

4811 

4812 Notes 

4813 ----- 

4814 Image [2]_ illustrates trapezoidal rule -- y-axis locations of points 

4815 will be taken from `y` array, by default x-axis distances between 

4816 points will be 1.0, alternatively they can be provided with `x` array 

4817 or with `dx` scalar. Return value will be equal to combined area under 

4818 the red lines. 

4819 

4820 

4821 References 

4822 ---------- 

4823 .. [1] Wikipedia page: https://en.wikipedia.org/wiki/Trapezoidal_rule 

4824 

4825 .. [2] Illustration image: 

4826 https://en.wikipedia.org/wiki/File:Composite_trapezoidal_rule_illustration.png 

4827 

4828 Examples 

4829 -------- 

4830 >>> np.trapz([1,2,3]) 

4831 4.0 

4832 >>> np.trapz([1,2,3], x=[4,6,8]) 

4833 8.0 

4834 >>> np.trapz([1,2,3], dx=2) 

4835 8.0 

4836 

4837 Using a decreasing `x` corresponds to integrating in reverse: 

4838 

4839 >>> np.trapz([1,2,3], x=[8,6,4]) 

4840 -8.0 

4841 

4842 More generally `x` is used to integrate along a parametric curve. 

4843 This finds the area of a circle, noting we repeat the sample which closes 

4844 the curve: 

4845 

4846 >>> theta = np.linspace(0, 2 * np.pi, num=1000, endpoint=True) 

4847 >>> np.trapz(np.cos(theta), x=np.sin(theta)) 

4848 3.141571941375841 

4849 

4850 >>> a = np.arange(6).reshape(2, 3) 

4851 >>> a 

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

4853 [3, 4, 5]]) 

4854 >>> np.trapz(a, axis=0) 

4855 array([1.5, 2.5, 3.5]) 

4856 >>> np.trapz(a, axis=1) 

4857 array([2., 8.]) 

4858 """ 

4859 y = asanyarray(y) 

4860 if x is None: 

4861 d = dx 

4862 else: 

4863 x = asanyarray(x) 

4864 if x.ndim == 1: 

4865 d = diff(x) 

4866 # reshape to correct shape 

4867 shape = [1]*y.ndim 

4868 shape[axis] = d.shape[0] 

4869 d = d.reshape(shape) 

4870 else: 

4871 d = diff(x, axis=axis) 

4872 nd = y.ndim 

4873 slice1 = [slice(None)]*nd 

4874 slice2 = [slice(None)]*nd 

4875 slice1[axis] = slice(1, None) 

4876 slice2[axis] = slice(None, -1) 

4877 try: 

4878 ret = (d * (y[tuple(slice1)] + y[tuple(slice2)]) / 2.0).sum(axis) 

4879 except ValueError: 

4880 # Operations didn't work, cast to ndarray 

4881 d = np.asarray(d) 

4882 y = np.asarray(y) 

4883 ret = add.reduce(d * (y[tuple(slice1)]+y[tuple(slice2)])/2.0, axis) 

4884 return ret 

4885 

4886 

4887def _meshgrid_dispatcher(*xi, copy=None, sparse=None, indexing=None): 

4888 return xi 

4889 

4890 

4891# Based on scitools meshgrid 

4892@array_function_dispatch(_meshgrid_dispatcher) 

4893def meshgrid(*xi, copy=True, sparse=False, indexing='xy'): 

4894 """ 

4895 Return coordinate matrices from coordinate vectors. 

4896 

4897 Make N-D coordinate arrays for vectorized evaluations of 

4898 N-D scalar/vector fields over N-D grids, given 

4899 one-dimensional coordinate arrays x1, x2,..., xn. 

4900 

4901 .. versionchanged:: 1.9 

4902 1-D and 0-D cases are allowed. 

4903 

4904 Parameters 

4905 ---------- 

4906 x1, x2,..., xn : array_like 

4907 1-D arrays representing the coordinates of a grid. 

4908 indexing : {'xy', 'ij'}, optional 

4909 Cartesian ('xy', default) or matrix ('ij') indexing of output. 

4910 See Notes for more details. 

4911 

4912 .. versionadded:: 1.7.0 

4913 sparse : bool, optional 

4914 If True the shape of the returned coordinate array for dimension *i* 

4915 is reduced from ``(N1, ..., Ni, ... Nn)`` to 

4916 ``(1, ..., 1, Ni, 1, ..., 1)``. These sparse coordinate grids are 

4917 intended to be use with :ref:`basics.broadcasting`. When all 

4918 coordinates are used in an expression, broadcasting still leads to a 

4919 fully-dimensonal result array. 

4920 

4921 Default is False. 

4922 

4923 .. versionadded:: 1.7.0 

4924 copy : bool, optional 

4925 If False, a view into the original arrays are returned in order to 

4926 conserve memory. Default is True. Please note that 

4927 ``sparse=False, copy=False`` will likely return non-contiguous 

4928 arrays. Furthermore, more than one element of a broadcast array 

4929 may refer to a single memory location. If you need to write to the 

4930 arrays, make copies first. 

4931 

4932 .. versionadded:: 1.7.0 

4933 

4934 Returns 

4935 ------- 

4936 X1, X2,..., XN : ndarray 

4937 For vectors `x1`, `x2`,..., `xn` with lengths ``Ni=len(xi)``, 

4938 returns ``(N1, N2, N3,..., Nn)`` shaped arrays if indexing='ij' 

4939 or ``(N2, N1, N3,..., Nn)`` shaped arrays if indexing='xy' 

4940 with the elements of `xi` repeated to fill the matrix along 

4941 the first dimension for `x1`, the second for `x2` and so on. 

4942 

4943 Notes 

4944 ----- 

4945 This function supports both indexing conventions through the indexing 

4946 keyword argument. Giving the string 'ij' returns a meshgrid with 

4947 matrix indexing, while 'xy' returns a meshgrid with Cartesian indexing. 

4948 In the 2-D case with inputs of length M and N, the outputs are of shape 

4949 (N, M) for 'xy' indexing and (M, N) for 'ij' indexing. In the 3-D case 

4950 with inputs of length M, N and P, outputs are of shape (N, M, P) for 

4951 'xy' indexing and (M, N, P) for 'ij' indexing. The difference is 

4952 illustrated by the following code snippet:: 

4953 

4954 xv, yv = np.meshgrid(x, y, indexing='ij') 

4955 for i in range(nx): 

4956 for j in range(ny): 

4957 # treat xv[i,j], yv[i,j] 

4958 

4959 xv, yv = np.meshgrid(x, y, indexing='xy') 

4960 for i in range(nx): 

4961 for j in range(ny): 

4962 # treat xv[j,i], yv[j,i] 

4963 

4964 In the 1-D and 0-D case, the indexing and sparse keywords have no effect. 

4965 

4966 See Also 

4967 -------- 

4968 mgrid : Construct a multi-dimensional "meshgrid" using indexing notation. 

4969 ogrid : Construct an open multi-dimensional "meshgrid" using indexing 

4970 notation. 

4971 how-to-index 

4972 

4973 Examples 

4974 -------- 

4975 >>> nx, ny = (3, 2) 

4976 >>> x = np.linspace(0, 1, nx) 

4977 >>> y = np.linspace(0, 1, ny) 

4978 >>> xv, yv = np.meshgrid(x, y) 

4979 >>> xv 

4980 array([[0. , 0.5, 1. ], 

4981 [0. , 0.5, 1. ]]) 

4982 >>> yv 

4983 array([[0., 0., 0.], 

4984 [1., 1., 1.]]) 

4985 

4986 The result of `meshgrid` is a coordinate grid: 

4987 

4988 >>> import matplotlib.pyplot as plt 

4989 >>> plt.plot(xv, yv, marker='o', color='k', linestyle='none') 

4990 >>> plt.show() 

4991 

4992 You can create sparse output arrays to save memory and computation time. 

4993 

4994 >>> xv, yv = np.meshgrid(x, y, sparse=True) 

4995 >>> xv 

4996 array([[0. , 0.5, 1. ]]) 

4997 >>> yv 

4998 array([[0.], 

4999 [1.]]) 

5000 

5001 `meshgrid` is very useful to evaluate functions on a grid. If the 

5002 function depends on all coordinates, both dense and sparse outputs can be 

5003 used. 

5004 

5005 >>> x = np.linspace(-5, 5, 101) 

5006 >>> y = np.linspace(-5, 5, 101) 

5007 >>> # full coordinate arrays 

5008 >>> xx, yy = np.meshgrid(x, y) 

5009 >>> zz = np.sqrt(xx**2 + yy**2) 

5010 >>> xx.shape, yy.shape, zz.shape 

5011 ((101, 101), (101, 101), (101, 101)) 

5012 >>> # sparse coordinate arrays 

5013 >>> xs, ys = np.meshgrid(x, y, sparse=True) 

5014 >>> zs = np.sqrt(xs**2 + ys**2) 

5015 >>> xs.shape, ys.shape, zs.shape 

5016 ((1, 101), (101, 1), (101, 101)) 

5017 >>> np.array_equal(zz, zs) 

5018 True 

5019 

5020 >>> h = plt.contourf(x, y, zs) 

5021 >>> plt.axis('scaled') 

5022 >>> plt.colorbar() 

5023 >>> plt.show() 

5024 """ 

5025 ndim = len(xi) 

5026 

5027 if indexing not in ['xy', 'ij']: 

5028 raise ValueError( 

5029 "Valid values for `indexing` are 'xy' and 'ij'.") 

5030 

5031 s0 = (1,) * ndim 

5032 output = [np.asanyarray(x).reshape(s0[:i] + (-1,) + s0[i + 1:]) 

5033 for i, x in enumerate(xi)] 

5034 

5035 if indexing == 'xy' and ndim > 1: 

5036 # switch first and second axis 

5037 output[0].shape = (1, -1) + s0[2:] 

5038 output[1].shape = (-1, 1) + s0[2:] 

5039 

5040 if not sparse: 

5041 # Return the full N-D matrix (not only the 1-D vector) 

5042 output = np.broadcast_arrays(*output, subok=True) 

5043 

5044 if copy: 

5045 output = [x.copy() for x in output] 

5046 

5047 return output 

5048 

5049 

5050def _delete_dispatcher(arr, obj, axis=None): 

5051 return (arr, obj) 

5052 

5053 

5054@array_function_dispatch(_delete_dispatcher) 

5055def delete(arr, obj, axis=None): 

5056 """ 

5057 Return a new array with sub-arrays along an axis deleted. For a one 

5058 dimensional array, this returns those entries not returned by 

5059 `arr[obj]`. 

5060 

5061 Parameters 

5062 ---------- 

5063 arr : array_like 

5064 Input array. 

5065 obj : slice, int or array of ints 

5066 Indicate indices of sub-arrays to remove along the specified axis. 

5067 

5068 .. versionchanged:: 1.19.0 

5069 Boolean indices are now treated as a mask of elements to remove, 

5070 rather than being cast to the integers 0 and 1. 

5071 

5072 axis : int, optional 

5073 The axis along which to delete the subarray defined by `obj`. 

5074 If `axis` is None, `obj` is applied to the flattened array. 

5075 

5076 Returns 

5077 ------- 

5078 out : ndarray 

5079 A copy of `arr` with the elements specified by `obj` removed. Note 

5080 that `delete` does not occur in-place. If `axis` is None, `out` is 

5081 a flattened array. 

5082 

5083 See Also 

5084 -------- 

5085 insert : Insert elements into an array. 

5086 append : Append elements at the end of an array. 

5087 

5088 Notes 

5089 ----- 

5090 Often it is preferable to use a boolean mask. For example: 

5091 

5092 >>> arr = np.arange(12) + 1 

5093 >>> mask = np.ones(len(arr), dtype=bool) 

5094 >>> mask[[0,2,4]] = False 

5095 >>> result = arr[mask,...] 

5096 

5097 Is equivalent to ``np.delete(arr, [0,2,4], axis=0)``, but allows further 

5098 use of `mask`. 

5099 

5100 Examples 

5101 -------- 

5102 >>> arr = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]]) 

5103 >>> arr 

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

5105 [ 5, 6, 7, 8], 

5106 [ 9, 10, 11, 12]]) 

5107 >>> np.delete(arr, 1, 0) 

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

5109 [ 9, 10, 11, 12]]) 

5110 

5111 >>> np.delete(arr, np.s_[::2], 1) 

5112 array([[ 2, 4], 

5113 [ 6, 8], 

5114 [10, 12]]) 

5115 >>> np.delete(arr, [1,3,5], None) 

5116 array([ 1, 3, 5, 7, 8, 9, 10, 11, 12]) 

5117 

5118 """ 

5119 wrap = None 

5120 if type(arr) is not ndarray: 

5121 try: 

5122 wrap = arr.__array_wrap__ 

5123 except AttributeError: 

5124 pass 

5125 

5126 arr = asarray(arr) 

5127 ndim = arr.ndim 

5128 arrorder = 'F' if arr.flags.fnc else 'C' 

5129 if axis is None: 

5130 if ndim != 1: 

5131 arr = arr.ravel() 

5132 # needed for np.matrix, which is still not 1d after being ravelled 

5133 ndim = arr.ndim 

5134 axis = ndim - 1 

5135 else: 

5136 axis = normalize_axis_index(axis, ndim) 

5137 

5138 slobj = [slice(None)]*ndim 

5139 N = arr.shape[axis] 

5140 newshape = list(arr.shape) 

5141 

5142 if isinstance(obj, slice): 

5143 start, stop, step = obj.indices(N) 

5144 xr = range(start, stop, step) 

5145 numtodel = len(xr) 

5146 

5147 if numtodel <= 0: 

5148 if wrap: 

5149 return wrap(arr.copy(order=arrorder)) 

5150 else: 

5151 return arr.copy(order=arrorder) 

5152 

5153 # Invert if step is negative: 

5154 if step < 0: 

5155 step = -step 

5156 start = xr[-1] 

5157 stop = xr[0] + 1 

5158 

5159 newshape[axis] -= numtodel 

5160 new = empty(newshape, arr.dtype, arrorder) 

5161 # copy initial chunk 

5162 if start == 0: 

5163 pass 

5164 else: 

5165 slobj[axis] = slice(None, start) 

5166 new[tuple(slobj)] = arr[tuple(slobj)] 

5167 # copy end chunk 

5168 if stop == N: 

5169 pass 

5170 else: 

5171 slobj[axis] = slice(stop-numtodel, None) 

5172 slobj2 = [slice(None)]*ndim 

5173 slobj2[axis] = slice(stop, None) 

5174 new[tuple(slobj)] = arr[tuple(slobj2)] 

5175 # copy middle pieces 

5176 if step == 1: 

5177 pass 

5178 else: # use array indexing. 

5179 keep = ones(stop-start, dtype=bool) 

5180 keep[:stop-start:step] = False 

5181 slobj[axis] = slice(start, stop-numtodel) 

5182 slobj2 = [slice(None)]*ndim 

5183 slobj2[axis] = slice(start, stop) 

5184 arr = arr[tuple(slobj2)] 

5185 slobj2[axis] = keep 

5186 new[tuple(slobj)] = arr[tuple(slobj2)] 

5187 if wrap: 

5188 return wrap(new) 

5189 else: 

5190 return new 

5191 

5192 if isinstance(obj, (int, integer)) and not isinstance(obj, bool): 

5193 single_value = True 

5194 else: 

5195 single_value = False 

5196 _obj = obj 

5197 obj = np.asarray(obj) 

5198 # `size == 0` to allow empty lists similar to indexing, but (as there) 

5199 # is really too generic: 

5200 if obj.size == 0 and not isinstance(_obj, np.ndarray): 

5201 obj = obj.astype(intp) 

5202 elif obj.size == 1 and obj.dtype.kind in "ui": 

5203 # For a size 1 integer array we can use the single-value path 

5204 # (most dtypes, except boolean, should just fail later). 

5205 obj = obj.item() 

5206 single_value = True 

5207 

5208 if single_value: 

5209 # optimization for a single value 

5210 if (obj < -N or obj >= N): 

5211 raise IndexError( 

5212 "index %i is out of bounds for axis %i with " 

5213 "size %i" % (obj, axis, N)) 

5214 if (obj < 0): 

5215 obj += N 

5216 newshape[axis] -= 1 

5217 new = empty(newshape, arr.dtype, arrorder) 

5218 slobj[axis] = slice(None, obj) 

5219 new[tuple(slobj)] = arr[tuple(slobj)] 

5220 slobj[axis] = slice(obj, None) 

5221 slobj2 = [slice(None)]*ndim 

5222 slobj2[axis] = slice(obj+1, None) 

5223 new[tuple(slobj)] = arr[tuple(slobj2)] 

5224 else: 

5225 if obj.dtype == bool: 

5226 if obj.shape != (N,): 

5227 raise ValueError('boolean array argument obj to delete ' 

5228 'must be one dimensional and match the axis ' 

5229 'length of {}'.format(N)) 

5230 

5231 # optimization, the other branch is slower 

5232 keep = ~obj 

5233 else: 

5234 keep = ones(N, dtype=bool) 

5235 keep[obj,] = False 

5236 

5237 slobj[axis] = keep 

5238 new = arr[tuple(slobj)] 

5239 

5240 if wrap: 

5241 return wrap(new) 

5242 else: 

5243 return new 

5244 

5245 

5246def _insert_dispatcher(arr, obj, values, axis=None): 

5247 return (arr, obj, values) 

5248 

5249 

5250@array_function_dispatch(_insert_dispatcher) 

5251def insert(arr, obj, values, axis=None): 

5252 """ 

5253 Insert values along the given axis before the given indices. 

5254 

5255 Parameters 

5256 ---------- 

5257 arr : array_like 

5258 Input array. 

5259 obj : int, slice or sequence of ints 

5260 Object that defines the index or indices before which `values` is 

5261 inserted. 

5262 

5263 .. versionadded:: 1.8.0 

5264 

5265 Support for multiple insertions when `obj` is a single scalar or a 

5266 sequence with one element (similar to calling insert multiple 

5267 times). 

5268 values : array_like 

5269 Values to insert into `arr`. If the type of `values` is different 

5270 from that of `arr`, `values` is converted to the type of `arr`. 

5271 `values` should be shaped so that ``arr[...,obj,...] = values`` 

5272 is legal. 

5273 axis : int, optional 

5274 Axis along which to insert `values`. If `axis` is None then `arr` 

5275 is flattened first. 

5276 

5277 Returns 

5278 ------- 

5279 out : ndarray 

5280 A copy of `arr` with `values` inserted. Note that `insert` 

5281 does not occur in-place: a new array is returned. If 

5282 `axis` is None, `out` is a flattened array. 

5283 

5284 See Also 

5285 -------- 

5286 append : Append elements at the end of an array. 

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

5288 delete : Delete elements from an array. 

5289 

5290 Notes 

5291 ----- 

5292 Note that for higher dimensional inserts ``obj=0`` behaves very different 

5293 from ``obj=[0]`` just like ``arr[:,0,:] = values`` is different from 

5294 ``arr[:,[0],:] = values``. 

5295 

5296 Examples 

5297 -------- 

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

5299 >>> a 

5300 array([[1, 1], 

5301 [2, 2], 

5302 [3, 3]]) 

5303 >>> np.insert(a, 1, 5) 

5304 array([1, 5, 1, ..., 2, 3, 3]) 

5305 >>> np.insert(a, 1, 5, axis=1) 

5306 array([[1, 5, 1], 

5307 [2, 5, 2], 

5308 [3, 5, 3]]) 

5309 

5310 Difference between sequence and scalars: 

5311 

5312 >>> np.insert(a, [1], [[1],[2],[3]], axis=1) 

5313 array([[1, 1, 1], 

5314 [2, 2, 2], 

5315 [3, 3, 3]]) 

5316 >>> np.array_equal(np.insert(a, 1, [1, 2, 3], axis=1), 

5317 ... np.insert(a, [1], [[1],[2],[3]], axis=1)) 

5318 True 

5319 

5320 >>> b = a.flatten() 

5321 >>> b 

5322 array([1, 1, 2, 2, 3, 3]) 

5323 >>> np.insert(b, [2, 2], [5, 6]) 

5324 array([1, 1, 5, ..., 2, 3, 3]) 

5325 

5326 >>> np.insert(b, slice(2, 4), [5, 6]) 

5327 array([1, 1, 5, ..., 2, 3, 3]) 

5328 

5329 >>> np.insert(b, [2, 2], [7.13, False]) # type casting 

5330 array([1, 1, 7, ..., 2, 3, 3]) 

5331 

5332 >>> x = np.arange(8).reshape(2, 4) 

5333 >>> idx = (1, 3) 

5334 >>> np.insert(x, idx, 999, axis=1) 

5335 array([[ 0, 999, 1, 2, 999, 3], 

5336 [ 4, 999, 5, 6, 999, 7]]) 

5337 

5338 """ 

5339 wrap = None 

5340 if type(arr) is not ndarray: 

5341 try: 

5342 wrap = arr.__array_wrap__ 

5343 except AttributeError: 

5344 pass 

5345 

5346 arr = asarray(arr) 

5347 ndim = arr.ndim 

5348 arrorder = 'F' if arr.flags.fnc else 'C' 

5349 if axis is None: 

5350 if ndim != 1: 

5351 arr = arr.ravel() 

5352 # needed for np.matrix, which is still not 1d after being ravelled 

5353 ndim = arr.ndim 

5354 axis = ndim - 1 

5355 else: 

5356 axis = normalize_axis_index(axis, ndim) 

5357 slobj = [slice(None)]*ndim 

5358 N = arr.shape[axis] 

5359 newshape = list(arr.shape) 

5360 

5361 if isinstance(obj, slice): 

5362 # turn it into a range object 

5363 indices = arange(*obj.indices(N), dtype=intp) 

5364 else: 

5365 # need to copy obj, because indices will be changed in-place 

5366 indices = np.array(obj) 

5367 if indices.dtype == bool: 

5368 # See also delete 

5369 # 2012-10-11, NumPy 1.8 

5370 warnings.warn( 

5371 "in the future insert will treat boolean arrays and " 

5372 "array-likes as a boolean index instead of casting it to " 

5373 "integer", FutureWarning, stacklevel=3) 

5374 indices = indices.astype(intp) 

5375 # Code after warning period: 

5376 #if obj.ndim != 1: 

5377 # raise ValueError('boolean array argument obj to insert ' 

5378 # 'must be one dimensional') 

5379 #indices = np.flatnonzero(obj) 

5380 elif indices.ndim > 1: 

5381 raise ValueError( 

5382 "index array argument obj to insert must be one dimensional " 

5383 "or scalar") 

5384 if indices.size == 1: 

5385 index = indices.item() 

5386 if index < -N or index > N: 

5387 raise IndexError(f"index {obj} is out of bounds for axis {axis} " 

5388 f"with size {N}") 

5389 if (index < 0): 

5390 index += N 

5391 

5392 # There are some object array corner cases here, but we cannot avoid 

5393 # that: 

5394 values = array(values, copy=False, ndmin=arr.ndim, dtype=arr.dtype) 

5395 if indices.ndim == 0: 

5396 # broadcasting is very different here, since a[:,0,:] = ... behaves 

5397 # very different from a[:,[0],:] = ...! This changes values so that 

5398 # it works likes the second case. (here a[:,0:1,:]) 

5399 values = np.moveaxis(values, 0, axis) 

5400 numnew = values.shape[axis] 

5401 newshape[axis] += numnew 

5402 new = empty(newshape, arr.dtype, arrorder) 

5403 slobj[axis] = slice(None, index) 

5404 new[tuple(slobj)] = arr[tuple(slobj)] 

5405 slobj[axis] = slice(index, index+numnew) 

5406 new[tuple(slobj)] = values 

5407 slobj[axis] = slice(index+numnew, None) 

5408 slobj2 = [slice(None)] * ndim 

5409 slobj2[axis] = slice(index, None) 

5410 new[tuple(slobj)] = arr[tuple(slobj2)] 

5411 if wrap: 

5412 return wrap(new) 

5413 return new 

5414 elif indices.size == 0 and not isinstance(obj, np.ndarray): 

5415 # Can safely cast the empty list to intp 

5416 indices = indices.astype(intp) 

5417 

5418 indices[indices < 0] += N 

5419 

5420 numnew = len(indices) 

5421 order = indices.argsort(kind='mergesort') # stable sort 

5422 indices[order] += np.arange(numnew) 

5423 

5424 newshape[axis] += numnew 

5425 old_mask = ones(newshape[axis], dtype=bool) 

5426 old_mask[indices] = False 

5427 

5428 new = empty(newshape, arr.dtype, arrorder) 

5429 slobj2 = [slice(None)]*ndim 

5430 slobj[axis] = indices 

5431 slobj2[axis] = old_mask 

5432 new[tuple(slobj)] = values 

5433 new[tuple(slobj2)] = arr 

5434 

5435 if wrap: 

5436 return wrap(new) 

5437 return new 

5438 

5439 

5440def _append_dispatcher(arr, values, axis=None): 

5441 return (arr, values) 

5442 

5443 

5444@array_function_dispatch(_append_dispatcher) 

5445def append(arr, values, axis=None): 

5446 """ 

5447 Append values to the end of an array. 

5448 

5449 Parameters 

5450 ---------- 

5451 arr : array_like 

5452 Values are appended to a copy of this array. 

5453 values : array_like 

5454 These values are appended to a copy of `arr`. It must be of the 

5455 correct shape (the same shape as `arr`, excluding `axis`). If 

5456 `axis` is not specified, `values` can be any shape and will be 

5457 flattened before use. 

5458 axis : int, optional 

5459 The axis along which `values` are appended. If `axis` is not 

5460 given, both `arr` and `values` are flattened before use. 

5461 

5462 Returns 

5463 ------- 

5464 append : ndarray 

5465 A copy of `arr` with `values` appended to `axis`. Note that 

5466 `append` does not occur in-place: a new array is allocated and 

5467 filled. If `axis` is None, `out` is a flattened array. 

5468 

5469 See Also 

5470 -------- 

5471 insert : Insert elements into an array. 

5472 delete : Delete elements from an array. 

5473 

5474 Examples 

5475 -------- 

5476 >>> np.append([1, 2, 3], [[4, 5, 6], [7, 8, 9]]) 

5477 array([1, 2, 3, ..., 7, 8, 9]) 

5478 

5479 When `axis` is specified, `values` must have the correct shape. 

5480 

5481 >>> np.append([[1, 2, 3], [4, 5, 6]], [[7, 8, 9]], axis=0) 

5482 array([[1, 2, 3], 

5483 [4, 5, 6], 

5484 [7, 8, 9]]) 

5485 >>> np.append([[1, 2, 3], [4, 5, 6]], [7, 8, 9], axis=0) 

5486 Traceback (most recent call last): 

5487 ... 

5488 ValueError: all the input arrays must have same number of dimensions, but 

5489 the array at index 0 has 2 dimension(s) and the array at index 1 has 1 

5490 dimension(s) 

5491 

5492 """ 

5493 arr = asanyarray(arr) 

5494 if axis is None: 

5495 if arr.ndim != 1: 

5496 arr = arr.ravel() 

5497 values = ravel(values) 

5498 axis = arr.ndim-1 

5499 return concatenate((arr, values), axis=axis) 

5500 

5501 

5502def _digitize_dispatcher(x, bins, right=None): 

5503 return (x, bins) 

5504 

5505 

5506@array_function_dispatch(_digitize_dispatcher) 

5507def digitize(x, bins, right=False): 

5508 """ 

5509 Return the indices of the bins to which each value in input array belongs. 

5510 

5511 ========= ============= ============================ 

5512 `right` order of bins returned index `i` satisfies 

5513 ========= ============= ============================ 

5514 ``False`` increasing ``bins[i-1] <= x < bins[i]`` 

5515 ``True`` increasing ``bins[i-1] < x <= bins[i]`` 

5516 ``False`` decreasing ``bins[i-1] > x >= bins[i]`` 

5517 ``True`` decreasing ``bins[i-1] >= x > bins[i]`` 

5518 ========= ============= ============================ 

5519 

5520 If values in `x` are beyond the bounds of `bins`, 0 or ``len(bins)`` is 

5521 returned as appropriate. 

5522 

5523 Parameters 

5524 ---------- 

5525 x : array_like 

5526 Input array to be binned. Prior to NumPy 1.10.0, this array had to 

5527 be 1-dimensional, but can now have any shape. 

5528 bins : array_like 

5529 Array of bins. It has to be 1-dimensional and monotonic. 

5530 right : bool, optional 

5531 Indicating whether the intervals include the right or the left bin 

5532 edge. Default behavior is (right==False) indicating that the interval 

5533 does not include the right edge. The left bin end is open in this 

5534 case, i.e., bins[i-1] <= x < bins[i] is the default behavior for 

5535 monotonically increasing bins. 

5536 

5537 Returns 

5538 ------- 

5539 indices : ndarray of ints 

5540 Output array of indices, of same shape as `x`. 

5541 

5542 Raises 

5543 ------ 

5544 ValueError 

5545 If `bins` is not monotonic. 

5546 TypeError 

5547 If the type of the input is complex. 

5548 

5549 See Also 

5550 -------- 

5551 bincount, histogram, unique, searchsorted 

5552 

5553 Notes 

5554 ----- 

5555 If values in `x` are such that they fall outside the bin range, 

5556 attempting to index `bins` with the indices that `digitize` returns 

5557 will result in an IndexError. 

5558 

5559 .. versionadded:: 1.10.0 

5560 

5561 `np.digitize` is implemented in terms of `np.searchsorted`. This means 

5562 that a binary search is used to bin the values, which scales much better 

5563 for larger number of bins than the previous linear search. It also removes 

5564 the requirement for the input array to be 1-dimensional. 

5565 

5566 For monotonically _increasing_ `bins`, the following are equivalent:: 

5567 

5568 np.digitize(x, bins, right=True) 

5569 np.searchsorted(bins, x, side='left') 

5570 

5571 Note that as the order of the arguments are reversed, the side must be too. 

5572 The `searchsorted` call is marginally faster, as it does not do any 

5573 monotonicity checks. Perhaps more importantly, it supports all dtypes. 

5574 

5575 Examples 

5576 -------- 

5577 >>> x = np.array([0.2, 6.4, 3.0, 1.6]) 

5578 >>> bins = np.array([0.0, 1.0, 2.5, 4.0, 10.0]) 

5579 >>> inds = np.digitize(x, bins) 

5580 >>> inds 

5581 array([1, 4, 3, 2]) 

5582 >>> for n in range(x.size): 

5583 ... print(bins[inds[n]-1], "<=", x[n], "<", bins[inds[n]]) 

5584 ... 

5585 0.0 <= 0.2 < 1.0 

5586 4.0 <= 6.4 < 10.0 

5587 2.5 <= 3.0 < 4.0 

5588 1.0 <= 1.6 < 2.5 

5589 

5590 >>> x = np.array([1.2, 10.0, 12.4, 15.5, 20.]) 

5591 >>> bins = np.array([0, 5, 10, 15, 20]) 

5592 >>> np.digitize(x,bins,right=True) 

5593 array([1, 2, 3, 4, 4]) 

5594 >>> np.digitize(x,bins,right=False) 

5595 array([1, 3, 3, 4, 5]) 

5596 """ 

5597 x = _nx.asarray(x) 

5598 bins = _nx.asarray(bins) 

5599 

5600 # here for compatibility, searchsorted below is happy to take this 

5601 if np.issubdtype(x.dtype, _nx.complexfloating): 

5602 raise TypeError("x may not be complex") 

5603 

5604 mono = _monotonicity(bins) 

5605 if mono == 0: 

5606 raise ValueError("bins must be monotonically increasing or decreasing") 

5607 

5608 # this is backwards because the arguments below are swapped 

5609 side = 'left' if right else 'right' 

5610 if mono == -1: 

5611 # reverse the bins, and invert the results 

5612 return len(bins) - _nx.searchsorted(bins[::-1], x, side=side) 

5613 else: 

5614 return _nx.searchsorted(bins, x, side=side)