summaryrefslogtreecommitdiff
path: root/numpy/lib/tests/test_function_base.py
diff options
context:
space:
mode:
Diffstat (limited to 'numpy/lib/tests/test_function_base.py')
-rw-r--r--numpy/lib/tests/test_function_base.py257
1 files changed, 176 insertions, 81 deletions
diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py
index 66110b479..b67a31b18 100644
--- a/numpy/lib/tests/test_function_base.py
+++ b/numpy/lib/tests/test_function_base.py
@@ -553,6 +553,11 @@ class TestInsert:
with pytest.raises(IndexError):
np.insert([0, 1, 2], np.array([], dtype=float), [])
+ @pytest.mark.parametrize('idx', [4, -4])
+ def test_index_out_of_bounds(self, idx):
+ with pytest.raises(IndexError, match='out of bounds'):
+ np.insert([0, 1, 2], [idx], [3, 4])
+
class TestAmax:
@@ -2862,7 +2867,7 @@ class TestPercentile:
assert_equal(np.percentile(x, 50), 1.75)
x[1] = np.nan
assert_equal(np.percentile(x, 0), np.nan)
- assert_equal(np.percentile(x, 0, interpolation='nearest'), np.nan)
+ assert_equal(np.percentile(x, 0, method='nearest'), np.nan)
def test_fraction(self):
x = [Fraction(i, 2) for i in range(8)]
@@ -2898,36 +2903,95 @@ class TestPercentile:
[1, 1, 1]])
assert_array_equal(np.percentile(x, 50, axis=0), [1, 1, 1])
- def test_linear(self):
-
- # Test defaults
- assert_equal(np.percentile(range(10), 50), 4.5)
-
- # explicitly specify interpolation_method 'linear' (the default)
- assert_equal(np.percentile(range(10), 50,
- interpolation='linear'), 4.5)
-
- def test_lower_higher(self):
-
- # interpolation_method 'lower'/'higher'
- assert_equal(np.percentile(range(10), 50,
- interpolation='lower'), 4)
- assert_equal(np.percentile(range(10), 50,
- interpolation='higher'), 5)
-
- def test_midpoint(self):
- assert_equal(np.percentile(range(10), 51,
- interpolation='midpoint'), 4.5)
- assert_equal(np.percentile(range(11), 51,
- interpolation='midpoint'), 5.5)
- assert_equal(np.percentile(range(11), 50,
- interpolation='midpoint'), 5)
-
- def test_nearest(self):
- assert_equal(np.percentile(range(10), 51,
- interpolation='nearest'), 5)
- assert_equal(np.percentile(range(10), 49,
- interpolation='nearest'), 4)
+ @pytest.mark.parametrize("dtype", np.typecodes["AllFloat"])
+ def test_linear_nan_1D(self, dtype):
+ # METHOD 1 of H&F
+ arr = np.asarray([15.0, np.NAN, 35.0, 40.0, 50.0], dtype=dtype)
+ res = np.percentile(
+ arr,
+ 40.0,
+ method="linear")
+ np.testing.assert_equal(res, np.NAN)
+ np.testing.assert_equal(res.dtype, arr.dtype)
+
+ H_F_TYPE_CODES = [(int_type, np.float64)
+ for int_type in np.typecodes["AllInteger"]
+ ] + [(np.float16, np.float64),
+ (np.float32, np.float64),
+ (np.float64, np.float64),
+ (np.longdouble, np.longdouble),
+ (np.complex64, np.complex128),
+ (np.complex128, np.complex128),
+ (np.clongdouble, np.clongdouble),
+ (np.dtype("O"), np.float64)]
+
+ @pytest.mark.parametrize(["input_dtype", "expected_dtype"], H_F_TYPE_CODES)
+ @pytest.mark.parametrize(["method", "expected"],
+ [("inverted_cdf", 20),
+ ("averaged_inverted_cdf", 27.5),
+ ("closest_observation", 20),
+ ("interpolated_inverted_cdf", 20),
+ ("hazen", 27.5),
+ ("weibull", 26),
+ ("linear", 29),
+ ("median_unbiased", 27),
+ ("normal_unbiased", 27.125),
+ ])
+ def test_linear_interpolation(self,
+ method,
+ expected,
+ input_dtype,
+ expected_dtype):
+ arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=input_dtype)
+ actual = np.percentile(arr, 40.0, method=method)
+
+ np.testing.assert_almost_equal(actual, expected, 14)
+
+ if method in ["inverted_cdf", "closest_observation"]:
+ if input_dtype == "O":
+ np.testing.assert_equal(np.asarray(actual).dtype, np.float64)
+ else:
+ np.testing.assert_equal(np.asarray(actual).dtype,
+ np.dtype(input_dtype))
+ else:
+ np.testing.assert_equal(np.asarray(actual).dtype,
+ np.dtype(expected_dtype))
+
+ TYPE_CODES = np.typecodes["AllInteger"] + np.typecodes["AllFloat"] + "O"
+
+ @pytest.mark.parametrize("dtype", TYPE_CODES)
+ def test_lower_higher(self, dtype):
+ assert_equal(np.percentile(np.arange(10, dtype=dtype), 50,
+ method='lower'), 4)
+ assert_equal(np.percentile(np.arange(10, dtype=dtype), 50,
+ method='higher'), 5)
+
+ @pytest.mark.parametrize("dtype", TYPE_CODES)
+ def test_midpoint(self, dtype):
+ assert_equal(np.percentile(np.arange(10, dtype=dtype), 51,
+ method='midpoint'), 4.5)
+ assert_equal(np.percentile(np.arange(9, dtype=dtype) + 1, 50,
+ method='midpoint'), 5)
+ assert_equal(np.percentile(np.arange(11, dtype=dtype), 51,
+ method='midpoint'), 5.5)
+ assert_equal(np.percentile(np.arange(11, dtype=dtype), 50,
+ method='midpoint'), 5)
+
+ @pytest.mark.parametrize("dtype", TYPE_CODES)
+ def test_nearest(self, dtype):
+ assert_equal(np.percentile(np.arange(10, dtype=dtype), 51,
+ method='nearest'), 5)
+ assert_equal(np.percentile(np.arange(10, dtype=dtype), 49,
+ method='nearest'), 4)
+
+ def test_linear_interpolation_extrapolation(self):
+ arr = np.random.rand(5)
+
+ actual = np.percentile(arr, 100)
+ np.testing.assert_equal(actual, arr.max())
+
+ actual = np.percentile(arr, 0)
+ np.testing.assert_equal(actual, arr.min())
def test_sequence(self):
x = np.arange(8) * 0.5
@@ -2955,19 +3019,19 @@ class TestPercentile:
assert_equal(
np.percentile(x, (25, 50, 75), axis=1).shape, (3, 3, 5, 6))
assert_equal(np.percentile(x, (25, 50),
- interpolation="higher").shape, (2,))
+ method="higher").shape, (2,))
assert_equal(np.percentile(x, (25, 50, 75),
- interpolation="higher").shape, (3,))
+ method="higher").shape, (3,))
assert_equal(np.percentile(x, (25, 50), axis=0,
- interpolation="higher").shape, (2, 4, 5, 6))
+ method="higher").shape, (2, 4, 5, 6))
assert_equal(np.percentile(x, (25, 50), axis=1,
- interpolation="higher").shape, (2, 3, 5, 6))
+ method="higher").shape, (2, 3, 5, 6))
assert_equal(np.percentile(x, (25, 50), axis=2,
- interpolation="higher").shape, (2, 3, 4, 6))
+ method="higher").shape, (2, 3, 4, 6))
assert_equal(np.percentile(x, (25, 50), axis=3,
- interpolation="higher").shape, (2, 3, 4, 5))
+ method="higher").shape, (2, 3, 4, 5))
assert_equal(np.percentile(x, (25, 50, 75), axis=1,
- interpolation="higher").shape, (3, 3, 5, 6))
+ method="higher").shape, (3, 3, 5, 6))
def test_scalar_q(self):
# test for no empty dimensions for compatibility with old percentile
@@ -2993,33 +3057,33 @@ class TestPercentile:
# test for no empty dimensions for compatibility with old percentile
x = np.arange(12).reshape(3, 4)
- assert_equal(np.percentile(x, 50, interpolation='lower'), 5.)
+ assert_equal(np.percentile(x, 50, method='lower'), 5.)
assert_(np.isscalar(np.percentile(x, 50)))
r0 = np.array([4., 5., 6., 7.])
- c0 = np.percentile(x, 50, interpolation='lower', axis=0)
+ c0 = np.percentile(x, 50, method='lower', axis=0)
assert_equal(c0, r0)
assert_equal(c0.shape, r0.shape)
r1 = np.array([1., 5., 9.])
- c1 = np.percentile(x, 50, interpolation='lower', axis=1)
+ c1 = np.percentile(x, 50, method='lower', axis=1)
assert_almost_equal(c1, r1)
assert_equal(c1.shape, r1.shape)
out = np.empty((), dtype=x.dtype)
- c = np.percentile(x, 50, interpolation='lower', out=out)
+ c = np.percentile(x, 50, method='lower', out=out)
assert_equal(c, 5)
assert_equal(out, 5)
out = np.empty(4, dtype=x.dtype)
- c = np.percentile(x, 50, interpolation='lower', axis=0, out=out)
+ c = np.percentile(x, 50, method='lower', axis=0, out=out)
assert_equal(c, r0)
assert_equal(out, r0)
out = np.empty(3, dtype=x.dtype)
- c = np.percentile(x, 50, interpolation='lower', axis=1, out=out)
+ c = np.percentile(x, 50, method='lower', axis=1, out=out)
assert_equal(c, r1)
assert_equal(out, r1)
def test_exception(self):
assert_raises(ValueError, np.percentile, [1, 2], 56,
- interpolation='foobar')
+ method='foobar')
assert_raises(ValueError, np.percentile, [1], 101)
assert_raises(ValueError, np.percentile, [1], -1)
assert_raises(ValueError, np.percentile, [1], list(range(50)) + [101])
@@ -3033,18 +3097,18 @@ class TestPercentile:
y = np.zeros((3,))
p = (1, 2, 3)
np.percentile(x, p, out=y)
- assert_equal(y, np.percentile(x, p))
+ assert_equal(np.percentile(x, p), y)
x = np.array([[1, 2, 3],
[4, 5, 6]])
y = np.zeros((3, 3))
np.percentile(x, p, axis=0, out=y)
- assert_equal(y, np.percentile(x, p, axis=0))
+ assert_equal(np.percentile(x, p, axis=0), y)
y = np.zeros((3, 2))
np.percentile(x, p, axis=1, out=y)
- assert_equal(y, np.percentile(x, p, axis=1))
+ assert_equal(np.percentile(x, p, axis=1), y)
x = np.arange(12).reshape(3, 4)
# q.dim > 1, float
@@ -3060,12 +3124,12 @@ class TestPercentile:
# q.dim > 1, int
r0 = np.array([[0, 1, 2, 3], [4, 5, 6, 7]])
out = np.empty((2, 4), dtype=x.dtype)
- c = np.percentile(x, (25, 50), interpolation='lower', axis=0, out=out)
+ c = np.percentile(x, (25, 50), method='lower', axis=0, out=out)
assert_equal(c, r0)
assert_equal(out, r0)
r1 = np.array([[0, 4, 8], [1, 5, 9]])
out = np.empty((2, 3), dtype=x.dtype)
- c = np.percentile(x, (25, 50), interpolation='lower', axis=1, out=out)
+ c = np.percentile(x, (25, 50), method='lower', axis=1, out=out)
assert_equal(c, r1)
assert_equal(out, r1)
@@ -3082,10 +3146,10 @@ class TestPercentile:
assert_array_equal(np.percentile(d, 50, axis=-4).shape, (1, 2, 1))
assert_array_equal(np.percentile(d, 50, axis=2,
- interpolation='midpoint').shape,
+ method='midpoint').shape,
(11, 1, 1))
assert_array_equal(np.percentile(d, 50, axis=-2,
- interpolation='midpoint').shape,
+ method='midpoint').shape,
(11, 1, 1))
assert_array_equal(np.array(np.percentile(d, [10, 50], axis=0)).shape,
@@ -3108,10 +3172,10 @@ class TestPercentile:
def test_no_p_overwrite(self):
p = np.linspace(0., 100., num=5)
- np.percentile(np.arange(100.), p, interpolation="midpoint")
+ np.percentile(np.arange(100.), p, method="midpoint")
assert_array_equal(p, np.linspace(0., 100., num=5))
p = np.linspace(0., 100., num=5).tolist()
- np.percentile(np.arange(100.), p, interpolation="midpoint")
+ np.percentile(np.arange(100.), p, method="midpoint")
assert_array_equal(p, np.linspace(0., 100., num=5).tolist())
def test_percentile_overwrite(self):
@@ -3189,14 +3253,14 @@ class TestPercentile:
o = np.zeros((4,))
d = np.ones((3, 4))
assert_equal(np.percentile(d, 0, 0, out=o), o)
- assert_equal(np.percentile(d, 0, 0, interpolation='nearest', out=o), o)
+ assert_equal(np.percentile(d, 0, 0, method='nearest', out=o), o)
o = np.zeros((3,))
assert_equal(np.percentile(d, 1, 1, out=o), o)
- assert_equal(np.percentile(d, 1, 1, interpolation='nearest', out=o), o)
+ assert_equal(np.percentile(d, 1, 1, method='nearest', out=o), o)
o = np.zeros(())
assert_equal(np.percentile(d, 2, out=o), o)
- assert_equal(np.percentile(d, 2, interpolation='nearest', out=o), o)
+ assert_equal(np.percentile(d, 2, method='nearest', out=o), o)
def test_out_nan(self):
with warnings.catch_warnings(record=True):
@@ -3206,15 +3270,15 @@ class TestPercentile:
d[2, 1] = np.nan
assert_equal(np.percentile(d, 0, 0, out=o), o)
assert_equal(
- np.percentile(d, 0, 0, interpolation='nearest', out=o), o)
+ np.percentile(d, 0, 0, method='nearest', out=o), o)
o = np.zeros((3,))
assert_equal(np.percentile(d, 1, 1, out=o), o)
assert_equal(
- np.percentile(d, 1, 1, interpolation='nearest', out=o), o)
+ np.percentile(d, 1, 1, method='nearest', out=o), o)
o = np.zeros(())
assert_equal(np.percentile(d, 1, out=o), o)
assert_equal(
- np.percentile(d, 1, interpolation='nearest', out=o), o)
+ np.percentile(d, 1, method='nearest', out=o), o)
def test_nan_behavior(self):
a = np.arange(24, dtype=float)
@@ -3269,13 +3333,13 @@ class TestPercentile:
b[:, 1] = np.nan
b[:, 2] = np.nan
assert_equal(np.percentile(a, [0.3, 0.6], (0, 2)), b)
- # axis02 not zerod with nearest interpolation
+ # axis02 not zerod with method='nearest'
b = np.percentile(np.arange(24, dtype=float).reshape(2, 3, 4),
- [0.3, 0.6], (0, 2), interpolation='nearest')
+ [0.3, 0.6], (0, 2), method='nearest')
b[:, 1] = np.nan
b[:, 2] = np.nan
assert_equal(np.percentile(
- a, [0.3, 0.6], (0, 2), interpolation='nearest'), b)
+ a, [0.3, 0.6], (0, 2), method='nearest'), b)
def test_nan_q(self):
# GH18830
@@ -3288,15 +3352,25 @@ class TestPercentile:
with pytest.raises(ValueError, match="Percentiles must be in"):
np.percentile([1, 2, 3, 4.0], q)
+
class TestQuantile:
# most of this is already tested by TestPercentile
+ def test_max_ulp(self):
+ x = [0.0, 0.2, 0.4]
+ a = np.quantile(x, 0.45)
+ # The default linear method would result in 0 + 0.2 * (0.45/2) = 0.18.
+ # 0.18 is not exactly representable and the formula leads to a 1 ULP
+ # different result. Ensure it is this exact within 1 ULP, see gh-20331.
+ np.testing.assert_array_max_ulp(a, 0.18, maxulp=1)
+
def test_basic(self):
x = np.arange(8) * 0.5
assert_equal(np.quantile(x, 0), 0.)
assert_equal(np.quantile(x, 1), 3.5)
assert_equal(np.quantile(x, 0.5), 1.75)
+ @pytest.mark.xfail(reason="See gh-19154")
def test_correct_quantile_value(self):
a = np.array([True])
tf_quant = np.quantile(True, False)
@@ -3305,12 +3379,11 @@ class TestQuantile:
a = np.array([False, True, True])
quant_res = np.quantile(a, a)
assert_array_equal(quant_res, a)
- assert_equal(a.dtype, quant_res.dtype)
+ assert_equal(quant_res.dtype, a.dtype)
def test_fraction(self):
# fractional input, integral quantile
x = [Fraction(i, 2) for i in range(8)]
-
q = np.quantile(x, 0)
assert_equal(q, 0)
assert_equal(type(q), Fraction)
@@ -3339,20 +3412,36 @@ class TestQuantile:
# this is worth retesting, because quantile does not make a copy
p0 = np.array([0, 0.75, 0.25, 0.5, 1.0])
p = p0.copy()
- np.quantile(np.arange(100.), p, interpolation="midpoint")
+ np.quantile(np.arange(100.), p, method="midpoint")
assert_array_equal(p, p0)
p0 = p0.tolist()
p = p.tolist()
- np.quantile(np.arange(100.), p, interpolation="midpoint")
+ np.quantile(np.arange(100.), p, method="midpoint")
assert_array_equal(p, p0)
- def test_quantile_monotonic(self):
+ @pytest.mark.parametrize("dtype", np.typecodes["AllInteger"])
+ def test_quantile_preserve_int_type(self, dtype):
+ res = np.quantile(np.array([1, 2], dtype=dtype), [0.5],
+ method="nearest")
+ assert res.dtype == dtype
+
+ @pytest.mark.parametrize("method",
+ ['inverted_cdf', 'averaged_inverted_cdf', 'closest_observation',
+ 'interpolated_inverted_cdf', 'hazen', 'weibull', 'linear',
+ 'median_unbiased', 'normal_unbiased',
+ 'nearest', 'lower', 'higher', 'midpoint'])
+ def test_quantile_monotonic(self, method):
# GH 14685
# test that the return value of quantile is monotonic if p0 is ordered
- p0 = np.arange(0, 1, 0.01)
+ # Also tests that the boundary values are not mishandled.
+ p0 = np.linspace(0, 1, 101)
quantile = np.quantile(np.array([0, 1, 1, 2, 2, 3, 3, 4, 5, 5, 1, 1, 9, 9, 9,
- 8, 8, 7]) * 0.1, p0)
+ 8, 8, 7]) * 0.1, p0, method=method)
+ assert_equal(np.sort(quantile), quantile)
+
+ # Also test one where the number of data points is clearly divisible:
+ quantile = np.quantile([0., 1., 2., 3.], p0, method=method)
assert_equal(np.sort(quantile), quantile)
@hypothesis.given(
@@ -3365,6 +3454,12 @@ class TestQuantile:
quantile = np.quantile(arr, p0)
assert_equal(np.sort(quantile), quantile)
+ def test_quantile_scalar_nan(self):
+ a = np.array([[10., 7., 4.], [3., 2., 1.]])
+ a[0][1] = np.nan
+ actual = np.quantile(a, 0.5)
+ assert np.isscalar(actual)
+ assert_equal(np.quantile(a, 0.5), np.nan)
class TestLerp:
@hypothesis.given(t0=st.floats(allow_nan=False, allow_infinity=False,
@@ -3375,9 +3470,9 @@ class TestLerp:
min_value=-1e300, max_value=1e300),
b = st.floats(allow_nan=False, allow_infinity=False,
min_value=-1e300, max_value=1e300))
- def test_lerp_monotonic(self, t0, t1, a, b):
- l0 = np.lib.function_base._lerp(a, b, t0)
- l1 = np.lib.function_base._lerp(a, b, t1)
+ def test_linear_interpolation_formula_monotonic(self, t0, t1, a, b):
+ l0 = nfb._lerp(a, b, t0)
+ l1 = nfb._lerp(a, b, t1)
if t0 == t1 or a == b:
assert l0 == l1 # uninteresting
elif (t0 < t1) == (a < b):
@@ -3391,11 +3486,11 @@ class TestLerp:
min_value=-1e300, max_value=1e300),
b=st.floats(allow_nan=False, allow_infinity=False,
min_value=-1e300, max_value=1e300))
- def test_lerp_bounded(self, t, a, b):
+ def test_linear_interpolation_formula_bounded(self, t, a, b):
if a <= b:
- assert a <= np.lib.function_base._lerp(a, b, t) <= b
+ assert a <= nfb._lerp(a, b, t) <= b
else:
- assert b <= np.lib.function_base._lerp(a, b, t) <= a
+ assert b <= nfb._lerp(a, b, t) <= a
@hypothesis.given(t=st.floats(allow_nan=False, allow_infinity=False,
min_value=0, max_value=1),
@@ -3403,17 +3498,17 @@ class TestLerp:
min_value=-1e300, max_value=1e300),
b=st.floats(allow_nan=False, allow_infinity=False,
min_value=-1e300, max_value=1e300))
- def test_lerp_symmetric(self, t, a, b):
+ def test_linear_interpolation_formula_symmetric(self, t, a, b):
# double subtraction is needed to remove the extra precision of t < 0.5
- left = np.lib.function_base._lerp(a, b, 1 - (1 - t))
- right = np.lib.function_base._lerp(b, a, 1 - t)
+ left = nfb._lerp(a, b, 1 - (1 - t))
+ right = nfb._lerp(b, a, 1 - t)
assert left == right
- def test_lerp_0d_inputs(self):
+ def test_linear_interpolation_formula_0d_inputs(self):
a = np.array(2)
b = np.array(5)
t = np.array(0.2)
- assert np.lib.function_base._lerp(a, b, t) == 2.6
+ assert nfb._lerp(a, b, t) == 2.6
class TestMedian: