codekingpro/portable-devtools
114k
1"""
2Functions that ignore NaN.
3
4Functions
5---------
6
7- `nanmin` -- minimum non-NaN value
8- `nanmax` -- maximum non-NaN value
9- `nanargmin` -- index of minimum non-NaN value
10- `nanargmax` -- index of maximum non-NaN value
11- `nansum` -- sum of non-NaN values
12- `nanprod` -- product of non-NaN values
13- `nancumsum` -- cumulative sum of non-NaN values
14- `nancumprod` -- cumulative product of non-NaN values
15- `nanmean` -- mean of non-NaN values
16- `nanvar` -- variance of non-NaN values
17- `nanstd` -- standard deviation of non-NaN values
18- `nanmedian` -- median of non-NaN values
19- `nanquantile` -- qth quantile of non-NaN values
20- `nanpercentile` -- qth percentile of non-NaN values
21
22"""
23import functools
24import warnings
25
26import numpy as np
27import numpy._core.numeric as _nx
28from numpy._core import overrides
29from numpy.lib import _function_base_impl as fnb
30from numpy.lib._function_base_impl import _weights_are_valid
31
32array_function_dispatch = functools.partial(
33 overrides.array_function_dispatch, module='numpy')
34
35
36__all__ = [
37 'nansum', 'nanmax', 'nanmin', 'nanargmax', 'nanargmin', 'nanmean',
38 'nanmedian', 'nanpercentile', 'nanvar', 'nanstd', 'nanprod',
39 'nancumsum', 'nancumprod', 'nanquantile'
40 ]
41
42
43def _nan_mask(a, out=None):
44 """
45 Parameters
46 ----------
47 a : array-like
48 Input array with at least 1 dimension.
49 out : ndarray, optional
50 Alternate output array in which to place the result. The default
51 is ``None``; if provided, it must have the same shape as the
52 expected output and will prevent the allocation of a new array.
53
54 Returns
55 -------
56 y : bool ndarray or True
57 A bool array where ``np.nan`` positions are marked with ``False``
58 and other positions are marked with ``True``. If the type of ``a``
59 is such that it can't possibly contain ``np.nan``, returns ``True``.
60 """
61 # we assume that a is an array for this private function
62
63 if a.dtype.kind not in 'fc':
64 return True
65
66 y = np.isnan(a, out=out)
67 y = np.invert(y, out=y)
68 return y
69
70def _replace_nan(a, val):
71 """
72 If `a` is of inexact type, make a copy of `a`, replace NaNs with
73 the `val` value, and return the copy together with a boolean mask
74 marking the locations where NaNs were present. If `a` is not of
75 inexact type, do nothing and return `a` together with a mask of None.
76
77 Note that scalars will end up as array scalars, which is important
78 for using the result as the value of the out argument in some
79 operations.
80
81 Parameters
82 ----------
83 a : array-like
84 Input array.
85 val : float
86 NaN values are set to val before doing the operation.
87
88 Returns
89 -------
90 y : ndarray
91 If `a` is of inexact type, return a copy of `a` with the NaNs
92 replaced by the fill value, otherwise return `a`.
93 mask: {bool, None}
94 If `a` is of inexact type, return a boolean mask marking locations of
95 NaNs, otherwise return None.
96
97 """
98 a = np.asanyarray(a)
99
100 if a.dtype == np.object_:
101 # object arrays do not support `isnan` (gh-9009), so make a guess
102 mask = np.not_equal(a, a, dtype=bool)
103 elif issubclass(a.dtype.type, np.inexact):
104 mask = np.isnan(a)
105 else:
106 mask = None
107
108 if mask is not None:
109 a = np.array(a, subok=True, copy=True)
110 np.copyto(a, val, where=mask)
111
112 return a, mask
113
114
115def _copyto(a, val, mask):
116 """
117 Replace values in `a` with NaN where `mask` is True. This differs from
118 copyto in that it will deal with the case where `a` is a numpy scalar.
119
120 Parameters
121 ----------
122 a : ndarray or numpy scalar
123 Array or numpy scalar some of whose values are to be replaced
124 by val.
125 val : numpy scalar
126 Value used a replacement.
127 mask : ndarray, scalar
128 Boolean array. Where True the corresponding element of `a` is
129 replaced by `val`. Broadcasts.
130
131 Returns
132 -------
133 res : ndarray, scalar
134 Array with elements replaced or scalar `val`.
135
136 """
137 if isinstance(a, np.ndarray):
138 np.copyto(a, val, where=mask, casting='unsafe')
139 else:
140 a = a.dtype.type(val)
141 return a
142
143
144def _remove_nan_1d(arr1d, second_arr1d=None, overwrite_input=False):
145 """
146 Equivalent to arr1d[~arr1d.isnan()], but in a different order
147
148 Presumably faster as it incurs fewer copies
149
150 Parameters
151 ----------
152 arr1d : ndarray
153 Array to remove nans from
154 second_arr1d : ndarray or None
155 A second array which will have the same positions removed as arr1d.
156 overwrite_input : bool
157 True if `arr1d` can be modified in place
158
159 Returns
160 -------
161 res : ndarray
162 Array with nan elements removed
163 second_res : ndarray or None
164 Second array with nan element positions of first array removed.
165 overwrite_input : bool
166 True if `res` can be modified in place, given the constraint on the
167 input
168 """
169 if arr1d.dtype == object:
170 # object arrays do not support `isnan` (gh-9009), so make a guess
171 c = np.not_equal(arr1d, arr1d, dtype=bool)
172 else:
173 c = np.isnan(arr1d)
174
175 s = np.nonzero(c)[0]
176 if s.size == arr1d.size:
177 warnings.warn("All-NaN slice encountered", RuntimeWarning,
178 stacklevel=6)
179 if second_arr1d is None:
180 return arr1d[:0], None, True
181 else:
182 return arr1d[:0], second_arr1d[:0], True
183 elif s.size == 0:
184 return arr1d, second_arr1d, overwrite_input
185 else:
186 if not overwrite_input:
187 arr1d = arr1d.copy()
188 # select non-nans at end of array
189 enonan = arr1d[-s.size:][~c[-s.size:]]
190 # fill nans in beginning of array with non-nans of end
191 arr1d[s[:enonan.size]] = enonan
192
193 if second_arr1d is None:
194 return arr1d[:-s.size], None, True
195 else:
196 if not overwrite_input:
197 second_arr1d = second_arr1d.copy()
198 enonan = second_arr1d[-s.size:][~c[-s.size:]]
199 second_arr1d[s[:enonan.size]] = enonan
200
201 return arr1d[:-s.size], second_arr1d[:-s.size], True
202
203
204def _divide_by_count(a, b, out=None):
205 """
206 Compute a/b ignoring invalid results. If `a` is an array the division
207 is done in place. If `a` is a scalar, then its type is preserved in the
208 output. If out is None, then a is used instead so that the division
209 is in place. Note that this is only called with `a` an inexact type.
210
211 Parameters
212 ----------
213 a : {ndarray, numpy scalar}
214 Numerator. Expected to be of inexact type but not checked.
215 b : {ndarray, numpy scalar}
216 Denominator.
217 out : ndarray, optional
218 Alternate output array in which to place the result. The default
219 is ``None``; if provided, it must have the same shape as the
220 expected output, but the type will be cast if necessary.
221
222 Returns
223 -------
224 ret : {ndarray, numpy scalar}
225 The return value is a/b. If `a` was an ndarray the division is done
226 in place. If `a` is a numpy scalar, the division preserves its type.
227
228 """
229 with np.errstate(invalid='ignore', divide='ignore'):
230 if isinstance(a, np.ndarray):
231 if out is None:
232 return np.divide(a, b, out=a, casting='unsafe')
233 else:
234 return np.divide(a, b, out=out, casting='unsafe')
235 elif out is None:
236 # Precaution against reduced object arrays
237 try:
238 return a.dtype.type(a / b)
239 except AttributeError:
240 return a / b
241 else:
242 # This is questionable, but currently a numpy scalar can
243 # be output to a zero dimensional array.
244 return np.divide(a, b, out=out, casting='unsafe')
245
246
247def _nanmin_dispatcher(a, axis=None, out=None, keepdims=None,
248 initial=None, where=None):
249 return (a, out)
250
251
252@array_function_dispatch(_nanmin_dispatcher)
253def nanmin(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue,
254 where=np._NoValue):
255 """
256 Return minimum of an array or minimum along an axis, ignoring any NaNs.
257 When all-NaN slices are encountered a ``RuntimeWarning`` is raised and
258 Nan is returned for that slice.
259
260 Parameters
261 ----------
262 a : array_like
263 Array containing numbers whose minimum is desired. If `a` is not an
264 array, a conversion is attempted.
265 axis : {int, tuple of int, None}, optional
266 Axis or axes along which the minimum is computed. The default is to compute
267 the minimum of the flattened array.
268 out : ndarray, optional
269 Alternate output array in which to place the result. The default
270 is ``None``; if provided, it must have the same shape as the
271 expected output, but the type will be cast if necessary. See
272 :ref:`ufuncs-output-type` for more details.
273 keepdims : bool, optional
274 If this is set to True, the axes which are reduced are left
275 in the result as dimensions with size one. With this option,
276 the result will broadcast correctly against the original `a`.
277
278 If the value is anything but the default, then
279 `keepdims` will be passed through to the `min` method
280 of sub-classes of `ndarray`. If the sub-classes methods
281 does not implement `keepdims` any exceptions will be raised.
282 initial : scalar, optional
283 The maximum value of an output element. Must be present to allow
284 computation on empty slice. See `~numpy.ufunc.reduce` for details.
285
286 .. versionadded:: 1.22.0
287 where : array_like of bool, optional
288 Elements to compare for the minimum. See `~numpy.ufunc.reduce`
289 for details.
290
291 .. versionadded:: 1.22.0
292
293 Returns
294 -------
295 nanmin : ndarray
296 An array with the same shape as `a`, with the specified axis
297 removed. If `a` is a 0-d array, or if axis is None, an ndarray
298 scalar is returned. The same dtype as `a` is returned.
299
300 See Also
301 --------
302 nanmax :
303 The maximum value of an array along a given axis, ignoring any NaNs.
304 amin :
305 The minimum value of an array along a given axis, propagating any NaNs.
306 fmin :
307 Element-wise minimum of two arrays, ignoring any NaNs.
308 minimum :
309 Element-wise minimum of two arrays, propagating any NaNs.
310 isnan :
311 Shows which elements are Not a Number (NaN).
312 isfinite:
313 Shows which elements are neither NaN nor infinity.
314
315 amax, fmax, maximum
316
317 Notes
318 -----
319 NumPy uses the IEEE Standard for Binary Floating-Point for Arithmetic
320 (IEEE 754). This means that Not a Number is not equivalent to infinity.
321 Positive infinity is treated as a very large number and negative
322 infinity is treated as a very small (i.e. negative) number.
323
324 If the input has a integer type the function is equivalent to np.min.
325
326 Examples
327 --------
328 >>> import numpy as np
329 >>> a = np.array([[1, 2], [3, np.nan]])
330 >>> np.nanmin(a)
331 1.0
332 >>> np.nanmin(a, axis=0)
333 array([1., 2.])
334 >>> np.nanmin(a, axis=1)
335 array([1., 3.])
336
337 When positive infinity and negative infinity are present:
338
339 >>> np.nanmin([1, 2, np.nan, np.inf])
340 1.0
341 >>> np.nanmin([1, 2, np.nan, -np.inf])
342 -inf
343
344 """
345 kwargs = {}
346 if keepdims is not np._NoValue:
347 kwargs['keepdims'] = keepdims
348 if initial is not np._NoValue:
349 kwargs['initial'] = initial
350 if where is not np._NoValue:
351 kwargs['where'] = where
352
353 if (type(a) is np.ndarray or type(a) is np.memmap) and a.dtype != np.object_:
354 # Fast, but not safe for subclasses of ndarray, or object arrays,
355 # which do not implement isnan (gh-9009), or fmin correctly (gh-8975)
356 res = np.fmin.reduce(a, axis=axis, out=out, **kwargs)
357 if np.isnan(res).any():
358 warnings.warn("All-NaN slice encountered", RuntimeWarning,
359 stacklevel=2)
360 else:
361 # Slow, but safe for subclasses of ndarray
362 a, mask = _replace_nan(a, +np.inf)
363 res = np.amin(a, axis=axis, out=out, **kwargs)
364 if mask is None:
365 return res
366
367 # Check for all-NaN axis
368 kwargs.pop("initial", None)
369 mask = np.all(mask, axis=axis, **kwargs)
370 if np.any(mask):
371 res = _copyto(res, np.nan, mask)
372 warnings.warn("All-NaN axis encountered", RuntimeWarning,
373 stacklevel=2)
374 return res
375
376
377def _nanmax_dispatcher(a, axis=None, out=None, keepdims=None,
378 initial=None, where=None):
379 return (a, out)
380
381
382@array_function_dispatch(_nanmax_dispatcher)
383def nanmax(a, axis=None, out=None, keepdims=np._NoValue, initial=np._NoValue,
384 where=np._NoValue):
385 """
386 Return the maximum of an array or maximum along an axis, ignoring any
387 NaNs. When all-NaN slices are encountered a ``RuntimeWarning`` is
388 raised and NaN is returned for that slice.
389
390 Parameters
391 ----------
392 a : array_like
393 Array containing numbers whose maximum is desired. If `a` is not an
394 array, a conversion is attempted.
395 axis : {int, tuple of int, None}, optional
396 Axis or axes along which the maximum is computed. The default is to compute
397 the maximum of the flattened array.
398 out : ndarray, optional
399 Alternate output array in which to place the result. The default
400 is ``None``; if provided, it must have the same shape as the
401 expected output, but the type will be cast if necessary. See
402 :ref:`ufuncs-output-type` for more details.
403 keepdims : bool, optional
404 If this is set to True, the axes which are reduced are left
405 in the result as dimensions with size one. With this option,
406 the result will broadcast correctly against the original `a`.
407 If the value is anything but the default, then
408 `keepdims` will be passed through to the `max` method
409 of sub-classes of `ndarray`. If the sub-classes methods
410 does not implement `keepdims` any exceptions will be raised.
411 initial : scalar, optional
412 The minimum value of an output element. Must be present to allow
413 computation on empty slice. See `~numpy.ufunc.reduce` for details.
414
415 .. versionadded:: 1.22.0
416 where : array_like of bool, optional
417 Elements to compare for the maximum. See `~numpy.ufunc.reduce`
418 for details.
419
420 .. versionadded:: 1.22.0
421
422 Returns
423 -------
424 nanmax : ndarray
425 An array with the same shape as `a`, with the specified axis removed.
426 If `a` is a 0-d array, or if axis is None, an ndarray scalar is
427 returned. The same dtype as `a` is returned.
428
429 See Also
430 --------
431 nanmin :
432 The minimum value of an array along a given axis, ignoring any NaNs.
433 amax :
434 The maximum value of an array along a given axis, propagating any NaNs.
435 fmax :
436 Element-wise maximum of two arrays, ignoring any NaNs.
437 maximum :
438 Element-wise maximum of two arrays, propagating any NaNs.
439 isnan :
440 Shows which elements are Not a Number (NaN).
441 isfinite:
442 Shows which elements are neither NaN nor infinity.
443
444 amin, fmin, minimum
445
446 Notes
447 -----
448 NumPy uses the IEEE Standard for Binary Floating-Point for Arithmetic
449 (IEEE 754). This means that Not a Number is not equivalent to infinity.
450 Positive infinity is treated as a very large number and negative
451 infinity is treated as a very small (i.e. negative) number.
452
453 If the input has a integer type the function is equivalent to np.max.
454
455 Examples
456 --------
457 >>> import numpy as np
458 >>> a = np.array([[1, 2], [3, np.nan]])
459 >>> np.nanmax(a)
460 3.0
461 >>> np.nanmax(a, axis=0)
462 array([3., 2.])
463 >>> np.nanmax(a, axis=1)
464 array([2., 3.])
465
466 When positive infinity and negative infinity are present:
467
468 >>> np.nanmax([1, 2, np.nan, -np.inf])
469 2.0
470 >>> np.nanmax([1, 2, np.nan, np.inf])
471 inf
472
473 """
474 kwargs = {}
475 if keepdims is not np._NoValue:
476 kwargs['keepdims'] = keepdims
477 if initial is not np._NoValue:
478 kwargs['initial'] = initial
479 if where is not np._NoValue:
480 kwargs['where'] = where
481
482 if (type(a) is np.ndarray or type(a) is np.memmap) and a.dtype != np.object_:
483 # Fast, but not safe for subclasses of ndarray, or object arrays,
484 # which do not implement isnan (gh-9009), or fmax correctly (gh-8975)
485 res = np.fmax.reduce(a, axis=axis, out=out, **kwargs)
486 if np.isnan(res).any():
487 warnings.warn("All-NaN slice encountered", RuntimeWarning,
488 stacklevel=2)
489 else:
490 # Slow, but safe for subclasses of ndarray
491 a, mask = _replace_nan(a, -np.inf)
492 res = np.amax(a, axis=axis, out=out, **kwargs)
493 if mask is None:
494 return res
495
496 # Check for all-NaN axis
497 kwargs.pop("initial", None)
498 mask = np.all(mask, axis=axis, **kwargs)
499 if np.any(mask):
500 res = _copyto(res, np.nan, mask)
501 warnings.warn("All-NaN axis encountered", RuntimeWarning,
502 stacklevel=2)
503 return res
504
505
506def _nanargmin_dispatcher(a, axis=None, out=None, *, keepdims=None):
507 return (a,)
508
509
510@array_function_dispatch(_nanargmin_dispatcher)
511def nanargmin(a, axis=None, out=None, *, keepdims=np._NoValue):
512 """
513 Return the indices of the minimum values in the specified axis ignoring
514 NaNs. For all-NaN slices ``ValueError`` is raised. Warning: the results
515 cannot be trusted if a slice contains only NaNs and Infs.
516
517 Parameters
518 ----------
519 a : array_like
520 Input data.
521 axis : int, optional
522 Axis along which to operate. By default flattened input is used.
523 out : array, optional
524 If provided, the result will be inserted into this array. It should
525 be of the appropriate shape and dtype.
526
527 .. versionadded:: 1.22.0
528 keepdims : bool, optional
529 If this is set to True, the axes which are reduced are left
530 in the result as dimensions with size one. With this option,
531 the result will broadcast correctly against the array.
532
533 .. versionadded:: 1.22.0
534
535 Returns
536 -------
537 index_array : ndarray
538 An array of indices or a single index value.
539
540 See Also
541 --------
542 argmin, nanargmax
543
544 Examples
545 --------
546 >>> import numpy as np
547 >>> a = np.array([[np.nan, 4], [2, 3]])
548 >>> np.argmin(a)
549 0
550 >>> np.nanargmin(a)
551 2
552 >>> np.nanargmin(a, axis=0)
553 array([1, 1])
554 >>> np.nanargmin(a, axis=1)
555 array([1, 0])
556
557 """
558 a, mask = _replace_nan(a, np.inf)
559 if mask is not None and mask.size:
560 mask = np.all(mask, axis=axis)
561 if np.any(mask):
562 raise ValueError("All-NaN slice encountered")
563 res = np.argmin(a, axis=axis, out=out, keepdims=keepdims)
564 return res
565
566
567def _nanargmax_dispatcher(a, axis=None, out=None, *, keepdims=None):
568 return (a,)
569
570
571@array_function_dispatch(_nanargmax_dispatcher)
572def nanargmax(a, axis=None, out=None, *, keepdims=np._NoValue):
573 """
574 Return the indices of the maximum values in the specified axis ignoring
575 NaNs. For all-NaN slices ``ValueError`` is raised. Warning: the
576 results cannot be trusted if a slice contains only NaNs and -Infs.
577
578
579 Parameters
580 ----------
581 a : array_like
582 Input data.
583 axis : int, optional
584 Axis along which to operate. By default flattened input is used.
585 out : array, optional
586 If provided, the result will be inserted into this array. It should
587 be of the appropriate shape and dtype.
588
589 .. versionadded:: 1.22.0
590 keepdims : bool, optional
591 If this is set to True, the axes which are reduced are left
592 in the result as dimensions with size one. With this option,
593 the result will broadcast correctly against the array.
594
595 .. versionadded:: 1.22.0
596
597 Returns
598 -------
599 index_array : ndarray
600 An array of indices or a single index value.
601
602 See Also
603 --------
604 argmax, nanargmin
605
606 Examples
607 --------
608 >>> import numpy as np
609 >>> a = np.array([[np.nan, 4], [2, 3]])
610 >>> np.argmax(a)
611 0
612 >>> np.nanargmax(a)
613 1
614 >>> np.nanargmax(a, axis=0)
615 array([1, 0])
616 >>> np.nanargmax(a, axis=1)
617 array([1, 1])
618
619 """
620 a, mask = _replace_nan(a, -np.inf)
621 if mask is not None and mask.size:
622 mask = np.all(mask, axis=axis)
623 if np.any(mask):
624 raise ValueError("All-NaN slice encountered")
625 res = np.argmax(a, axis=axis, out=out, keepdims=keepdims)
626 return res
627
628
629def _nansum_dispatcher(a, axis=None, dtype=None, out=None, keepdims=None,
630 initial=None, where=None):
631 return (a, out)
632
633
634@array_function_dispatch(_nansum_dispatcher)
635def nansum(a, axis=None, dtype=None, out=None, keepdims=np._NoValue,
636 initial=np._NoValue, where=np._NoValue):
637 """
638 Return the sum of array elements over a given axis treating Not a
639 Numbers (NaNs) as zero.
640
641 In NumPy versions <= 1.9.0 Nan is returned for slices that are all-NaN or
642 empty. In later versions zero is returned.
643
644 Parameters
645 ----------
646 a : array_like
647 Array containing numbers whose sum is desired. If `a` is not an
648 array, a conversion is attempted.
649 axis : {int, tuple of int, None}, optional
650 Axis or axes along which the sum is computed. The default is to compute the
651 sum of the flattened array.
652 dtype : data-type, optional
653 The type of the returned array and of the accumulator in which the
654 elements are summed. By default, the dtype of `a` is used. An
655 exception is when `a` has an integer type with less precision than
656 the platform (u)intp. In that case, the default will be either
657 (u)int32 or (u)int64 depending on whether the platform is 32 or 64
658 bits. For inexact inputs, dtype must be inexact.
659 out : ndarray, optional
660 Alternate output array in which to place the result. The default
661 is ``None``. If provided, it must have the same shape as the
662 expected output, but the type will be cast if necessary. See
663 :ref:`ufuncs-output-type` for more details. The casting of NaN to integer
664 can yield unexpected results.
665 keepdims : bool, optional
666 If this is set to True, the axes which are reduced are left
667 in the result as dimensions with size one. With this option,
668 the result will broadcast correctly against the original `a`.
669
670 If the value is anything but the default, then
671 `keepdims` will be passed through to the `mean` or `sum` methods
672 of sub-classes of `ndarray`. If the sub-classes methods
673 does not implement `keepdims` any exceptions will be raised.
674 initial : scalar, optional
675 Starting value for the sum. See `~numpy.ufunc.reduce` for details.
676
677 .. versionadded:: 1.22.0
678 where : array_like of bool, optional
679 Elements to include in the sum. See `~numpy.ufunc.reduce` for details.
680
681 .. versionadded:: 1.22.0
682
683 Returns
684 -------
685 nansum : ndarray.
686 A new array holding the result is returned unless `out` is
687 specified, in which it is returned. The result has the same
688 size as `a`, and the same shape as `a` if `axis` is not None
689 or `a` is a 1-d array.
690
691 See Also
692 --------
693 numpy.sum : Sum across array propagating NaNs.
694 isnan : Show which elements are NaN.
695 isfinite : Show which elements are not NaN or +/-inf.
696
697 Notes
698 -----
699 If both positive and negative infinity are present, the sum will be Not
700 A Number (NaN).
701
702 Examples
703 --------
704 >>> import numpy as np
705 >>> np.nansum(1)
706 1
707 >>> np.nansum([1])
708 1
709 >>> np.nansum([1, np.nan])
710 1.0
711 >>> a = np.array([[1, 1], [1, np.nan]])
712 >>> np.nansum(a)
713 3.0
714 >>> np.nansum(a, axis=0)
715 array([2., 1.])
716 >>> np.nansum([1, np.nan, np.inf])
717 inf
718 >>> np.nansum([1, np.nan, -np.inf])
719 -inf
720 >>> with np.errstate(invalid="ignore"):
721 ... np.nansum([1, np.nan, np.inf, -np.inf]) # both +/- infinity present
722 np.float64(nan)
723
724 """
725 a, mask = _replace_nan(a, 0)
726 return np.sum(a, axis=axis, dtype=dtype, out=out, keepdims=keepdims,
727 initial=initial, where=where)
728
729
730def _nanprod_dispatcher(a, axis=None, dtype=None, out=None, keepdims=None,
731 initial=None, where=None):
732 return (a, out)
733
734
735@array_function_dispatch(_nanprod_dispatcher)
736def nanprod(a, axis=None, dtype=None, out=None, keepdims=np._NoValue,
737 initial=np._NoValue, where=np._NoValue):
738 """
739 Return the product of array elements over a given axis treating Not a
740 Numbers (NaNs) as ones.
741
742 One is returned for slices that are all-NaN or empty.
743
744 Parameters
745 ----------
746 a : array_like
747 Array containing numbers whose product is desired. If `a` is not an
748 array, a conversion is attempted.
749 axis : {int, tuple of int, None}, optional
750 Axis or axes along which the product is computed. The default is to compute
751 the product of the flattened array.
752 dtype : data-type, optional
753 The type of the returned array and of the accumulator in which the
754 elements are summed. By default, the dtype of `a` is used. An
755 exception is when `a` has an integer type with less precision than
756 the platform (u)intp. In that case, the default will be either
757 (u)int32 or (u)int64 depending on whether the platform is 32 or 64
758 bits. For inexact inputs, dtype must be inexact.
759 out : ndarray, optional
760 Alternate output array in which to place the result. The default
761 is ``None``. If provided, it must have the same shape as the
762 expected output, but the type will be cast if necessary. See
763 :ref:`ufuncs-output-type` for more details. The casting of NaN to integer
764 can yield unexpected results.
765 keepdims : bool, optional
766 If True, the axes which are reduced are left in the result as
767 dimensions with size one. With this option, the result will
768 broadcast correctly against the original `arr`.
769 initial : scalar, optional
770 The starting value for this product. See `~numpy.ufunc.reduce`
771 for details.
772
773 .. versionadded:: 1.22.0
774 where : array_like of bool, optional
775 Elements to include in the product. See `~numpy.ufunc.reduce`
776 for details.
777
778 .. versionadded:: 1.22.0
779
780 Returns
781 -------
782 nanprod : ndarray
783 A new array holding the result is returned unless `out` is
784 specified, in which case it is returned.
785
786 See Also
787 --------
788 numpy.prod : Product across array propagating NaNs.
789 isnan : Show which elements are NaN.
790
791 Examples
792 --------
793 >>> import numpy as np
794 >>> np.nanprod(1)
795 1
796 >>> np.nanprod([1])
797 1
798 >>> np.nanprod([1, np.nan])
799 1.0
800 >>> a = np.array([[1, 2], [3, np.nan]])
801 >>> np.nanprod(a)
802 6.0
803 >>> np.nanprod(a, axis=0)
804 array([3., 2.])
805
806 """
807 a, mask = _replace_nan(a, 1)
808 return np.prod(a, axis=axis, dtype=dtype, out=out, keepdims=keepdims,
809 initial=initial, where=where)
810
811
812def _nancumsum_dispatcher(a, axis=None, dtype=None, out=None):
813 return (a, out)
814
815
816@array_function_dispatch(_nancumsum_dispatcher)
817def nancumsum(a, axis=None, dtype=None, out=None):
818 """
819 Return the cumulative sum of array elements over a given axis treating Not a
820 Numbers (NaNs) as zero. The cumulative sum does not change when NaNs are
821 encountered and leading NaNs are replaced by zeros.
822
823 Zeros are returned for slices that are all-NaN or empty.
824
825 Parameters
826 ----------
827 a : array_like
828 Input array.
829 axis : int, optional
830 Axis along which the cumulative sum is computed. The default
831 (None) is to compute the cumsum over the flattened array.
832 dtype : dtype, optional
833 Type of the returned array and of the accumulator in which the
834 elements are summed. If `dtype` is not specified, it defaults
835 to the dtype of `a`, unless `a` has an integer dtype with a
836 precision less than that of the default platform integer. In
837 that case, the default platform integer is used.
838 out : ndarray, optional
839 Alternative output array in which to place the result. It must
840 have the same shape and buffer length as the expected output
841 but the type will be cast if necessary. See :ref:`ufuncs-output-type` for
842 more details.
843
844 Returns
845 -------
846 nancumsum : ndarray.
847 A new array holding the result is returned unless `out` is
848 specified, in which it is returned. The result has the same
849 size as `a`, and the same shape as `a` if `axis` is not None
850 or `a` is a 1-d array.
851
852 See Also
853 --------
854 numpy.cumsum : Cumulative sum across array propagating NaNs.
855 isnan : Show which elements are NaN.
856
857 Examples
858 --------
859 >>> import numpy as np
860 >>> np.nancumsum(1)
861 array([1])
862 >>> np.nancumsum([1])
863 array([1])
864 >>> np.nancumsum([1, np.nan])
865 array([1., 1.])
866 >>> a = np.array([[1, 2], [3, np.nan]])
867 >>> np.nancumsum(a)
868 array([1., 3., 6., 6.])
869 >>> np.nancumsum(a, axis=0)
870 array([[1., 2.],
871 [4., 2.]])
872 >>> np.nancumsum(a, axis=1)
873 array([[1., 3.],
874 [3., 3.]])
875
876 """
877 a, mask = _replace_nan(a, 0)
878 return np.cumsum(a, axis=axis, dtype=dtype, out=out)
879
880
881def _nancumprod_dispatcher(a, axis=None, dtype=None, out=None):
882 return (a, out)
883
884
885@array_function_dispatch(_nancumprod_dispatcher)
886def nancumprod(a, axis=None, dtype=None, out=None):
887 """
888 Return the cumulative product of array elements over a given axis treating Not a
889 Numbers (NaNs) as one. The cumulative product does not change when NaNs are
890 encountered and leading NaNs are replaced by ones.
891
892 Ones are returned for slices that are all-NaN or empty.
893
894 Parameters
895 ----------
896 a : array_like
897 Input array.
898 axis : int, optional
899 Axis along which the cumulative product is computed. By default
900 the input is flattened.
901 dtype : dtype, optional
902 Type of the returned array, as well as of the accumulator in which
903 the elements are multiplied. If *dtype* is not specified, it
904 defaults to the dtype of `a`, unless `a` has an integer dtype with
905 a precision less than that of the default platform integer. In
906 that case, the default platform integer is used instead.
907 out : ndarray, optional
908 Alternative output array in which to place the result. It must
909 have the same shape and buffer length as the expected output
910 but the type of the resulting values will be cast if necessary.
911
912 Returns
913 -------
914 nancumprod : ndarray
915 A new array holding the result is returned unless `out` is
916 specified, in which case it is returned.
917
918 See Also
919 --------
920 numpy.cumprod : Cumulative product across array propagating NaNs.
921 isnan : Show which elements are NaN.
922
923 Examples
924 --------
925 >>> import numpy as np
926 >>> np.nancumprod(1)
927 array([1])
928 >>> np.nancumprod([1])
929 array([1])
930 >>> np.nancumprod([1, np.nan])
931 array([1., 1.])
932 >>> a = np.array([[1, 2], [3, np.nan]])
933 >>> np.nancumprod(a)
934 array([1., 2., 6., 6.])
935 >>> np.nancumprod(a, axis=0)
936 array([[1., 2.],
937 [3., 2.]])
938 >>> np.nancumprod(a, axis=1)
939 array([[1., 2.],
940 [3., 3.]])
941
942 """
943 a, mask = _replace_nan(a, 1)
944 return np.cumprod(a, axis=axis, dtype=dtype, out=out)
945
946
947def _nanmean_dispatcher(a, axis=None, dtype=None, out=None, keepdims=None,
948 *, where=None):
949 return (a, out)
950
951
952@array_function_dispatch(_nanmean_dispatcher)
953def nanmean(a, axis=None, dtype=None, out=None, keepdims=np._NoValue,
954 *, where=np._NoValue):
955 """
956 Compute the arithmetic mean along the specified axis, ignoring NaNs.
957
958 Returns the average of the array elements. The average is taken over
959 the flattened array by default, otherwise over the specified axis.
960 `float64` intermediate and return values are used for integer inputs.
961
962 For all-NaN slices, NaN is returned and a `RuntimeWarning` is raised.
963
964 Parameters
965 ----------
966 a : array_like
967 Array containing numbers whose mean is desired. If `a` is not an
968 array, a conversion is attempted.
969 axis : {int, tuple of int, None}, optional
970 Axis or axes along which the means are computed. The default is to compute
971 the mean of the flattened array.
972 dtype : data-type, optional
973 Type to use in computing the mean. For integer inputs, the default
974 is `float64`; for inexact inputs, it is the same as the input
975 dtype.
976 out : ndarray, optional
977 Alternate output array in which to place the result. The default
978 is ``None``; if provided, it must have the same shape as the
979 expected output, but the type will be cast if necessary.
980 See :ref:`ufuncs-output-type` for more details.
981 keepdims : bool, optional
982 If this is set to True, the axes which are reduced are left
983 in the result as dimensions with size one. With this option,
984 the result will broadcast correctly against the original `a`.
985
986 If the value is anything but the default, then
987 `keepdims` will be passed through to the `mean` or `sum` methods
988 of sub-classes of `ndarray`. If the sub-classes methods
989 does not implement `keepdims` any exceptions will be raised.
990 where : array_like of bool, optional
991 Elements to include in the mean. See `~numpy.ufunc.reduce` for details.
992
993 .. versionadded:: 1.22.0
994
995 Returns
996 -------
997 m : ndarray, see dtype parameter above
998 If `out=None`, returns a new array containing the mean values,
999 otherwise a reference to the output array is returned. Nan is
1000 returned for slices that contain only NaNs.
1001
1002 See Also
1003 --------
1004 average : Weighted average
1005 mean : Arithmetic mean taken while not ignoring NaNs
1006 var, nanvar
1007
1008 Notes
1009 -----
1010 The arithmetic mean is the sum of the non-NaN elements along the axis
1011 divided by the number of non-NaN elements.
1012
1013 Note that for floating-point input, the mean is computed using the same
1014 precision the input has. Depending on the input data, this can cause
1015 the results to be inaccurate, especially for `float32`. Specifying a
1016 higher-precision accumulator using the `dtype` keyword can alleviate
1017 this issue.
1018
1019 Examples
1020 --------
1021 >>> import numpy as np
1022 >>> a = np.array([[1, np.nan], [3, 4]])
1023 >>> np.nanmean(a)
1024 2.6666666666666665
1025 >>> np.nanmean(a, axis=0)
1026 array([2., 4.])
1027 >>> np.nanmean(a, axis=1)
1028 array([1., 3.5]) # may vary
1029
1030 """
1031 arr, mask = _replace_nan(a, 0)
1032 if mask is None:
1033 return np.mean(arr, axis=axis, dtype=dtype, out=out, keepdims=keepdims,
1034 where=where)
1035
1036 if dtype is not None:
1037 dtype = np.dtype(dtype)
1038 if dtype is not None and not issubclass(dtype.type, np.inexact):
1039 raise TypeError("If a is inexact, then dtype must be inexact")
1040 if out is not None and not issubclass(out.dtype.type, np.inexact):
1041 raise TypeError("If a is inexact, then out must be inexact")
1042
1043 cnt = np.sum(~mask, axis=axis, dtype=np.intp, keepdims=keepdims,
1044 where=where)
1045 tot = np.sum(arr, axis=axis, dtype=dtype, out=out, keepdims=keepdims,
1046 where=where)
1047 avg = _divide_by_count(tot, cnt, out=out)
1048
1049 isbad = (cnt == 0)
1050 if isbad.any():
1051 warnings.warn("Mean of empty slice", RuntimeWarning, stacklevel=2)
1052 # NaN is the only possible bad value, so no further
1053 # action is needed to handle bad results.
1054 return avg
1055
1056
1057def _nanmedian1d(arr1d, overwrite_input=False):
1058 """
1059 Private function for rank 1 arrays. Compute the median ignoring NaNs.
1060 See nanmedian for parameter usage
1061 """
1062 arr1d_parsed, _, overwrite_input = _remove_nan_1d(
1063 arr1d, overwrite_input=overwrite_input,
1064 )
1065
1066 if arr1d_parsed.size == 0:
1067 # Ensure that a nan-esque scalar of the appropriate type (and unit)
1068 # is returned for `timedelta64` and `complexfloating`
1069 return arr1d[-1]
1070
1071 return np.median(arr1d_parsed, overwrite_input=overwrite_input)
1072
1073
1074def _nanmedian(a, axis=None, out=None, overwrite_input=False):
1075 """
1076 Private function that doesn't support extended axis or keepdims.
1077 These methods are extended to this function using _ureduce
1078 See nanmedian for parameter usage
1079
1080 """
1081 if axis is None or a.ndim == 1:
1082 part = a.ravel()
1083 if out is None:
1084 return _nanmedian1d(part, overwrite_input)
1085 else:
1086 out[...] = _nanmedian1d(part, overwrite_input)
1087 return out
1088 else:
1089 # for small medians use sort + indexing which is still faster than
1090 # apply_along_axis
1091 # benchmarked with shuffled (50, 50, x) containing a few NaN
1092 if a.shape[axis] < 600:
1093 return _nanmedian_small(a, axis, out, overwrite_input)
1094 result = np.apply_along_axis(_nanmedian1d, axis, a, overwrite_input)
1095 if out is not None:
1096 out[...] = result
1097 return result
1098
1099
1100def _nanmedian_small(a, axis=None, out=None, overwrite_input=False):
1101 """
1102 sort + indexing median, faster for small medians along multiple
1103 dimensions due to the high overhead of apply_along_axis
1104
1105 see nanmedian for parameter usage
1106 """
1107 a = np.ma.masked_array(a, np.isnan(a))
1108 m = np.ma.median(a, axis=axis, overwrite_input=overwrite_input)
1109 for i in range(np.count_nonzero(m.mask.ravel())):
1110 warnings.warn("All-NaN slice encountered", RuntimeWarning,
1111 stacklevel=5)
1112
1113 fill_value = np.timedelta64("NaT") if m.dtype.kind == "m" else np.nan
1114 if out is not None:
1115 out[...] = m.filled(fill_value)
1116 return out
1117 return m.filled(fill_value)
1118
1119
1120def _nanmedian_dispatcher(
1121 a, axis=None, out=None, overwrite_input=None, keepdims=None):
1122 return (a, out)
1123
1124
1125@array_function_dispatch(_nanmedian_dispatcher)
1126def nanmedian(a, axis=None, out=None, overwrite_input=False, keepdims=np._NoValue):
1127 """
1128 Compute the median along the specified axis, while ignoring NaNs.
1129
1130 Returns the median of the array elements.
1131
1132 Parameters
1133 ----------
1134 a : array_like
1135 Input array or object that can be converted to an array.
1136 axis : {int, sequence of int, None}, optional
1137 Axis or axes along which the medians are computed. The default
1138 is to compute the median along a flattened version of the array.
1139 A sequence of axes is supported since version 1.9.0.
1140 out : ndarray, optional
1141 Alternative output array in which to place the result. It must
1142 have the same shape and buffer length as the expected output,
1143 but the type (of the output) will be cast if necessary.
1144 overwrite_input : bool, optional
1145 If True, then allow use of memory of input array `a` for
1146 calculations. The input array will be modified by the call to
1147 `median`. This will save memory when you do not need to preserve
1148 the contents of the input array. Treat the input as undefined,
1149 but it will probably be fully or partially sorted. Default is
1150 False. If `overwrite_input` is ``True`` and `a` is not already an
1151 `ndarray`, an error will be raised.
1152 keepdims : bool, optional
1153 If this is set to True, the axes which are reduced are left
1154 in the result as dimensions with size one. With this option,
1155 the result will broadcast correctly against the original `a`.
1156
1157 If this is anything but the default value it will be passed
1158 through (in the special case of an empty array) to the
1159 `mean` function of the underlying array. If the array is
1160 a sub-class and `mean` does not have the kwarg `keepdims` this
1161 will raise a RuntimeError.
1162
1163 Returns
1164 -------
1165 median : ndarray
1166 A new array holding the result. If the input contains integers
1167 or floats smaller than ``float64``, then the output data-type is
1168 ``np.float64``. Otherwise, the data-type of the output is the
1169 same as that of the input. If `out` is specified, that array is
1170 returned instead.
1171
1172 See Also
1173 --------
1174 mean, median, percentile
1175
1176 Notes
1177 -----
1178 Given a vector ``V`` of length ``N``, the median of ``V`` is the
1179 middle value of a sorted copy of ``V``, ``V_sorted`` - i.e.,
1180 ``V_sorted[(N-1)/2]``, when ``N`` is odd and the average of the two
1181 middle values of ``V_sorted`` when ``N`` is even.
1182
1183 Examples
1184 --------
1185 >>> import numpy as np
1186 >>> a = np.array([[10.0, 7, 4], [3, 2, 1]])
1187 >>> a[0, 1] = np.nan
1188 >>> a
1189 array([[10., nan, 4.],
1190 [ 3., 2., 1.]])
1191 >>> np.median(a)
1192 np.float64(nan)
1193 >>> np.nanmedian(a)
1194 3.0
1195 >>> np.nanmedian(a, axis=0)
1196 array([6.5, 2. , 2.5])
1197 >>> np.median(a, axis=1)
1198 array([nan, 2.])
1199 >>> b = a.copy()
1200 >>> np.nanmedian(b, axis=1, overwrite_input=True)
