summaryrefslogtreecommitdiff
path: root/numpy/lib/function_base.py
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/lib/function_base.py')
-rw-r--r--numpy/lib/function_base.py251
1 files changed, 200 insertions, 51 deletions
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py
index 0434eb472..a6e3e07d3 100644
--- a/numpy/lib/function_base.py
+++ b/numpy/lib/function_base.py
@@ -1,6 +1,11 @@
from __future__ import division, absolute_import, print_function
-import collections
+try:
+ # Accessing collections abstact classes from collections
+ # has been deprecated since Python 3.3
+ import collections.abc as collections_abc
+except ImportError:
+ import collections as collections_abc
import re
import sys
import warnings
@@ -49,7 +54,8 @@ __all__ = [
'bincount', 'digitize', 'cov', 'corrcoef',
'msort', 'median', 'sinc', 'hamming', 'hanning', 'bartlett',
'blackman', 'kaiser', 'trapz', 'i0', 'add_newdoc', 'add_docstring',
- 'meshgrid', 'delete', 'insert', 'append', 'interp', 'add_newdoc_ufunc'
+ 'meshgrid', 'delete', 'insert', 'append', 'interp', 'add_newdoc_ufunc',
+ 'quantile'
]
@@ -140,7 +146,7 @@ def rot90(m, k=1, axes=(0,1)):
return flip(transpose(m, axes_list), axes[1])
-def flip(m, axis):
+def flip(m, axis=None):
"""
Reverse the order of elements in an array along the given axis.
@@ -152,9 +158,16 @@ def flip(m, axis):
----------
m : array_like
Input array.
- axis : integer
- Axis in array, which entries are reversed.
+ axis : None or int or tuple of ints, optional
+ Axis or axes along which to flip over. The default,
+ axis=None, will flip over all of the axes of the input array.
+ If axis is negative it counts from the last to the first axis.
+
+ If axis is a tuple of ints, flipping is performed on all of the axes
+ specified in the tuple.
+ .. versionchanged:: 1.15.0
+ None and tuples of axes are supported
Returns
-------
@@ -170,46 +183,60 @@ def flip(m, axis):
Notes
-----
flip(m, 0) is equivalent to flipud(m).
+
flip(m, 1) is equivalent to fliplr(m).
+
flip(m, n) corresponds to ``m[...,::-1,...]`` with ``::-1`` at position n.
+ flip(m) corresponds to ``m[::-1,::-1,...,::-1]`` with ``::-1`` at all
+ positions.
+
+ flip(m, (0, 1)) corresponds to ``m[::-1,::-1,...]`` with ``::-1`` at
+ position 0 and position 1.
+
Examples
--------
>>> A = np.arange(8).reshape((2,2,2))
>>> A
array([[[0, 1],
[2, 3]],
-
[[4, 5],
[6, 7]]])
-
>>> flip(A, 0)
array([[[4, 5],
[6, 7]],
-
[[0, 1],
[2, 3]]])
-
>>> flip(A, 1)
array([[[2, 3],
[0, 1]],
-
[[6, 7],
[4, 5]]])
-
+ >>> np.flip(A)
+ array([[[7, 6],
+ [5, 4]],
+ [[3, 2],
+ [1, 0]]])
+ >>> np.flip(A, (0, 2))
+ array([[[5, 4],
+ [7, 6]],
+ [[1, 0],
+ [3, 2]]])
>>> A = np.random.randn(3,4,5)
>>> np.all(flip(A,2) == A[:,:,::-1,...])
True
"""
if not hasattr(m, 'ndim'):
m = asarray(m)
- indexer = [slice(None)] * m.ndim
- try:
- indexer[axis] = slice(None, None, -1)
- except IndexError:
- raise ValueError("axis=%i is invalid for the %i-dimensional input array"
- % (axis, m.ndim))
- return m[tuple(indexer)]
+ if axis is None:
+ indexer = (np.s_[::-1],) * m.ndim
+ else:
+ axis = _nx.normalize_axis_tuple(axis, m.ndim)
+ indexer = [np.s_[:]] * m.ndim
+ for ax in axis:
+ indexer[ax] = np.s_[::-1]
+ indexer = tuple(indexer)
+ return m[indexer]
def iterable(y):
@@ -547,7 +574,7 @@ def piecewise(x, condlist, funclist, *args, **kw):
y = zeros(x.shape, x.dtype)
for k in range(n):
item = funclist[k]
- if not isinstance(item, collections.Callable):
+ if not isinstance(item, collections_abc.Callable):
y[condlist[k]] = item
else:
vals = x[condlist[k]]
@@ -632,7 +659,7 @@ def select(condlist, choicelist, default=0):
deprecated_ints = True
else:
raise ValueError(
- 'invalid entry in choicelist: should be boolean ndarray')
+ 'invalid entry {} in condlist: should be boolean ndarray'.format(i))
if deprecated_ints:
# 2014-02-24, 1.9
@@ -818,9 +845,9 @@ def gradient(f, *varargs, **kwargs):
Notes
-----
Assuming that :math:`f\\in C^{3}` (i.e., :math:`f` has at least 3 continuous
- derivatives) and let be :math:`h_{*}` a non homogeneous stepsize, the
- spacing the finite difference coefficients are computed by minimising
- the consistency error :math:`\\eta_{i}`:
+ derivatives) and let :math:`h_{*}` be a non-homogeneous stepsize, we
+ minimize the "consistency error" :math:`\\eta_{i}` between the true gradient
+ and its estimate from a linear combination of the neighboring grid-points:
.. math::
@@ -839,7 +866,7 @@ def gradient(f, *varargs, **kwargs):
\\left\\{
\\begin{array}{r}
\\alpha+\\beta+\\gamma=0 \\\\
- -\\beta h_{d}+\\gamma h_{s}=1 \\\\
+ \\beta h_{d}-\\gamma h_{s}=1 \\\\
\\beta h_{d}^{2}+\\gamma h_{s}^{2}=0
\\end{array}
\\right.
@@ -1255,23 +1282,13 @@ def interp(x, xp, fp, left=None, right=None, period=None):
interp_func = compiled_interp
input_dtype = np.float64
- if period is None:
- if isinstance(x, (float, int, number)):
- return interp_func([x], xp, fp, left, right).item()
- elif isinstance(x, np.ndarray) and x.ndim == 0:
- return interp_func([x], xp, fp, left, right).item()
- else:
- return interp_func(x, xp, fp, left, right)
- else:
+ if period is not None:
if period == 0:
raise ValueError("period must be a non-zero value")
period = abs(period)
left = None
right = None
- return_array = True
- if isinstance(x, (float, int, number)):
- return_array = False
- x = [x]
+
x = np.asarray(x, dtype=np.float64)
xp = np.asarray(xp, dtype=np.float64)
fp = np.asarray(fp, dtype=input_dtype)
@@ -1289,10 +1306,7 @@ def interp(x, xp, fp, left=None, right=None, period=None):
xp = np.concatenate((xp[-1:]-period, xp, xp[0:1]+period))
fp = np.concatenate((fp[-1:], fp, fp[0:1]))
- if return_array:
- return interp_func(x, xp, fp, left, right)
- else:
- return interp_func(x, xp, fp, left, right).item()
+ return interp_func(x, xp, fp, left, right)
def angle(z, deg=0):
@@ -1619,9 +1633,9 @@ def disp(mesg, device=None, linefeed=True):
Besides ``sys.stdout``, a file-like object can also be used as it has
both required methods:
- >>> from StringIO import StringIO
+ >>> from io import StringIO
>>> buf = StringIO()
- >>> np.disp('"Display" in a file', device=buf)
+ >>> np.disp(u'"Display" in a file', device=buf)
>>> buf.getvalue()
'"Display" in a file\\n'
@@ -2310,7 +2324,7 @@ def cov(m, y=None, rowvar=True, bias=False, ddof=None, fweights=None,
else:
X_T = (X*w).T
c = dot(X, X_T.conj())
- c *= 1. / np.float64(fact)
+ c *= np.true_divide(1, fact)
return c.squeeze()
@@ -3411,17 +3425,19 @@ def percentile(a, q, axis=None, out=None,
If True, then allow the input array `a` to be modified by intermediate
calculations, to save memory. In this case, the contents of the input
`a` after this function completes is undefined.
+
interpolation : {'linear', 'lower', 'higher', 'midpoint', 'nearest'}
This optional parameter specifies the interpolation method to
- use when the desired quantile lies between two data points
+ use when the desired percentile lies between two data points
``i < j``:
- * linear: ``i + (j - i) * fraction``, where ``fraction``
- is the fractional part of the index surrounded by ``i``
- and ``j``.
- * lower: ``i``.
- * higher: ``j``.
- * nearest: ``i`` or ``j``, whichever is nearest.
- * midpoint: ``(i + j) / 2``.
+
+ * 'linear': ``i + (j - i) * fraction``, where ``fraction``
+ is the fractional part of the index surrounded by ``i``
+ and ``j``.
+ * 'lower': ``i``.
+ * 'higher': ``j``.
+ * 'nearest': ``i`` or ``j``, whichever is nearest.
+ * 'midpoint': ``(i + j) / 2``.
.. versionadded:: 1.9.0
keepdims : bool, optional
@@ -3448,6 +3464,7 @@ def percentile(a, q, axis=None, out=None,
mean
median : equivalent to ``percentile(..., 50)``
nanpercentile
+ quantile : equivalent to percentile, except with q in the range [0, 1].
Notes
-----
@@ -3488,6 +3505,34 @@ def percentile(a, q, axis=None, out=None,
array([ 7., 2.])
>>> assert not np.all(a == b)
+ The different types of interpolation can be visualized graphically:
+
+ .. plot::
+
+ import matplotlib.pyplot as plt
+
+ a = np.arange(4)
+ p = np.linspace(0, 100, 6001)
+ ax = plt.gca()
+ lines = [
+ ('linear', None),
+ ('higher', '--'),
+ ('lower', '--'),
+ ('nearest', '-.'),
+ ('midpoint', '-.'),
+ ]
+ for interpolation, style in lines:
+ ax.plot(
+ p, np.percentile(a, p, interpolation=interpolation),
+ label=interpolation, linestyle=style)
+ ax.set(
+ title='Interpolation methods for list: ' + str(a),
+ xlabel='Percentile',
+ ylabel='List item returned',
+ yticks=a)
+ ax.legend()
+ plt.show()
+
"""
q = np.true_divide(q, 100.0) # handles the asarray for us too
if not _quantile_is_valid(q):
@@ -3496,6 +3541,110 @@ def percentile(a, q, axis=None, out=None,
a, q, axis, out, overwrite_input, interpolation, keepdims)
+def quantile(a, q, axis=None, out=None,
+ overwrite_input=False, interpolation='linear', keepdims=False):
+ """
+ Compute the `q`th quantile of the data along the specified axis.
+ ..versionadded:: 1.15.0
+
+ Parameters
+ ----------
+ a : array_like
+ Input array or object that can be converted to an array.
+ q : array_like of float
+ Quantile or sequence of quantiles to compute, which must be between
+ 0 and 1 inclusive.
+ axis : {int, tuple of int, None}, optional
+ Axis or axes along which the quantiles are computed. The
+ default is to compute the quantile(s) along a flattened
+ version of the array.
+ out : ndarray, optional
+ Alternative output array in which to place the result. It must
+ have the same shape and buffer length as the expected output,
+ but the type (of the output) will be cast if necessary.
+ overwrite_input : bool, optional
+ If True, then allow the input array `a` to be modified by intermediate
+ calculations, to save memory. In this case, the contents of the input
+ `a` after this function completes is undefined.
+ interpolation : {'linear', 'lower', 'higher', 'midpoint', 'nearest'}
+ This optional parameter specifies the interpolation method to
+ use when the desired quantile lies between two data points
+ ``i < j``:
+ * linear: ``i + (j - i) * fraction``, where ``fraction``
+ is the fractional part of the index surrounded by ``i``
+ and ``j``.
+ * lower: ``i``.
+ * higher: ``j``.
+ * nearest: ``i`` or ``j``, whichever is nearest.
+ * midpoint: ``(i + j) / 2``.
+ keepdims : bool, optional
+ If this is set to True, the axes which are reduced are left in
+ the result as dimensions with size one. With this option, the
+ result will broadcast correctly against the original array `a`.
+
+ Returns
+ -------
+ quantile : scalar or ndarray
+ If `q` is a single quantile and `axis=None`, then the result
+ is a scalar. If multiple quantiles are given, first axis of
+ the result corresponds to the quantiles. The other axes are
+ the axes that remain after the reduction of `a`. If the input
+ contains integers or floats smaller than ``float64``, the output
+ data-type is ``float64``. Otherwise, the output data-type is the
+ same as that of the input. If `out` is specified, that array is
+ returned instead.
+
+ See Also
+ --------
+ mean
+ percentile : equivalent to quantile, but with q in the range [0, 100].
+ median : equivalent to ``quantile(..., 0.5)``
+ nanquantile
+
+ Notes
+ -----
+ Given a vector ``V`` of length ``N``, the ``q``-th quantile of
+ ``V`` is the value ``q`` of the way from the minimum to the
+ maximum in a sorted copy of ``V``. The values and distances of
+ the two nearest neighbors as well as the `interpolation` parameter
+ will determine the quantile if the normalized ranking does not
+ match the location of ``q`` exactly. This function is the same as
+ the median if ``q=0.5``, the same as the minimum if ``q=0.0`` and the
+ same as the maximum if ``q=1.0``.
+
+ Examples
+ --------
+ >>> a = np.array([[10, 7, 4], [3, 2, 1]])
+ >>> a
+ array([[10, 7, 4],
+ [ 3, 2, 1]])
+ >>> np.quantile(a, 0.5)
+ 3.5
+ >>> np.quantile(a, 0.5, axis=0)
+ array([[ 6.5, 4.5, 2.5]])
+ >>> np.quantile(a, 0.5, axis=1)
+ array([ 7., 2.])
+ >>> np.quantile(a, 0.5, axis=1, keepdims=True)
+ array([[ 7.],
+ [ 2.]])
+ >>> m = np.quantile(a, 0.5, axis=0)
+ >>> out = np.zeros_like(m)
+ >>> np.quantile(a, 0.5, axis=0, out=out)
+ array([[ 6.5, 4.5, 2.5]])
+ >>> m
+ array([[ 6.5, 4.5, 2.5]])
+ >>> b = a.copy()
+ >>> np.quantile(b, 0.5, axis=1, overwrite_input=True)
+ array([ 7., 2.])
+ >>> assert not np.all(a == b)
+ """
+ q = np.asanyarray(q)
+ if not _quantile_is_valid(q):
+ raise ValueError("Quantiles must be in the range [0, 1]")
+ return _quantile_unchecked(
+ a, q, axis, out, overwrite_input, interpolation, keepdims)
+
+
def _quantile_unchecked(a, q, axis=None, out=None, overwrite_input=False,
interpolation='linear', keepdims=False):
"""Assumes that q is in [0, 1], and is an ndarray"""