From 5de1a8215edc5982458473b2ef6da091beb4b19d Mon Sep 17 00:00:00 2001 From: drabach Date: Sun, 12 Feb 2017 03:46:53 +0100 Subject: DOC: gradient uses 1st order central difference in the interior (#8605) The gradient function uses 1st order central difference in the interior, not second order. --- numpy/lib/function_base.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'numpy/lib/function_base.py') diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index 51353351f..30bc1a548 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -1491,7 +1491,7 @@ def gradient(f, *varargs, **kwargs): """ Return the gradient of an N-dimensional array. - The gradient is computed using second order accurate central differences + The gradient is computed using first order accurate central differences in the interior and either first differences or second order accurate one-sides (forward or backwards) differences at the boundaries. The returned gradient hence has the same shape as the input array. @@ -1630,7 +1630,7 @@ def gradient(f, *varargs, **kwargs): "Shape of array too small to calculate a numerical gradient, " "at least two elements are required.") - # Numerical differentiation: 1st order edges, 2nd order interior + # Numerical differentiation: 1st order edges, 1st order interior if y.shape[axis] == 2 or edge_order == 1: # Use first order differences for time data out = np.empty_like(y, dtype=otype) @@ -1653,7 +1653,7 @@ def gradient(f, *varargs, **kwargs): # 1D equivalent -- out[-1] = (y[-1] - y[-2]) out[slice1] = (y[slice2] - y[slice3]) - # Numerical differentiation: 2st order edges, 2nd order interior + # Numerical differentiation: 2nd order edges, 1st order interior else: # Use second order differences where possible out = np.empty_like(y, dtype=otype) -- cgit v1.2.1 From 829b83ce53cc76b94979910e196d3a17e8bd2538 Mon Sep 17 00:00:00 2001 From: Alessandro Pietro Bardelli Date: Sun, 12 Feb 2017 12:55:12 +0100 Subject: Revert "DOC: gradient uses 1st order central difference in the interior" --- numpy/lib/function_base.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'numpy/lib/function_base.py') diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index 30bc1a548..51353351f 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -1491,7 +1491,7 @@ def gradient(f, *varargs, **kwargs): """ Return the gradient of an N-dimensional array. - The gradient is computed using first order accurate central differences + The gradient is computed using second order accurate central differences in the interior and either first differences or second order accurate one-sides (forward or backwards) differences at the boundaries. The returned gradient hence has the same shape as the input array. @@ -1630,7 +1630,7 @@ def gradient(f, *varargs, **kwargs): "Shape of array too small to calculate a numerical gradient, " "at least two elements are required.") - # Numerical differentiation: 1st order edges, 1st order interior + # Numerical differentiation: 1st order edges, 2nd order interior if y.shape[axis] == 2 or edge_order == 1: # Use first order differences for time data out = np.empty_like(y, dtype=otype) @@ -1653,7 +1653,7 @@ def gradient(f, *varargs, **kwargs): # 1D equivalent -- out[-1] = (y[-1] - y[-2]) out[slice1] = (y[slice2] - y[slice3]) - # Numerical differentiation: 2nd order edges, 1st order interior + # Numerical differentiation: 2st order edges, 2nd order interior else: # Use second order differences where possible out = np.empty_like(y, dtype=otype) -- cgit v1.2.1 From 0b7215793d0702746f78d5b43e9d3a357de82de6 Mon Sep 17 00:00:00 2001 From: Alex Rothberg Date: Sun, 12 Feb 2017 14:38:06 -0500 Subject: DOC: Indicate that axis param to average may be a tuple of ints. --- numpy/lib/function_base.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'numpy/lib/function_base.py') diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index 51353351f..2aa104174 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -1027,9 +1027,16 @@ def average(a, axis=None, weights=None, returned=False): a : array_like Array containing data to be averaged. If `a` is not an array, a conversion is attempted. - axis : int, optional - Axis along which to average `a`. If `None`, averaging is done over - the flattened array. + axis : None or int or tuple of ints, optional + Axis or axes along which to average `a`. The default, + axis=None, will average over all of the elements of the input array. + If axis is negative it counts from the last to the first axis. + + .. versionadded:: 1.7.0 + + If axis is a tuple of ints, averaging is performed on all of the axes + specified in the tuple instead of a single axis or all the axes as + before. weights : array_like, optional An array of weights associated with the values in `a`. Each value in `a` contributes to the average according to its associated weight. -- cgit v1.2.1 From d932fcd38d9ef0f76c988d6c197856fa0c71314b Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Mon, 13 Feb 2017 21:02:06 +0000 Subject: BUG: Copy meshgrid after broadcasting, fixing #8561 Also, remove some unused variables --- numpy/lib/function_base.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'numpy/lib/function_base.py') diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index 51353351f..23f8d7d4d 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -4498,24 +4498,21 @@ def meshgrid(*xi, **kwargs): "Valid values for `indexing` are 'xy' and 'ij'.") s0 = (1,) * ndim - output = [np.asanyarray(x).reshape(s0[:i] + (-1,) + s0[i + 1::]) + output = [np.asanyarray(x).reshape(s0[:i] + (-1,) + s0[i + 1:]) for i, x in enumerate(xi)] - shape = [x.size for x in output] - if indexing == 'xy' and ndim > 1: # switch first and second axis - output[0].shape = (1, -1) + (1,)*(ndim - 2) - output[1].shape = (-1, 1) + (1,)*(ndim - 2) - shape[0], shape[1] = shape[1], shape[0] - - if copy_: - output = [x.copy() for x in output] + output[0].shape = (1, -1) + s0[2:] + output[1].shape = (-1, 1) + s0[2:] - if not sparse and len(output) > 0: + if not sparse: # Return the full N-D matrix (not only the 1-D vector) output = np.broadcast_arrays(*output, subok=True) + if copy_: + output = [x.copy() for x in output] + return output -- cgit v1.2.1 From 370b6506f128460371484a50c813d66e64582f44 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Wed, 8 Feb 2017 22:05:11 +0000 Subject: MAINT: Use normalize_axis_index in all python axis checking As a result, some exceptions change from ValueError to IndexError This also changes the exception types raised in places where normalize_axis_index is not quite appropriate --- numpy/lib/function_base.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) (limited to 'numpy/lib/function_base.py') diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index ae1420b72..4d1ffbccc 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -25,7 +25,7 @@ from numpy.core.numerictypes import typecodes, number from numpy.lib.twodim_base import diag from .utils import deprecate from numpy.core.multiarray import ( - _insert, add_docstring, digitize, bincount, + _insert, add_docstring, digitize, bincount, normalize_axis_index, interp as compiled_interp, interp_complex as compiled_interp_complex ) from numpy.core.umath import _add_newdoc_ufunc as add_newdoc_ufunc @@ -4828,14 +4828,7 @@ def insert(arr, obj, values, axis=None): arr = arr.ravel() ndim = arr.ndim axis = ndim - 1 - else: - if ndim > 0 and (axis < -ndim or axis >= ndim): - raise IndexError( - "axis %i is out of bounds for an array of " - "dimension %i" % (axis, ndim)) - if (axis < 0): - axis += ndim - if (ndim == 0): + elif ndim == 0: # 2013-09-24, 1.9 warnings.warn( "in the future the special handling of scalars will be removed " @@ -4846,6 +4839,8 @@ def insert(arr, obj, values, axis=None): return wrap(arr) else: return arr + else: + axis = normalize_axis_index(axis, ndim) slobj = [slice(None)]*ndim N = arr.shape[axis] newshape = list(arr.shape) -- cgit v1.2.1 From 9520de90837d0afaac3d1612047f4b952563b3d5 Mon Sep 17 00:00:00 2001 From: Alessandro Pietro Bardelli Date: Wed, 4 Jan 2017 00:58:44 +0100 Subject: ENH: gradient support for unevenly spaced data This somehow reverts #7618 and solves #6847, #7548 by implementing support for unevenly spaced data. Now the behaviour is similar to that of Matlab/Octave function. As argument it can take: 1. A single scalar to specify a sample distance for all dimensions. 2. N scalars to specify a constant sample distance for each dimension. i.e. `dx`, `dy`, `dz`, ... 3. N arrays to specify the coordinates of the values along each dimension of F. The length of the array must match the size of the corresponding dimension 4. Any combination of N scalars/arrays with the meaning of 2. and 3. --- numpy/lib/function_base.py | 319 +++++++++++++++++++++++++++++++++------------ 1 file changed, 235 insertions(+), 84 deletions(-) (limited to 'numpy/lib/function_base.py') diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index 4d1ffbccc..fc49a6fd7 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -128,7 +128,8 @@ def rot90(m, k=1, axes=(0,1)): return flip(flip(m, axes[0]), axes[1]) axes_list = arange(0, m.ndim) - axes_list[axes[0]], axes_list[axes[1]] = axes_list[axes[1]], axes_list[axes[0]] + (axes_list[axes[0]], axes_list[axes[1]]) = (axes_list[axes[1]], + axes_list[axes[0]]) if k == 1: return transpose(flip(m,axes[1]), axes_list) @@ -332,7 +333,7 @@ def _hist_bin_doane(x): Improved version of Sturges' formula which works better for non-normal data. See - http://stats.stackexchange.com/questions/55134/doanes-formula-for-histogram-binning + stats.stackexchange.com/questions/55134/doanes-formula-for-histogram-binning Parameters ---------- @@ -638,7 +639,7 @@ def histogram(a, bins=10, range=None, normed=False, weights=None, >>> rng = np.random.RandomState(10) # deterministic random data >>> a = np.hstack((rng.normal(size=1000), ... rng.normal(loc=5, scale=2, size=1000))) - >>> plt.hist(a, bins='auto') # plt.hist passes its arguments to np.histogram + >>> plt.hist(a, bins='auto') # arguments are passed to np.histogram >>> plt.title("Histogram with 'auto' bins") >>> plt.show() @@ -764,15 +765,19 @@ def histogram(a, bins=10, range=None, normed=False, weights=None, decrement = tmp_a_data < bin_edges[indices] indices[decrement] -= 1 # The last bin includes the right edge. The other bins do not. - increment = (tmp_a_data >= bin_edges[indices + 1]) & (indices != bins - 1) + increment = ((tmp_a_data >= bin_edges[indices + 1]) + & (indices != bins - 1)) indices[increment] += 1 # We now compute the histogram using bincount if ntype.kind == 'c': - n.real += np.bincount(indices, weights=tmp_w.real, minlength=bins) - n.imag += np.bincount(indices, weights=tmp_w.imag, minlength=bins) + n.real += np.bincount(indices, weights=tmp_w.real, + minlength=bins) + n.imag += np.bincount(indices, weights=tmp_w.imag, + minlength=bins) else: - n += np.bincount(indices, weights=tmp_w, minlength=bins).astype(ntype) + n += np.bincount(indices, weights=tmp_w, + minlength=bins).astype(ntype) # Rename the bin edges for return. bins = bin_edges @@ -1499,19 +1504,29 @@ def gradient(f, *varargs, **kwargs): Return the gradient of an N-dimensional array. The gradient is computed using second order accurate central differences - in the interior and either first differences or second order accurate - one-sides (forward or backwards) differences at the boundaries. The - returned gradient hence has the same shape as the input array. + in the interior points and either first or second order accurate one-sides + (forward or backwards) differences at the boundaries. + The returned gradient hence has the same shape as the input array. Parameters ---------- f : array_like An N-dimensional array containing samples of a scalar function. - varargs : scalar or list of scalar, optional - N scalars specifying the sample distances for each dimension, - i.e. `dx`, `dy`, `dz`, ... Default distance: 1. - single scalar specifies sample distance for all dimensions. - if `axis` is given, the number of varargs must equal the number of axes. + varargs : list of scalar or array, optional + Spacing between f values. Default unitary spacing for all dimensions. + Spacing can be specified using: + + 1. single scalar to specify a sample distance for all dimensions. + 2. N scalars to specify a constant sample distance for each dimension. + i.e. `dx`, `dy`, `dz`, ... + 3. N arrays to specify the coordinates of the values along each + dimension of F. The length of the array must match the size of + the corresponding dimension + 4. Any combination of N scalars/arrays with the meaning of 2. and 3. + + If `axis` is given, the number of varargs must equal the number of axes. + Default: 1. + edge_order : {1, 2}, optional Gradient is calculated using N-th order accurate differences at the boundaries. Default: 1. @@ -1520,8 +1535,9 @@ def gradient(f, *varargs, **kwargs): axis : None or int or tuple of ints, optional Gradient is calculated only along the given axis or axes - The default (axis = None) is to calculate the gradient for all the axes of the input array. - axis may be negative, in which case it counts from the last to the first axis. + The default (axis = None) is to calculate the gradient for all the axes + of the input array. axis may be negative, in which case it counts from + the last to the first axis. .. versionadded:: 1.11.0 @@ -1529,17 +1545,31 @@ def gradient(f, *varargs, **kwargs): ------- gradient : ndarray or list of ndarray A set of ndarrays (or a single ndarray if there is only one dimension) - correposnding to the derivatives of f with respect to each dimension. + corresponding to the derivatives of f with respect to each dimension. Each derivative has the same shape as f. - + Examples -------- - >>> x = np.array([1, 2, 4, 7, 11, 16], dtype=np.float) - >>> np.gradient(x) + >>> f = np.array([1, 2, 4, 7, 11, 16], dtype=np.float) + >>> np.gradient(f) array([ 1. , 1.5, 2.5, 3.5, 4.5, 5. ]) - >>> np.gradient(x, 2) + >>> np.gradient(f, 2) array([ 0.5 , 0.75, 1.25, 1.75, 2.25, 2.5 ]) + + Spacing can be also specified with an array that represents the coordinates + of the values F along the dimensions. + For instance a uniform spacing: + + >>> x = np.arange(f.size) + >>> np.gradient(f, x) + array([ 1. , 1.5, 2.5, 3.5, 4.5, 5. ]) + Or a non uniform one: + + >>> x = np.array([0., 1., 1.5, 3.5, 4., 6.], dtype=np.float) + >>> np.gradient(f, x) + array([ 1. , 3. , 3.5, 6.7, 6.9, 2.5]) + For two dimensional arrays, the return will be two arrays ordered by axis. In this example the first array stands for the gradient in rows and the second one in columns direction: @@ -1549,15 +1579,99 @@ def gradient(f, *varargs, **kwargs): [ 2., 2., -1.]]), array([[ 1. , 2.5, 4. ], [ 1. , 1. , 1. ]])] + In this example the spacing is also specified: + uniform for axis=0 and non uniform for axis=1 + + >>> dx = 2. + >>> y = [1., 1.5, 3.5] + >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=np.float), dx, y) + [array([[ 1. , 1. , -0.5], + [ 1. , 1. , -0.5]]), array([[ 2. , 2. , 2. ], + [ 2. , 1.7, 0.5]])] + + It is possible to specify how boundaries are treated using `edge_order` + >>> x = np.array([0, 1, 2, 3, 4]) - >>> y = x**2 - >>> np.gradient(y, edge_order=2) + >>> f = x**2 + >>> np.gradient(f, edge_order=1) + array([ 1., 2., 4., 6., 7.]) + >>> np.gradient(f, edge_order=2) array([-0., 2., 4., 6., 8.]) - The axis keyword can be used to specify a subset of axes of which the gradient is calculated + The `axis` keyword can be used to specify a subset of axes of which the + gradient is calculated + >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=np.float), axis=0) array([[ 2., 2., -1.], [ 2., 2., -1.]]) + + Notes + ----- + Assuming that :math:`f\\in C^{3}` (i.e., :math:`f` has at least 3 continous + 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}`: + + .. math:: + + \\eta_{i} = f_{i}^{\\left(1\\right)} - + \\left[ \\alpha f\\left(x_{i}\\right) + + \\beta f\\left(x_{i} + h_{d}\\right) + + \\gamma f\\left(x_{i}-h_{s}\\right) + \\right] + + By substituting :math:`f(x_{i} + h_{d})` and :math:`f(x_{i} - h_{s})` + with their Taylor series expansion, this translates into solving + the following the linear system: + + .. math:: + + \\left\\{ + \\begin{array}{r} + \\alpha+\\beta+\\gamma=0 \\\\ + -\\beta h_{d}+\\gamma h_{s}=1 \\\\ + \\beta h_{d}^{2}+\\gamma h_{s}^{2}=0 + \\end{array} + \\right. + + The resulting approximation of :math:`f_{i}^{(1)}` is the following: + + .. math:: + + \\hat f_{i}^{(1)} = + \\frac{ + h_{s}^{2}f\\left(x_{i} + h_{d}\\right) + + \\left(h_{d}^{2} - h_{s}^{2}\\right)f\\left(x_{i}\\right) + - h_{d}^{2}f\\left(x_{i}-h_{s}\\right)} + { h_{s}h_{d}\\left(h_{d} + h_{s}\\right)} + + \mathcal{O}\\left(\\frac{h_{d}h_{s}^{2} + + h_{s}h_{d}^{2}}{h_{d} + + h_{s}}\\right) + + It is worth noting that if :math:`h_{s}=h_{d}` + (i.e., data are evenly spaced) + we find the standard second order approximation: + + .. math:: + + \\hat f_{i}^{(1)}= + \\frac{f\\left(x_{i+1}\\right) - f\\left(x_{i-1}\\right)}{2h} + + \mathcal{O}\\left(h^{2}\\right) + + With a similar procedure the forward/backward approximations used for + boundaries can be derived. + + References + ---------- + .. [1] Quarteroni A., Sacco R., Saleri F. (2007) Numerical Mathematics + (Texts in Applied Mathematics). New York: Springer. + .. [2] Durran D. R. (1999) Numerical Methods for Wave Equations + in Geophysical Fluid Dynamics. New York: Springer. + .. [3] Fornberg B. (1988) Generation of Finite Difference Formulas on + Arbitrarily Spaced Grids, + Mathematics of Computation 51, no. 184 : 699-706. + `PDF `_. """ f = np.asanyarray(f) N = len(f.shape) # number of dimensions @@ -1576,22 +1690,32 @@ def gradient(f, *varargs, **kwargs): if max(axes) >= N or min(axes) < 0: raise ValueError("'axis' entry is out of bounds") - if len(set(axes)) != len(axes): + len_axes = len(axes) + if len(set(axes)) != len_axes: raise ValueError("duplicate value in 'axis'") n = len(varargs) if n == 0: - dx = [1.0]*N - elif n == 1: - dx = [varargs[0]]*N - elif n == len(axes): + dx = [1.0] * len_axes + elif n == len_axes or (n == 1 and np.isscalar(varargs[0])): dx = list(varargs) + for i, distances in enumerate(dx): + if np.isscalar(distances): + continue + if len(distances) != f.shape[axes[i]]: + raise ValueError("distances must be either scalars or match " + "the length of the corresponding dimension") + diffx = np.diff(dx[i]) + # if distances are constant reduce to the scalar case + # since it brings a consistent speedup + if (diffx == diffx[0]).all(): + diffx = diffx[0] + dx[i] = diffx + if len(dx) == 1: + dx *= len_axes else: - raise SyntaxError( - "invalid number of arguments") - if any([not np.isscalar(dxi) for dxi in dx]): - raise ValueError("distances must be scalars") - + raise TypeError("invalid number of arguments") + edge_order = kwargs.pop('edge_order', 1) if kwargs: raise TypeError('"{}" are not valid keyword arguments.'.format( @@ -1631,62 +1755,88 @@ def gradient(f, *varargs, **kwargs): y = f for i, axis in enumerate(axes): - - if y.shape[axis] < 2: + if y.shape[axis] < edge_order + 1: raise ValueError( "Shape of array too small to calculate a numerical gradient, " - "at least two elements are required.") - - # Numerical differentiation: 1st order edges, 2nd order interior - if y.shape[axis] == 2 or edge_order == 1: - # Use first order differences for time data - out = np.empty_like(y, dtype=otype) - - slice1[axis] = slice(1, -1) - slice2[axis] = slice(2, None) - slice3[axis] = slice(None, -2) - # 1D equivalent -- out[1:-1] = (y[2:] - y[:-2])/2.0 - out[slice1] = (y[slice2] - y[slice3])/2.0 - + "at least (edge_order + 1) elements are required.") + # result allocation + out = np.empty_like(y, dtype=otype) + + uniform_spacing = np.isscalar(dx[i]) + + # Numerical differentiation: 2nd order interior + slice1[axis] = slice(1, -1) + slice2[axis] = slice(None, -2) + slice3[axis] = slice(1, -1) + slice4[axis] = slice(2, None) + + if uniform_spacing: + out[slice1] = (f[slice4] - f[slice2]) / (2. * dx[i]) + else: + dx1 = dx[i][0:-1] + dx2 = dx[i][1:] + a = -(dx2)/(dx1 * (dx1 + dx2)) + b = (dx2 - dx1) / (dx1 * dx2) + c = dx1 / (dx2 * (dx1 + dx2)) + # fix the shape for broadcasting + shape = np.ones(N, dtype=int) + shape[axis] = -1 + a.shape = b.shape = c.shape = shape + # 1D equivalent -- out[1:-1] = a * f[:-2] + b * f[1:-1] + c * f[2:] + out[slice1] = a * f[slice2] + b * f[slice3] + c * f[slice4] + + # Numerical differentiation: 1st order edges + if edge_order == 1: slice1[axis] = 0 slice2[axis] = 1 slice3[axis] = 0 - # 1D equivalent -- out[0] = (y[1] - y[0]) - out[slice1] = (y[slice2] - y[slice3]) - + dx_0 = dx[i] if uniform_spacing else dx[i][0] + # 1D equivalent -- out[0] = (y[1] - y[0]) / (x[1] - x[0]) + out[slice1] = (y[slice2] - y[slice3]) / dx_0 + slice1[axis] = -1 slice2[axis] = -1 slice3[axis] = -2 - # 1D equivalent -- out[-1] = (y[-1] - y[-2]) - out[slice1] = (y[slice2] - y[slice3]) - - # Numerical differentiation: 2st order edges, 2nd order interior + dx_n = dx[i] if uniform_spacing else dx[i][-1] + # 1D equivalent -- out[-1] = (y[-1] - y[-2]) / (x[-1] - x[-2]) + out[slice1] = (y[slice2] - y[slice3]) / dx_n + + # Numerical differentiation: 2nd order edges else: - # Use second order differences where possible - out = np.empty_like(y, dtype=otype) - - slice1[axis] = slice(1, -1) - slice2[axis] = slice(2, None) - slice3[axis] = slice(None, -2) - # 1D equivalent -- out[1:-1] = (y[2:] - y[:-2])/2.0 - out[slice1] = (y[slice2] - y[slice3])/2.0 - slice1[axis] = 0 slice2[axis] = 0 slice3[axis] = 1 slice4[axis] = 2 - # 1D equivalent -- out[0] = -(3*y[0] - 4*y[1] + y[2]) / 2.0 - out[slice1] = -(3.0*y[slice2] - 4.0*y[slice3] + y[slice4])/2.0 - + if uniform_spacing: + a = -1.5 / dx[i] + b = 2. / dx[i] + c = -0.5 / dx[i] + else: + dx1 = dx[i][0] + dx2 = dx[i][1] + a = -(2. * dx1 + dx2)/(dx1 * (dx1 + dx2)) + b = (dx1 + dx2) / (dx1 * dx2) + c = - dx1 / (dx2 * (dx1 + dx2)) + # 1D equivalent -- out[0] = a * y[0] + b * y[1] + c * y[2] + out[slice1] = a * y[slice2] + b * y[slice3] + c * y[slice4] + slice1[axis] = -1 - slice2[axis] = -1 + slice2[axis] = -3 slice3[axis] = -2 - slice4[axis] = -3 - # 1D equivalent -- out[-1] = (3*y[-1] - 4*y[-2] + y[-3]) - out[slice1] = (3.0*y[slice2] - 4.0*y[slice3] + y[slice4])/2.0 - - # divide by step size - out /= dx[i] + slice4[axis] = -1 + if uniform_spacing: + a = 0.5 / dx[i] + b = -2. / dx[i] + c = 1.5 / dx[i] + else: + dx1 = dx[i][-2] + dx2 = dx[i][-1] + a = (dx2) / (dx1 * (dx1 + dx2)) + b = - (dx2 + dx1) / (dx1 * dx2) + c = (2. * dx2 + dx1) / (dx2 * (dx1 + dx2)) + # 1D equivalent -- out[-1] = a * f[-3] + b * f[-2] + c * f[-1] + out[slice1] = a * y[slice2] + b * y[slice3] + c * y[slice4] + outvals.append(out) # reset the slice object in this dimension to ":" @@ -1695,7 +1845,7 @@ def gradient(f, *varargs, **kwargs): slice3[axis] = slice(None) slice4[axis] = slice(None) - if len(axes) == 1: + if len_axes == 1: return outvals[0] else: return outvals @@ -2746,9 +2896,9 @@ def cov(m, y=None, rowvar=True, bias=False, ddof=None, fweights=None, contain observations. bias : bool, optional Default normalization (False) is by ``(N - 1)``, where ``N`` is the - number of observations given (unbiased estimate). If `bias` is True, then - normalization is by ``N``. These values can be overridden by using the - keyword ``ddof`` in numpy versions >= 1.5. + number of observations given (unbiased estimate). If `bias` is True, + then normalization is by ``N``. These values can be overridden by using + the keyword ``ddof`` in numpy versions >= 1.5. ddof : int, optional If not ``None`` the default value implied by `bias` is overridden. Note that ``ddof=1`` will return the unbiased estimate, even if both @@ -2912,7 +3062,8 @@ def cov(m, y=None, rowvar=True, bias=False, ddof=None, fweights=None, fact = w_sum - ddof*sum(w*aweights)/w_sum if fact <= 0: - warnings.warn("Degrees of freedom <= 0 for slice", RuntimeWarning, stacklevel=2) + warnings.warn("Degrees of freedom <= 0 for slice", + RuntimeWarning, stacklevel=2) fact = 0.0 X -= avg[:, None] @@ -4665,9 +4816,9 @@ def delete(arr, obj, axis=None): # After removing the special handling of booleans and out of # bounds values, the conversion to the array can be removed. 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) + 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) obj = obj.astype(intp) if isinstance(_obj, (int, long, integer)): # optimization for a single value -- cgit v1.2.1 From 48783e5ceb7f60c33db81ab72e5024f42b220990 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Fri, 24 Feb 2017 16:46:58 +0000 Subject: MAINT: replace len(x.shape) with x.ndim --- numpy/lib/function_base.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'numpy/lib/function_base.py') diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index fc49a6fd7..1cf57d617 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -1674,7 +1674,7 @@ def gradient(f, *varargs, **kwargs): S0025-5718-1988-0935077-0/S0025-5718-1988-0935077-0.pdf>`_. """ f = np.asanyarray(f) - N = len(f.shape) # number of dimensions + N = f.ndim # number of dimensions axes = kwargs.pop('axis', None) if axes is None: @@ -1900,7 +1900,7 @@ def diff(a, n=1, axis=-1): raise ValueError( "order must be non-negative but got " + repr(n)) a = asanyarray(a) - nd = len(a.shape) + nd = a.ndim slice1 = [slice(None)]*nd slice2 = [slice(None)]*nd slice1[axis] = slice(1, None) @@ -2144,7 +2144,7 @@ def unwrap(p, discont=pi, axis=-1): """ p = asarray(p) - nd = len(p.shape) + nd = p.ndim dd = diff(p, axis=axis) slice1 = [slice(None, None)]*nd # full slices slice1[axis] = slice(1, None) @@ -4488,7 +4488,7 @@ def trapz(y, x=None, dx=1.0, axis=-1): d = d.reshape(shape) else: d = diff(x, axis=axis) - nd = len(y.shape) + nd = y.ndim slice1 = [slice(None)]*nd slice2 = [slice(None)]*nd slice1[axis] = slice(1, None) -- cgit v1.2.1 From d7d3e212ce1ff176c718485aed889c77a48ef88f Mon Sep 17 00:00:00 2001 From: Charles Harris Date: Fri, 24 Feb 2017 13:58:48 -0700 Subject: MAINT: Fix use of Python 2.6 deprecated escape sequences. Closes #8687. --- numpy/lib/function_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'numpy/lib/function_base.py') diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index fc49a6fd7..bee60fa20 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -1644,7 +1644,7 @@ def gradient(f, *varargs, **kwargs): + \\left(h_{d}^{2} - h_{s}^{2}\\right)f\\left(x_{i}\\right) - h_{d}^{2}f\\left(x_{i}-h_{s}\\right)} { h_{s}h_{d}\\left(h_{d} + h_{s}\\right)} - + \mathcal{O}\\left(\\frac{h_{d}h_{s}^{2} + + \\mathcal{O}\\left(\\frac{h_{d}h_{s}^{2} + h_{s}h_{d}^{2}}{h_{d} + h_{s}}\\right) @@ -1656,7 +1656,7 @@ def gradient(f, *varargs, **kwargs): \\hat f_{i}^{(1)}= \\frac{f\\left(x_{i+1}\\right) - f\\left(x_{i-1}\\right)}{2h} - + \mathcal{O}\\left(h^{2}\\right) + + \\mathcal{O}\\left(h^{2}\\right) With a similar procedure the forward/backward approximations used for boundaries can be derived. -- cgit v1.2.1 From 2cd13fec69551b1718763a03c180b85bf820f139 Mon Sep 17 00:00:00 2001 From: Joseph Fox-Rabinovitz Date: Fri, 24 Feb 2017 17:08:56 -0500 Subject: DOC: Added note to np.diff Also noted that type is preserved. [ci skip] --- numpy/lib/function_base.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'numpy/lib/function_base.py') diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index fc49a6fd7..a00ee8338 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -1872,12 +1872,19 @@ def diff(a, n=1, axis=-1): ------- diff : ndarray The n-th differences. The shape of the output is the same as `a` - except along `axis` where the dimension is smaller by `n`. + except along `axis` where the dimension is smaller by `n`. The + type of the output is the same as that of the input. See Also -------- gradient, ediff1d, cumsum + Notes + ----- + For boolean arrays, the preservation of type means that the result + will contain `False` when consecutive elements are the same and + `True` when they differ. + Examples -------- >>> x = np.array([1, 2, 4, 7, 0]) -- cgit v1.2.1 From 4f8e1a36d099c8ed901645daca3e99976835cd95 Mon Sep 17 00:00:00 2001 From: Michael Seifert Date: Sun, 26 Feb 2017 16:53:20 +0100 Subject: DOC: Fixed small mistakes in numpy.copy documentation. Including missing backticks around link, included a missing colon in example and removed excessive indentation before "doctest skip directive". [skip ci] --- numpy/lib/function_base.py | 136 ++++++++++++++++++++++----------------------- 1 file changed, 68 insertions(+), 68 deletions(-) (limited to 'numpy/lib/function_base.py') diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index d01a4a6cd..c54512c21 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -1462,7 +1462,7 @@ def copy(a, order='K'): Controls the memory layout of the copy. 'C' means C-order, 'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous, 'C' otherwise. 'K' means match the layout of `a` as closely - as possible. (Note that this function and :meth:ndarray.copy are very + as possible. (Note that this function and :meth:`ndarray.copy` are very similar, but have different default values for their order= arguments.) @@ -1473,9 +1473,9 @@ def copy(a, order='K'): Notes ----- - This is equivalent to + This is equivalent to: - >>> np.array(a, copy=True) #doctest: +SKIP + >>> np.array(a, copy=True) #doctest: +SKIP Examples -------- @@ -1515,18 +1515,18 @@ def gradient(f, *varargs, **kwargs): varargs : list of scalar or array, optional Spacing between f values. Default unitary spacing for all dimensions. Spacing can be specified using: - + 1. single scalar to specify a sample distance for all dimensions. 2. N scalars to specify a constant sample distance for each dimension. i.e. `dx`, `dy`, `dz`, ... - 3. N arrays to specify the coordinates of the values along each - dimension of F. The length of the array must match the size of + 3. N arrays to specify the coordinates of the values along each + dimension of F. The length of the array must match the size of the corresponding dimension 4. Any combination of N scalars/arrays with the meaning of 2. and 3. - + If `axis` is given, the number of varargs must equal the number of axes. Default: 1. - + edge_order : {1, 2}, optional Gradient is calculated using N-th order accurate differences at the boundaries. Default: 1. @@ -1535,8 +1535,8 @@ def gradient(f, *varargs, **kwargs): axis : None or int or tuple of ints, optional Gradient is calculated only along the given axis or axes - The default (axis = None) is to calculate the gradient for all the axes - of the input array. axis may be negative, in which case it counts from + The default (axis = None) is to calculate the gradient for all the axes + of the input array. axis may be negative, in which case it counts from the last to the first axis. .. versionadded:: 1.11.0 @@ -1547,7 +1547,7 @@ def gradient(f, *varargs, **kwargs): A set of ndarrays (or a single ndarray if there is only one dimension) corresponding to the derivatives of f with respect to each dimension. Each derivative has the same shape as f. - + Examples -------- >>> f = np.array([1, 2, 4, 7, 11, 16], dtype=np.float) @@ -1555,7 +1555,7 @@ def gradient(f, *varargs, **kwargs): array([ 1. , 1.5, 2.5, 3.5, 4.5, 5. ]) >>> np.gradient(f, 2) array([ 0.5 , 0.75, 1.25, 1.75, 2.25, 2.5 ]) - + Spacing can be also specified with an array that represents the coordinates of the values F along the dimensions. For instance a uniform spacing: @@ -1564,12 +1564,12 @@ def gradient(f, *varargs, **kwargs): >>> np.gradient(f, x) array([ 1. , 1.5, 2.5, 3.5, 4.5, 5. ]) - Or a non uniform one: - + Or a non uniform one: + >>> x = np.array([0., 1., 1.5, 3.5, 4., 6.], dtype=np.float) >>> np.gradient(f, x) array([ 1. , 3. , 3.5, 6.7, 6.9, 2.5]) - + For two dimensional arrays, the return will be two arrays ordered by axis. In this example the first array stands for the gradient in rows and the second one in columns direction: @@ -1579,7 +1579,7 @@ def gradient(f, *varargs, **kwargs): [ 2., 2., -1.]]), array([[ 1. , 2.5, 4. ], [ 1. , 1. , 1. ]])] - In this example the spacing is also specified: + In this example the spacing is also specified: uniform for axis=0 and non uniform for axis=1 >>> dx = 2. @@ -1590,7 +1590,7 @@ def gradient(f, *varargs, **kwargs): [ 2. , 1.7, 0.5]])] It is possible to specify how boundaries are treated using `edge_order` - + >>> x = np.array([0, 1, 2, 3, 4]) >>> f = x**2 >>> np.gradient(f, edge_order=1) @@ -1598,35 +1598,35 @@ def gradient(f, *varargs, **kwargs): >>> np.gradient(f, edge_order=2) array([-0., 2., 4., 6., 8.]) - The `axis` keyword can be used to specify a subset of axes of which the + The `axis` keyword can be used to specify a subset of axes of which the gradient is calculated - + >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]], dtype=np.float), axis=0) array([[ 2., 2., -1.], [ 2., 2., -1.]]) Notes ----- - Assuming that :math:`f\\in C^{3}` (i.e., :math:`f` has at least 3 continous - derivatives) and let be :math:`h_{*}` a non homogeneous stepsize, the - spacing the finite difference coefficients are computed by minimising + Assuming that :math:`f\\in C^{3}` (i.e., :math:`f` has at least 3 continous + 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}`: - - .. math:: - - \\eta_{i} = f_{i}^{\\left(1\\right)} - - \\left[ \\alpha f\\left(x_{i}\\right) + + + .. math:: + + \\eta_{i} = f_{i}^{\\left(1\\right)} - + \\left[ \\alpha f\\left(x_{i}\\right) + \\beta f\\left(x_{i} + h_{d}\\right) + \\gamma f\\left(x_{i}-h_{s}\\right) \\right] - - By substituting :math:`f(x_{i} + h_{d})` and :math:`f(x_{i} - h_{s})` - with their Taylor series expansion, this translates into solving + + By substituting :math:`f(x_{i} + h_{d})` and :math:`f(x_{i} - h_{s})` + with their Taylor series expansion, this translates into solving the following the linear system: - .. math:: + .. math:: - \\left\\{ + \\left\\{ \\begin{array}{r} \\alpha+\\beta+\\gamma=0 \\\\ -\\beta h_{d}+\\gamma h_{s}=1 \\\\ @@ -1636,40 +1636,40 @@ def gradient(f, *varargs, **kwargs): The resulting approximation of :math:`f_{i}^{(1)}` is the following: - .. math:: - - \\hat f_{i}^{(1)} = - \\frac{ - h_{s}^{2}f\\left(x_{i} + h_{d}\\right) - + \\left(h_{d}^{2} - h_{s}^{2}\\right)f\\left(x_{i}\\right) + .. math:: + + \\hat f_{i}^{(1)} = + \\frac{ + h_{s}^{2}f\\left(x_{i} + h_{d}\\right) + + \\left(h_{d}^{2} - h_{s}^{2}\\right)f\\left(x_{i}\\right) - h_{d}^{2}f\\left(x_{i}-h_{s}\\right)} { h_{s}h_{d}\\left(h_{d} + h_{s}\\right)} - + \\mathcal{O}\\left(\\frac{h_{d}h_{s}^{2} - + h_{s}h_{d}^{2}}{h_{d} + + \\mathcal{O}\\left(\\frac{h_{d}h_{s}^{2} + + h_{s}h_{d}^{2}}{h_{d} + h_{s}}\\right) - It is worth noting that if :math:`h_{s}=h_{d}` - (i.e., data are evenly spaced) + It is worth noting that if :math:`h_{s}=h_{d}` + (i.e., data are evenly spaced) we find the standard second order approximation: - - .. math:: - + + .. math:: + \\hat f_{i}^{(1)}= - \\frac{f\\left(x_{i+1}\\right) - f\\left(x_{i-1}\\right)}{2h} + \\frac{f\\left(x_{i+1}\\right) - f\\left(x_{i-1}\\right)}{2h} + \\mathcal{O}\\left(h^{2}\\right) - With a similar procedure the forward/backward approximations used for + With a similar procedure the forward/backward approximations used for boundaries can be derived. - + References ---------- - .. [1] Quarteroni A., Sacco R., Saleri F. (2007) Numerical Mathematics + .. [1] Quarteroni A., Sacco R., Saleri F. (2007) Numerical Mathematics (Texts in Applied Mathematics). New York: Springer. - .. [2] Durran D. R. (1999) Numerical Methods for Wave Equations + .. [2] Durran D. R. (1999) Numerical Methods for Wave Equations in Geophysical Fluid Dynamics. New York: Springer. - .. [3] Fornberg B. (1988) Generation of Finite Difference Formulas on - Arbitrarily Spaced Grids, - Mathematics of Computation 51, no. 184 : 699-706. + .. [3] Fornberg B. (1988) Generation of Finite Difference Formulas on + Arbitrarily Spaced Grids, + Mathematics of Computation 51, no. 184 : 699-706. `PDF `_. """ @@ -1707,15 +1707,15 @@ def gradient(f, *varargs, **kwargs): "the length of the corresponding dimension") diffx = np.diff(dx[i]) # if distances are constant reduce to the scalar case - # since it brings a consistent speedup - if (diffx == diffx[0]).all(): + # since it brings a consistent speedup + if (diffx == diffx[0]).all(): diffx = diffx[0] dx[i] = diffx if len(dx) == 1: dx *= len_axes else: raise TypeError("invalid number of arguments") - + edge_order = kwargs.pop('edge_order', 1) if kwargs: raise TypeError('"{}" are not valid keyword arguments.'.format( @@ -1762,14 +1762,14 @@ def gradient(f, *varargs, **kwargs): # result allocation out = np.empty_like(y, dtype=otype) - uniform_spacing = np.isscalar(dx[i]) + uniform_spacing = np.isscalar(dx[i]) # Numerical differentiation: 2nd order interior slice1[axis] = slice(1, -1) slice2[axis] = slice(None, -2) slice3[axis] = slice(1, -1) slice4[axis] = slice(2, None) - + if uniform_spacing: out[slice1] = (f[slice4] - f[slice2]) / (2. * dx[i]) else: @@ -1784,7 +1784,7 @@ def gradient(f, *varargs, **kwargs): a.shape = b.shape = c.shape = shape # 1D equivalent -- out[1:-1] = a * f[:-2] + b * f[1:-1] + c * f[2:] out[slice1] = a * f[slice2] + b * f[slice3] + c * f[slice4] - + # Numerical differentiation: 1st order edges if edge_order == 1: slice1[axis] = 0 @@ -1793,14 +1793,14 @@ def gradient(f, *varargs, **kwargs): dx_0 = dx[i] if uniform_spacing else dx[i][0] # 1D equivalent -- out[0] = (y[1] - y[0]) / (x[1] - x[0]) out[slice1] = (y[slice2] - y[slice3]) / dx_0 - + slice1[axis] = -1 slice2[axis] = -1 slice3[axis] = -2 dx_n = dx[i] if uniform_spacing else dx[i][-1] # 1D equivalent -- out[-1] = (y[-1] - y[-2]) / (x[-1] - x[-2]) out[slice1] = (y[slice2] - y[slice3]) / dx_n - + # Numerical differentiation: 2nd order edges else: slice1[axis] = 0 @@ -1819,7 +1819,7 @@ def gradient(f, *varargs, **kwargs): c = - dx1 / (dx2 * (dx1 + dx2)) # 1D equivalent -- out[0] = a * y[0] + b * y[1] + c * y[2] out[slice1] = a * y[slice2] + b * y[slice3] + c * y[slice4] - + slice1[axis] = -1 slice2[axis] = -3 slice3[axis] = -2 @@ -1835,8 +1835,8 @@ def gradient(f, *varargs, **kwargs): b = - (dx2 + dx1) / (dx1 * dx2) c = (2. * dx2 + dx1) / (dx2 * (dx1 + dx2)) # 1D equivalent -- out[-1] = a * f[-3] + b * f[-2] + c * f[-1] - out[slice1] = a * y[slice2] + b * y[slice3] + c * y[slice4] - + out[slice1] = a * y[slice2] + b * y[slice3] + c * y[slice4] + outvals.append(out) # reset the slice object in this dimension to ":" @@ -2903,8 +2903,8 @@ def cov(m, y=None, rowvar=True, bias=False, ddof=None, fweights=None, contain observations. bias : bool, optional Default normalization (False) is by ``(N - 1)``, where ``N`` is the - number of observations given (unbiased estimate). If `bias` is True, - then normalization is by ``N``. These values can be overridden by using + number of observations given (unbiased estimate). If `bias` is True, + then normalization is by ``N``. These values can be overridden by using the keyword ``ddof`` in numpy versions >= 1.5. ddof : int, optional If not ``None`` the default value implied by `bias` is overridden. @@ -3069,7 +3069,7 @@ def cov(m, y=None, rowvar=True, bias=False, ddof=None, fweights=None, fact = w_sum - ddof*sum(w*aweights)/w_sum if fact <= 0: - warnings.warn("Degrees of freedom <= 0 for slice", + warnings.warn("Degrees of freedom <= 0 for slice", RuntimeWarning, stacklevel=2) fact = 0.0 @@ -4823,7 +4823,7 @@ def delete(arr, obj, axis=None): # After removing the special handling of booleans and out of # bounds values, the conversion to the array can be removed. if obj.dtype == bool: - warnings.warn("in the future insert will treat boolean arrays and " + 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) obj = obj.astype(intp) -- cgit v1.2.1 From 1588ae39ffb51ea916f03510671aab711fdfb568 Mon Sep 17 00:00:00 2001 From: Duke Vijitbenjaronk Date: Tue, 7 Mar 2017 11:11:53 -0600 Subject: BUG: Fix np.average with object array weights Fixes #8696 --- numpy/lib/function_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'numpy/lib/function_base.py') diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index c54512c21..0903790bd 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -1135,7 +1135,7 @@ def average(a, axis=None, weights=None, returned=False): wgt = wgt.swapaxes(-1, axis) scl = wgt.sum(axis=axis, dtype=result_dtype) - if (scl == 0.0).any(): + if np.any(scl == 0.0): raise ZeroDivisionError( "Weights sum to zero, can't be normalized") -- cgit v1.2.1 From 9f7a9e00eec6f0a795c859ff8328a6b82603e506 Mon Sep 17 00:00:00 2001 From: Egor Klenin Date: Mon, 20 Mar 2017 16:26:59 +0300 Subject: DOC: Include np. prefix in meshgrid examples Add "np." prefix to meshgrid calls for consistency --- numpy/lib/function_base.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'numpy/lib/function_base.py') diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index 0903790bd..cc0e8feeb 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -4601,12 +4601,12 @@ def meshgrid(*xi, **kwargs): 'xy' indexing and (M, N, P) for 'ij' indexing. The difference is illustrated by the following code snippet:: - xv, yv = meshgrid(x, y, sparse=False, indexing='ij') + xv, yv = np.meshgrid(x, y, sparse=False, indexing='ij') for i in range(nx): for j in range(ny): # treat xv[i,j], yv[i,j] - xv, yv = meshgrid(x, y, sparse=False, indexing='xy') + xv, yv = np.meshgrid(x, y, sparse=False, indexing='xy') for i in range(nx): for j in range(ny): # treat xv[j,i], yv[j,i] @@ -4625,14 +4625,14 @@ def meshgrid(*xi, **kwargs): >>> nx, ny = (3, 2) >>> x = np.linspace(0, 1, nx) >>> y = np.linspace(0, 1, ny) - >>> xv, yv = meshgrid(x, y) + >>> xv, yv = np.meshgrid(x, y) >>> xv array([[ 0. , 0.5, 1. ], [ 0. , 0.5, 1. ]]) >>> yv array([[ 0., 0., 0.], [ 1., 1., 1.]]) - >>> xv, yv = meshgrid(x, y, sparse=True) # make sparse output arrays + >>> xv, yv = np.meshgrid(x, y, sparse=True) # make sparse output arrays >>> xv array([[ 0. , 0.5, 1. ]]) >>> yv @@ -4643,7 +4643,7 @@ def meshgrid(*xi, **kwargs): >>> x = np.arange(-5, 5, 0.1) >>> y = np.arange(-5, 5, 0.1) - >>> xx, yy = meshgrid(x, y, sparse=True) + >>> xx, yy = np.meshgrid(x, y, sparse=True) >>> z = np.sin(xx**2 + yy**2) / (xx**2 + yy**2) >>> h = plt.contourf(x,y,z) -- cgit v1.2.1 From efa1bd2c0de6cd9c07b410002f2e1c0bae8cf385 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Sun, 26 Mar 2017 10:38:28 +0100 Subject: MAINT: Reuse _validate_axis in np.gradient This also means that its axis argument invokes operator.index like others do. _validate_axis currently accepts lists of axes, which is a bug. --- numpy/lib/function_base.py | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'numpy/lib/function_base.py') diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index cc0e8feeb..2a8a13caa 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -1679,21 +1679,10 @@ def gradient(f, *varargs, **kwargs): axes = kwargs.pop('axis', None) if axes is None: axes = tuple(range(N)) - # check axes to have correct type and no duplicate entries - if isinstance(axes, int): - axes = (axes,) - if not isinstance(axes, tuple): - raise TypeError("A tuple of integers or a single integer is required") - - # normalize axis values: - axes = tuple(x + N if x < 0 else x for x in axes) - if max(axes) >= N or min(axes) < 0: - raise ValueError("'axis' entry is out of bounds") + else: + axes = _nx._validate_axis(axes, N) len_axes = len(axes) - if len(set(axes)) != len_axes: - raise ValueError("duplicate value in 'axis'") - n = len(varargs) if n == 0: dx = [1.0] * len_axes -- cgit v1.2.1 From e3ed705e5d91b584e9191a20f3a4780d354271ff Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Sun, 26 Mar 2017 11:22:43 +0100 Subject: MAINT: Use _validate_axis inside _ureduce This fixes an omission where duplicate axes would only be detected when positive --- numpy/lib/function_base.py | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'numpy/lib/function_base.py') diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index 2a8a13caa..5b3af311b 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -12,7 +12,7 @@ from numpy.core import linspace, atleast_1d, atleast_2d, transpose from numpy.core.numeric import ( ones, zeros, arange, concatenate, array, asarray, asanyarray, empty, empty_like, ndarray, around, floor, ceil, take, dot, where, intp, - integer, isscalar, absolute + integer, isscalar, absolute, AxisError ) from numpy.core.umath import ( pi, multiply, add, arctan2, frompyfunc, cos, less_equal, sqrt, sin, @@ -3972,21 +3972,15 @@ def _ureduce(a, func, **kwargs): if axis is not None: keepdim = list(a.shape) nd = a.ndim - try: - axis = operator.index(axis) - if axis >= nd or axis < -nd: - raise IndexError("axis %d out of bounds (%d)" % (axis, a.ndim)) - keepdim[axis] = 1 - except TypeError: - sax = set() - for x in axis: - if x >= nd or x < -nd: - raise IndexError("axis %d out of bounds (%d)" % (x, nd)) - if x in sax: - raise ValueError("duplicate value in axis") - sax.add(x % nd) - keepdim[x] = 1 - keep = sax.symmetric_difference(frozenset(range(nd))) + axis = _nx._validate_axis(axis, nd) + + for ax in axis: + keepdim[ax] = 1 + + if len(axis) == 1: + kwargs['axis'] = axis[0] + else: + keep = set(range(nd)) - set(axis) nkeep = len(keep) # swap axis that should not be reduced to front for i, s in enumerate(sorted(keep)): @@ -4742,7 +4736,8 @@ def delete(arr, obj, axis=None): if ndim != 1: arr = arr.ravel() ndim = arr.ndim - axis = ndim - 1 + axis = -1 + if ndim == 0: # 2013-09-24, 1.9 warnings.warn( @@ -4753,6 +4748,8 @@ def delete(arr, obj, axis=None): else: return arr.copy(order=arrorder) + axis = normalize_axis_index(axis, ndim) + slobj = [slice(None)]*ndim N = arr.shape[axis] newshape = list(arr.shape) -- cgit v1.2.1 From 17466ad1839718c091c629bb647e881b7922a148 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Sun, 26 Mar 2017 11:30:23 +0100 Subject: MAINT: Rename _validate_axis, and document it --- numpy/lib/function_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'numpy/lib/function_base.py') diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index 5b3af311b..2e6de9ec7 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -1680,7 +1680,7 @@ def gradient(f, *varargs, **kwargs): if axes is None: axes = tuple(range(N)) else: - axes = _nx._validate_axis(axes, N) + axes = _nx.normalize_axis_tuple(axes, N) len_axes = len(axes) n = len(varargs) @@ -3972,7 +3972,7 @@ def _ureduce(a, func, **kwargs): if axis is not None: keepdim = list(a.shape) nd = a.ndim - axis = _nx._validate_axis(axis, nd) + axis = _nx.normalize_axis_tuple(axis, nd) for ax in axis: keepdim[ax] = 1 -- cgit v1.2.1 From eb12b7106fb2962167627af21bc0bef24f6f650d Mon Sep 17 00:00:00 2001 From: Baurzhan Muftakhidinov Date: Thu, 6 Apr 2017 15:12:23 +0500 Subject: DOC: Fix typos in percentile (#8900) --- numpy/lib/function_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'numpy/lib/function_base.py') diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index 2e6de9ec7..4a07815e8 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -4209,8 +4209,8 @@ def percentile(a, q, axis=None, out=None, Notes ----- Given a vector ``V`` of length ``N``, the ``q``-th percentile of - ``V`` is the value ``q/100`` of the way from the mimumum to the - maximum in in a sorted copy of ``V``. The values and distances of + ``V`` is the value ``q/100`` 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 percentile if the normalized ranking does not match the location of ``q`` exactly. This function is the same as -- cgit v1.2.1