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.py198
1 files changed, 93 insertions, 105 deletions
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py
index cee7b3a62..499120630 100644
--- a/numpy/lib/function_base.py
+++ b/numpy/lib/function_base.py
@@ -1,7 +1,7 @@
from __future__ import division, absolute_import, print_function
try:
- # Accessing collections abstact classes from collections
+ # Accessing collections abstract classes from collections
# has been deprecated since Python 3.3
import collections.abc as collections_abc
except ImportError:
@@ -31,7 +31,6 @@ from numpy.core.overrides import set_module
from numpy.core import overrides
from numpy.core.function_base import add_newdoc
from numpy.lib.twodim_base import diag
-from .utils import deprecate
from numpy.core.multiarray import (
_insert, add_docstring, bincount, normalize_axis_index, _monotonicity,
interp as compiled_interp, interp_complex as compiled_interp_complex
@@ -317,14 +316,17 @@ def average(a, axis=None, weights=None, returned=False):
The weights array can either be 1-D (in which case its length must be
the size of `a` along the given axis) or of the same shape as `a`.
If `weights=None`, then all data in `a` are assumed to have a
- weight equal to one.
+ weight equal to one. The 1-D calculation is::
+
+ avg = sum(a * weights) / sum(weights)
+
+ The only constraint on `weights` is that `sum(weights)` must not be 0.
returned : bool, optional
Default is `False`. If `True`, the tuple (`average`, `sum_of_weights`)
is returned, otherwise only the average is returned.
If `weights=None`, `sum_of_weights` is equivalent to the number of
elements over which the average is taken.
-
Returns
-------
retval, [sum_of_weights] : array_type or double
@@ -359,12 +361,12 @@ def average(a, axis=None, weights=None, returned=False):
Examples
--------
- >>> data = list(range(1,5))
+ >>> data = np.arange(1, 5)
>>> data
- [1, 2, 3, 4]
+ array([1, 2, 3, 4])
>>> np.average(data)
2.5
- >>> np.average(range(1,11), weights=range(10,0,-1))
+ >>> np.average(np.arange(1, 11), weights=np.arange(10, 0, -1))
4.0
>>> data = np.arange(6).reshape((3,2))
@@ -378,7 +380,7 @@ def average(a, axis=None, weights=None, returned=False):
Traceback (most recent call last):
...
TypeError: Axis must be specified when shapes of a and weights differ.
-
+
>>> a = np.ones(5, dtype=np.float128)
>>> w = np.ones(5, dtype=np.complex64)
>>> avg = np.average(a, weights=w)
@@ -680,11 +682,7 @@ def select(condlist, choicelist, default=0):
# Now that the dtype is known, handle the deprecated select([], []) case
if len(condlist) == 0:
- # 2014-02-24, 1.9
- warnings.warn("select with an empty condition list is not possible"
- "and will be deprecated",
- DeprecationWarning, stacklevel=2)
- return np.asarray(default)[()]
+ raise ValueError("select with an empty condition list is not possible")
choicelist = [np.asarray(choice) for choice in choicelist]
choicelist.append(np.asarray(default))
@@ -700,25 +698,11 @@ def select(condlist, choicelist, default=0):
choicelist = np.broadcast_arrays(*choicelist)
# If cond array is not an ndarray in boolean format or scalar bool, abort.
- deprecated_ints = False
for i in range(len(condlist)):
cond = condlist[i]
if cond.dtype.type is not np.bool_:
- if np.issubdtype(cond.dtype, np.integer):
- # A previous implementation accepted int ndarrays accidentally.
- # Supported here deliberately, but deprecated.
- condlist[i] = condlist[i].astype(bool)
- deprecated_ints = True
- else:
- raise ValueError(
- 'invalid entry {} in condlist: should be boolean ndarray'.format(i))
-
- if deprecated_ints:
- # 2014-02-24, 1.9
- msg = "select condlists containing integer ndarrays is deprecated " \
- "and will be removed in the future. Use `.astype(bool)` to " \
- "convert to bools."
- warnings.warn(msg, DeprecationWarning, stacklevel=2)
+ raise TypeError(
+ 'invalid entry {} in condlist: should be boolean ndarray'.format(i))
if choicelist[0].ndim == 0:
# This may be common, so avoid the call.
@@ -1150,7 +1134,7 @@ def diff(a, n=1, axis=-1, prepend=np._NoValue, append=np._NoValue):
"""
Calculate the n-th discrete difference along the given axis.
- The first difference is given by ``out[n] = a[n+1] - a[n]`` along
+ The first difference is given by ``out[i] = a[i+1] - a[i]`` along
the given axis, higher differences are calculated by using `diff`
recursively.
@@ -1165,11 +1149,13 @@ def diff(a, n=1, axis=-1, prepend=np._NoValue, append=np._NoValue):
The axis along which the difference is taken, default is the
last axis.
prepend, append : array_like, optional
- Values to prepend or append to "a" along axis prior to
+ Values to prepend or append to `a` along axis prior to
performing the difference. Scalar values are expanded to
arrays with length 1 in the direction of axis and the shape
of the input array in along all other axes. Otherwise the
- dimension and shape must match "a" except along axis.
+ dimension and shape must match `a` except along axis.
+
+ .. versionadded:: 1.16.0
Returns
-------
@@ -1236,6 +1222,8 @@ def diff(a, n=1, axis=-1, prepend=np._NoValue, append=np._NoValue):
a = asanyarray(a)
nd = a.ndim
+ if nd == 0:
+ raise ValueError("diff requires input that is at least one dimensional")
axis = normalize_axis_index(axis, nd)
combined = []
@@ -1326,9 +1314,13 @@ def interp(x, xp, fp, left=None, right=None, period=None):
Notes
-----
- Does not check that the x-coordinate sequence `xp` is increasing.
- If `xp` is not increasing, the results are nonsense.
- A simple check for increasing is::
+ The x-coordinate sequence is expected to be increasing, but this is not
+ explicitly enforced. However, if the sequence `xp` is non-increasing,
+ interpolation results are meaningless.
+
+ Note that, since NaN is unsortable, `xp` also cannot contain NaNs.
+
+ A simple check for `xp` being strictly increasing is::
np.all(np.diff(xp) > 0)
@@ -1430,9 +1422,9 @@ def angle(z, deg=False):
Returns
-------
angle : ndarray or scalar
- The counterclockwise angle from the positive real axis on
- the complex plane, with dtype as numpy.float64.
-
+ The counterclockwise angle from the positive real axis on the complex
+ plane in the range ``(-pi, pi]``, with dtype as numpy.float64.
+
..versionchanged:: 1.16.0
This function works on subclasses of ndarray like `ma.array`.
@@ -1901,7 +1893,7 @@ class vectorize(object):
typecode characters or a list of data type specifiers. There should
be one data type specifier for each output.
doc : str, optional
- The docstring for the function. If `None`, the docstring will be the
+ The docstring for the function. If None, the docstring will be the
``pyfunc.__doc__``.
excluded : set, optional
Set of strings or integers representing the positional or keyword
@@ -1930,6 +1922,30 @@ class vectorize(object):
vectorized : callable
Vectorized function.
+ See Also
+ --------
+ frompyfunc : Takes an arbitrary Python function and returns a ufunc
+
+ Notes
+ -----
+ The `vectorize` function is provided primarily for convenience, not for
+ performance. The implementation is essentially a for loop.
+
+ If `otypes` is not specified, then a call to the function with the
+ first argument will be used to determine the number of outputs. The
+ results of this call will be cached if `cache` is `True` to prevent
+ calling the function twice. However, to implement the cache, the
+ original function must be wrapped which will slow down subsequent
+ calls, so only do this if your function is expensive.
+
+ The new keyword argument interface and `excluded` argument support
+ further degrades performance.
+
+ References
+ ----------
+ .. [1] NumPy Reference, section `Generalized Universal Function API
+ <https://docs.scipy.org/doc/numpy/reference/c-api.generalized-ufuncs.html>`_.
+
Examples
--------
>>> def myfunc(a, b):
@@ -1989,8 +2005,8 @@ class vectorize(object):
>>> import scipy.stats
>>> pearsonr = np.vectorize(scipy.stats.pearsonr,
- ... signature='(n),(n)->(),()')
- >>> pearsonr([[0, 1, 2, 3]], [[1, 2, 3, 4], [4, 3, 2, 1]])
+ ... signature='(n),(n)->(),()')
+ >>> pearsonr([[0, 1, 2, 3]], [[1, 2, 3, 4], [4, 3, 2, 1]])
(array([ 1., -1.]), array([ 0., 0.]))
Or for a vectorized convolution:
@@ -2002,31 +2018,7 @@ class vectorize(object):
[0., 0., 1., 2., 1., 0.],
[0., 0., 0., 1., 2., 1.]])
- See Also
- --------
- frompyfunc : Takes an arbitrary Python function and returns a ufunc
-
- Notes
- -----
- The `vectorize` function is provided primarily for convenience, not for
- performance. The implementation is essentially a for loop.
-
- If `otypes` is not specified, then a call to the function with the
- first argument will be used to determine the number of outputs. The
- results of this call will be cached if `cache` is `True` to prevent
- calling the function twice. However, to implement the cache, the
- original function must be wrapped which will slow down subsequent
- calls, so only do this if your function is expensive.
-
- The new keyword argument interface and `excluded` argument support
- further degrades performance.
-
- References
- ----------
- .. [1] NumPy Reference, section `Generalized Universal Function API
- <https://docs.scipy.org/doc/numpy/reference/c-api.generalized-ufuncs.html>`_.
"""
-
def __init__(self, pyfunc, otypes=None, doc=None, excluded=None,
cache=False, signature=None):
self.pyfunc = pyfunc
@@ -2313,7 +2305,7 @@ def cov(m, y=None, rowvar=True, bias=False, ddof=None, fweights=None,
>>> m = np.arange(10, dtype=np.float64)
>>> f = np.arange(10) * 2
>>> a = np.arange(10) ** 2.
- >>> ddof = 9 # N - 1
+ >>> ddof = 1
>>> w = f * a
>>> v1 = np.sum(w)
>>> v2 = np.sum(w * a)
@@ -2442,7 +2434,7 @@ def cov(m, y=None, rowvar=True, bias=False, ddof=None, fweights=None,
if fact <= 0:
warnings.warn("Degrees of freedom <= 0 for slice",
- RuntimeWarning, stacklevel=2)
+ RuntimeWarning, stacklevel=3)
fact = 0.0
X -= avg[:, None]
@@ -2521,7 +2513,7 @@ def corrcoef(x, y=None, rowvar=True, bias=np._NoValue, ddof=np._NoValue):
if bias is not np._NoValue or ddof is not np._NoValue:
# 2015-03-15, 1.10
warnings.warn('bias and ddof have no effect and are deprecated',
- DeprecationWarning, stacklevel=2)
+ DeprecationWarning, stacklevel=3)
c = cov(x, y, rowvar)
try:
d = diag(c)
@@ -2619,7 +2611,9 @@ def blackman(M):
>>> A = fft(window, 2048) / 25.5
>>> mag = np.abs(fftshift(A))
>>> freq = np.linspace(-0.5, 0.5, len(A))
- >>> response = 20 * np.log10(mag)
+ >>> with np.errstate(divide='ignore', invalid='ignore'):
+ ... response = 20 * np.log10(mag)
+ ...
>>> response = np.clip(response, -100, 100)
>>> plt.plot(freq, response)
[<matplotlib.lines.Line2D object at 0x...>]
@@ -2726,7 +2720,9 @@ def bartlett(M):
>>> A = fft(window, 2048) / 25.5
>>> mag = np.abs(fftshift(A))
>>> freq = np.linspace(-0.5, 0.5, len(A))
- >>> response = 20 * np.log10(mag)
+ >>> with np.errstate(divide='ignore', invalid='ignore'):
+ ... response = 20 * np.log10(mag)
+ ...
>>> response = np.clip(response, -100, 100)
>>> plt.plot(freq, response)
[<matplotlib.lines.Line2D object at 0x...>]
@@ -2827,7 +2823,9 @@ def hanning(M):
>>> A = fft(window, 2048) / 25.5
>>> mag = np.abs(fftshift(A))
>>> freq = np.linspace(-0.5, 0.5, len(A))
- >>> response = 20 * np.log10(mag)
+ >>> with np.errstate(divide='ignore', invalid='ignore'):
+ ... response = 20 * np.log10(mag)
+ ...
>>> response = np.clip(response, -100, 100)
>>> plt.plot(freq, response)
[<matplotlib.lines.Line2D object at 0x...>]
@@ -3063,10 +3061,13 @@ def i0(x):
See Also
--------
- scipy.special.iv, scipy.special.ive
+ scipy.special.i0, scipy.special.iv, scipy.special.ive
Notes
-----
+ The scipy implementation is recommended over this function: it is a
+ proper ufunc written in C, and more than an order of magnitude faster.
+
We use the algorithm published by Clenshaw [1]_ and referenced by
Abramowitz and Stegun [2]_, for which the function domain is
partitioned into the two intervals [0,8] and (8,inf), and Chebyshev
@@ -3086,21 +3087,15 @@ def i0(x):
Examples
--------
- >>> np.i0([0.])
- array(1.0) # may vary
+ >>> np.i0(0.)
+ array(1.0) # may vary
>>> np.i0([0., 1. + 2j])
- array([ 1.00000000+0.j , 0.18785373+0.64616944j]) # may vary
+ array([ 1.00000000+0.j , 0.18785373+0.64616944j]) # may vary
"""
- x = atleast_1d(x).copy()
- y = empty_like(x)
- ind = (x < 0)
- x[ind] = -x[ind]
- ind = (x <= 8.0)
- y[ind] = _i0_1(x[ind])
- ind2 = ~ind
- y[ind2] = _i0_2(x[ind2])
- return y.squeeze()
+ x = np.asanyarray(x)
+ x = np.abs(x)
+ return piecewise(x, [x <= 8.0], [_i0_1, _i0_2])
## End of cephes code for i0
@@ -3306,13 +3301,6 @@ def sinc(x):
Text(0.5, 0, 'X')
>>> plt.show()
- It works in 2-D as well:
-
- >>> x = np.linspace(-4, 4, 401)
- >>> xx = np.outer(x, x)
- >>> plt.imshow(np.sinc(xx))
- <matplotlib.image.AxesImage object at 0x...>
-
"""
x = np.asanyarray(x)
y = pi * where(x == 0, 1.0e-20, x)
@@ -3701,7 +3689,8 @@ def percentile(a, q, axis=None, out=None,
plt.show()
"""
- q = np.true_divide(q, 100.0) # handles the asarray for us too
+ q = np.true_divide(q, 100)
+ q = asanyarray(q) # undo any decay that the ufunc performed (see gh-13105)
if not _quantile_is_valid(q):
raise ValueError("Percentiles must be in the range [0, 100]")
return _quantile_unchecked(
@@ -3718,7 +3707,8 @@ 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
+
+ .. versionadded:: 1.15.0
Parameters
----------
@@ -3919,7 +3909,7 @@ def _quantile_ureduce_func(a, q, axis=None, out=None, overwrite_input=False,
indices_above = concatenate((indices_above, [-1]))
weights_above = indices - indices_below
- weights_below = 1.0 - weights_above
+ weights_below = 1 - weights_above
weights_shape = [1, ] * ap.ndim
weights_shape[axis] = len(indices)
@@ -3956,8 +3946,6 @@ def _quantile_ureduce_func(a, q, axis=None, out=None, overwrite_input=False,
r = add(x1, x2)
if np.any(n):
- warnings.warn("Invalid value encountered in percentile",
- RuntimeWarning, stacklevel=3)
if zerod:
if ap.ndim == 1:
if out is not None:
@@ -4298,7 +4286,7 @@ def delete(arr, obj, axis=None):
# 2013-09-24, 1.9
warnings.warn(
"in the future the special handling of scalars will be removed "
- "from delete and raise an error", DeprecationWarning, stacklevel=2)
+ "from delete and raise an error", DeprecationWarning, stacklevel=3)
if wrap:
return wrap(arr)
else:
@@ -4335,7 +4323,7 @@ def delete(arr, obj, axis=None):
else:
slobj[axis] = slice(None, start)
new[tuple(slobj)] = arr[tuple(slobj)]
- # copy end chunck
+ # copy end chunk
if stop == N:
pass
else:
@@ -4367,7 +4355,7 @@ def delete(arr, obj, axis=None):
if obj.dtype == bool:
warnings.warn("in the future insert will treat boolean arrays and "
"array-likes as boolean index instead of casting it "
- "to integer", FutureWarning, stacklevel=2)
+ "to integer", FutureWarning, stacklevel=3)
obj = obj.astype(intp)
if isinstance(_obj, (int, long, integer)):
# optimization for a single value
@@ -4395,7 +4383,7 @@ def delete(arr, obj, axis=None):
# 2013-09-24, 1.9
warnings.warn(
"using a non-integer array as obj in delete will result in an "
- "error in the future", DeprecationWarning, stacklevel=2)
+ "error in the future", DeprecationWarning, stacklevel=3)
obj = obj.astype(intp)
keep = ones(N, dtype=bool)
@@ -4406,13 +4394,13 @@ def delete(arr, obj, axis=None):
warnings.warn(
"in the future out of bounds indices will raise an error "
"instead of being ignored by `numpy.delete`.",
- DeprecationWarning, stacklevel=2)
+ DeprecationWarning, stacklevel=3)
obj = obj[inside_bounds]
positive_indices = obj >= 0
if not positive_indices.all():
warnings.warn(
"in the future negative indices will not be ignored by "
- "`numpy.delete`.", FutureWarning, stacklevel=2)
+ "`numpy.delete`.", FutureWarning, stacklevel=3)
obj = obj[positive_indices]
keep[obj, ] = False
@@ -4537,7 +4525,7 @@ def insert(arr, obj, values, axis=None):
# 2013-09-24, 1.9
warnings.warn(
"in the future the special handling of scalars will be removed "
- "from insert and raise an error", DeprecationWarning, stacklevel=2)
+ "from insert and raise an error", DeprecationWarning, stacklevel=3)
arr = arr.copy(order=arrorder)
arr[...] = values
if wrap:
@@ -4561,7 +4549,7 @@ def insert(arr, obj, values, axis=None):
warnings.warn(
"in the future insert will treat boolean arrays and "
"array-likes as a boolean index instead of casting it to "
- "integer", FutureWarning, stacklevel=2)
+ "integer", FutureWarning, stacklevel=3)
indices = indices.astype(intp)
# Code after warning period:
#if obj.ndim != 1:
@@ -4611,7 +4599,7 @@ def insert(arr, obj, values, axis=None):
# 2013-09-24, 1.9
warnings.warn(
"using a non-integer array as obj in insert will result in an "
- "error in the future", DeprecationWarning, stacklevel=2)
+ "error in the future", DeprecationWarning, stacklevel=3)
indices = indices.astype(intp)
indices[indices < 0] += N