From dfee8851c65276907eedd084ff40334ea7d46865 Mon Sep 17 00:00:00 2001 From: Max Kellermeier Date: Sun, 2 Aug 2020 18:10:01 +0200 Subject: Tests added according to #14877, obsolete comments removed. --- numpy/lib/tests/test_function_base.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index eb2fc3311..878fb3de1 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1756,7 +1756,23 @@ class TestUnwrap: assert_array_equal(unwrap([1, 1 + 2 * np.pi]), [1, 1]) # check that unwrap maintains continuity assert_(np.all(diff(unwrap(rand(10) * 100)) < np.pi)) - + + def test_minmax(self): + # check that unwrap removes jumps greater that 255 + assert_array_equal(unwrap([1, 1 + 256], interval_size=255), [1, 2]) + # check that unwrap maintains continuity + assert_(np.all(diff(unwrap(rand(10) * 1000, interval_size=255)) < 255)) + # check simple case + simple_seq = np.array([0, 75, 150, 225, 300]) + wrap_seq = np.mod(simple_seq, 255) + assert_array_equal(unwrap(wrap_seq, interval_size=255), simple_seq) + # check custom discont value + uneven_seq = np.array([0, 75, 150, 225, 300, 430]) + wrap_uneven = np.mod(uneven_seq, 250) + no_discont = unwrap(wrap_uneven, interval_size=250) + assert_array_equal(no_discont, [0, 75, 150, 225, 300, 180]) + sm_discont = unwrap(wrap_uneven, interval_size=250, discont=140) + assert_array_equal(sm_discont, [0, 75, 150, 225, 300, 430]) class TestFilterwindows: -- cgit v1.2.1 From 593ef5fc5a02fbcd6eeb70a59684b3b21c9cc643 Mon Sep 17 00:00:00 2001 From: Bas van Beek <43369155+BvB93@users.noreply.github.com> Date: Tue, 4 Aug 2020 06:00:37 +0200 Subject: ENH: Speed up trim_zeros (#16911) * Added a benchmark for `trim_zeros()` * Improve the performance of `np.trim_zeros()` * Increase the variety of the tests Fall back to the old `np.trim_zeros()` implementation if an exception is encountered. Emit a `DeprecationWarning` in such case. * DEP,REL: Added a deprecation release note --- numpy/lib/tests/test_function_base.py | 46 ++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 12 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index eb2fc3311..89c1a2d9b 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1166,25 +1166,47 @@ class TestAngle: class TestTrimZeros: - """ - Only testing for integer splits. + a = np.array([0, 0, 1, 0, 2, 3, 4, 0]) + b = a.astype(float) + c = a.astype(complex) + d = np.array([None, [], 1, False, 'b', 3.0, range(4), b''], dtype=object) - """ + def values(self): + attr_names = ('a', 'b', 'c', 'd') + return (getattr(self, name) for name in attr_names) def test_basic(self): - a = np.array([0, 0, 1, 2, 3, 4, 0]) - res = trim_zeros(a) - assert_array_equal(res, np.array([1, 2, 3, 4])) + slc = np.s_[2:-1] + for arr in self.values(): + res = trim_zeros(arr) + assert_array_equal(res, arr[slc]) def test_leading_skip(self): - a = np.array([0, 0, 1, 0, 2, 3, 4, 0]) - res = trim_zeros(a) - assert_array_equal(res, np.array([1, 0, 2, 3, 4])) + slc = np.s_[:-1] + for arr in self.values(): + res = trim_zeros(arr, trim='b') + assert_array_equal(res, arr[slc]) def test_trailing_skip(self): - a = np.array([0, 0, 1, 0, 2, 3, 0, 4, 0]) - res = trim_zeros(a) - assert_array_equal(res, np.array([1, 0, 2, 3, 0, 4])) + slc = np.s_[2:] + for arr in self.values(): + res = trim_zeros(arr, trim='F') + assert_array_equal(res, arr[slc]) + + def test_all_zero(self): + for _arr in self.values(): + arr = np.zeros_like(_arr, dtype=_arr.dtype) + + res1 = trim_zeros(arr, trim='B') + assert len(res1) == 0 + + res2 = trim_zeros(arr, trim='f') + assert len(res2) == 0 + + def test_size_zero(self): + arr = np.zeros(0) + res = trim_zeros(arr) + assert_array_equal(arr, res) class TestExtins: -- cgit v1.2.1 From 7127cdfb8553030ba317455c9f31fe4d7ed74e81 Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Tue, 11 Aug 2020 15:53:55 +0200 Subject: ENH: Use elementwise comparisons with 0 rather than boolean casting --- numpy/lib/tests/test_function_base.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 89c1a2d9b..744034e01 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1169,10 +1169,9 @@ class TestTrimZeros: a = np.array([0, 0, 1, 0, 2, 3, 4, 0]) b = a.astype(float) c = a.astype(complex) - d = np.array([None, [], 1, False, 'b', 3.0, range(4), b''], dtype=object) def values(self): - attr_names = ('a', 'b', 'c', 'd') + attr_names = ('a', 'b', 'c') return (getattr(self, name) for name in attr_names) def test_basic(self): -- cgit v1.2.1 From a2b9c2d5b6637b040917c0a2ef393dae83f09ee3 Mon Sep 17 00:00:00 2001 From: peterbell10 Date: Wed, 12 Aug 2020 07:36:07 +0100 Subject: API, BUG: Raise error on complex input to i0 (#17062) * BUG, API: Raise error on complex input to np.i0 --- numpy/lib/tests/test_function_base.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 89c1a2d9b..635fe1432 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -2111,8 +2111,9 @@ class Test_I0: i0(0.5), np.array(1.0634833707413234)) - A = np.array([0.49842636, 0.6969809, 0.22011976, 0.0155549]) - expected = np.array([1.06307822, 1.12518299, 1.01214991, 1.00006049]) + # need at least one test above 8, as the implementation is piecewise + A = np.array([0.49842636, 0.6969809, 0.22011976, 0.0155549, 10.0]) + expected = np.array([1.06307822, 1.12518299, 1.01214991, 1.00006049, 2815.71662847]) assert_almost_equal(i0(A), expected) assert_almost_equal(i0(-A), expected) @@ -2149,6 +2150,10 @@ class Test_I0: assert_array_equal(exp, res) + def test_complex(self): + a = np.array([0, 1 + 2j]) + with pytest.raises(TypeError, match="i0 not supported for complex values"): + res = i0(a) class TestKaiser: -- cgit v1.2.1 From 26734efdb1c8ee269bb97acc22b587027a5a3f88 Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Thu, 13 Aug 2020 17:06:27 +0200 Subject: TST: Added / updated object array-related tests --- numpy/lib/tests/test_function_base.py | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 744034e01..ce5c358e0 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1169,9 +1169,10 @@ class TestTrimZeros: a = np.array([0, 0, 1, 0, 2, 3, 4, 0]) b = a.astype(float) c = a.astype(complex) + d = a.astype(object) def values(self): - attr_names = ('a', 'b', 'c') + attr_names = ('a', 'b', 'c', 'd') return (getattr(self, name) for name in attr_names) def test_basic(self): @@ -1207,6 +1208,22 @@ class TestTrimZeros: res = trim_zeros(arr) assert_array_equal(arr, res) + @pytest.mark.parametrize( + 'arr', + [np.array([0, 2**62, 0]), + np.array([0, 2**63, 0]), + np.array([0, 2**64, 0])] + ) + def test_overflow(self, arr): + slc = np.s_[1:2] + res = trim_zeros(arr) + assert_array_equal(res, arr[slc]) + + def test_no_trim(self): + arr = np.array([None, 1, None]) + res = trim_zeros(arr) + assert_array_equal(arr, res) + class TestExtins: -- cgit v1.2.1 From 8cf0872290fa05b6adc18d53e45e121ef9f74bd3 Mon Sep 17 00:00:00 2001 From: scimax Date: Thu, 20 Aug 2020 12:01:53 +0200 Subject: Update numpy/lib/tests/test_function_base.py Co-authored-by: Eric Wieser --- numpy/lib/tests/test_function_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 878fb3de1..44ff7ea81 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1757,7 +1757,7 @@ class TestUnwrap: # check that unwrap maintains continuity assert_(np.all(diff(unwrap(rand(10) * 100)) < np.pi)) - def test_minmax(self): + def test_period(self): # check that unwrap removes jumps greater that 255 assert_array_equal(unwrap([1, 1 + 256], interval_size=255), [1, 2]) # check that unwrap maintains continuity -- cgit v1.2.1 From 00dcda244bc1eb58cb3b4f30c7b18a71a8569194 Mon Sep 17 00:00:00 2001 From: Max Kellermeier Date: Fri, 21 Aug 2020 22:55:29 +0200 Subject: Updated incorrect argument in tests. boundary correction for int and float. Co-authored-by: Eric Wieser --- numpy/lib/tests/test_function_base.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 44ff7ea81..2ebde9aec 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1759,20 +1759,21 @@ class TestUnwrap: def test_period(self): # check that unwrap removes jumps greater that 255 - assert_array_equal(unwrap([1, 1 + 256], interval_size=255), [1, 2]) + assert_array_equal(unwrap([1, 1 + 256], period=255), [1, 2]) # check that unwrap maintains continuity - assert_(np.all(diff(unwrap(rand(10) * 1000, interval_size=255)) < 255)) + assert_(np.all(diff(unwrap(rand(10) * 1000, period=255)) < 255)) # check simple case simple_seq = np.array([0, 75, 150, 225, 300]) wrap_seq = np.mod(simple_seq, 255) - assert_array_equal(unwrap(wrap_seq, interval_size=255), simple_seq) + assert_array_equal(unwrap(wrap_seq, period=255), simple_seq) # check custom discont value uneven_seq = np.array([0, 75, 150, 225, 300, 430]) wrap_uneven = np.mod(uneven_seq, 250) - no_discont = unwrap(wrap_uneven, interval_size=250) + no_discont = unwrap(wrap_uneven, period=250) assert_array_equal(no_discont, [0, 75, 150, 225, 300, 180]) - sm_discont = unwrap(wrap_uneven, interval_size=250, discont=140) + sm_discont = unwrap(wrap_uneven, period=250, discont=140) assert_array_equal(sm_discont, [0, 75, 150, 225, 300, 430]) + assert sm_discont.dtype == wrap_uneven.dtype class TestFilterwindows: -- cgit v1.2.1 From 051198414ba1e2c3e56919013d4d4372c34aa994 Mon Sep 17 00:00:00 2001 From: mattip Date: Thu, 27 Aug 2020 19:35:52 +0300 Subject: BUG: revert trim_zeros changes from gh-16911 --- numpy/lib/tests/test_function_base.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 34a395ee4..41afccacc 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1225,6 +1225,10 @@ class TestTrimZeros: assert_array_equal(arr, res) + def test_list_to_list(self): + res = trim_zeros(self.a.tolist()) + assert isinstance(res, list) + class TestExtins: def test_basic(self): -- cgit v1.2.1 From 36ad0e43127240377692b9ca669db06c7fb153f7 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Mon, 31 Aug 2020 11:14:40 +0100 Subject: ENH: Make the window functions exactly symmetric This relies on the fact that `cos` is exactly symmetric around zero, but not around the floating-point approximation of `pi`. Closes gh-17169. --- numpy/lib/tests/test_function_base.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 41afccacc..7bddb941c 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1805,28 +1805,28 @@ class TestFilterwindows: def test_hanning(self): # check symmetry w = hanning(10) - assert_array_almost_equal(w, flipud(w), 7) + assert_equal(w, flipud(w)) # check known value assert_almost_equal(np.sum(w, axis=0), 4.500, 4) def test_hamming(self): # check symmetry w = hamming(10) - assert_array_almost_equal(w, flipud(w), 7) + assert_equal(w, flipud(w)) # check known value assert_almost_equal(np.sum(w, axis=0), 4.9400, 4) def test_bartlett(self): # check symmetry w = bartlett(10) - assert_array_almost_equal(w, flipud(w), 7) + assert_equal(w, flipud(w)) # check known value assert_almost_equal(np.sum(w, axis=0), 4.4444, 4) def test_blackman(self): # check symmetry w = blackman(10) - assert_array_almost_equal(w, flipud(w), 7) + assert_equal(w, flipud(w)) # check known value assert_almost_equal(np.sum(w, axis=0), 3.7800, 4) -- cgit v1.2.1 From e54a06ca81dd93cfda4570ae03740711092e08d3 Mon Sep 17 00:00:00 2001 From: Eric Wieser Date: Mon, 14 Sep 2020 10:18:55 +0100 Subject: Add missing whitespace --- numpy/lib/tests/test_function_base.py | 1 + 1 file changed, 1 insertion(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 2ebde9aec..f881ddf00 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1775,6 +1775,7 @@ class TestUnwrap: assert_array_equal(sm_discont, [0, 75, 150, 225, 300, 430]) assert sm_discont.dtype == wrap_uneven.dtype + class TestFilterwindows: def test_hanning(self): -- cgit v1.2.1 From 156cd054e007b05d4ac4829e10a369d19dd2b0b1 Mon Sep 17 00:00:00 2001 From: Lisa Schwetlick Date: Fri, 9 Oct 2020 21:35:47 +0200 Subject: ENH: add dtype option to cov and corrcoef (#17456) Adds a keyword-only dtype parameter to correlate and coerrcoef to allow user to specify the dtype of the output. Co-authored-by: Eric Wieser Co-authored-by: Ross Barnowski --- numpy/lib/tests/test_function_base.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 7bddb941c..4c7c0480c 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -2023,6 +2023,12 @@ class TestCorrCoef: assert_array_almost_equal(c, np.array([[1., -1.], [-1., 1.]])) assert_(np.all(np.abs(c) <= 1.0)) + @pytest.mark.parametrize("test_type", [np.half, np.single, np.double, np.longdouble]) + def test_corrcoef_dtype(self, test_type): + cast_A = self.A.astype(test_type) + res = corrcoef(cast_A, dtype=test_type) + assert test_type == res.dtype + class TestCov: x1 = np.array([[0, 2], [1, 1], [2, 0]]).T @@ -2123,6 +2129,12 @@ class TestCov: aweights=self.unit_weights), self.res1) + @pytest.mark.parametrize("test_type", [np.half, np.single, np.double, np.longdouble]) + def test_cov_dtype(self, test_type): + cast_x1 = self.x1.astype(test_type) + res = cov(cast_x1, dtype=test_type) + assert test_type == res.dtype + class Test_I0: -- cgit v1.2.1 From aeae93b6c0042f6ed8f45205545985cc194f84f3 Mon Sep 17 00:00:00 2001 From: Marten van Kerkwijk Date: Sun, 3 Jan 2021 11:11:15 -0500 Subject: API: make piecewise subclass safe using use zeros_like. Subclass input of piecewise was already respected, so it seems more logical to ensure the output is the same subclass (possibly just an oversight that it was not done before). --- numpy/lib/tests/test_function_base.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 4c7c0480c..afcb81eff 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -2399,6 +2399,14 @@ class TestPiecewise: assert_array_equal(y, np.array([[-1., -1., -1.], [3., 3., 1.]])) + def test_subclasses(self): + class subclass(np.ndarray): + pass + x = np.arange(5.).view(subclass) + r = piecewise(x, [x<2., x>=4], [-1., 1., 0.]) + assert_equal(type(r), subclass) + assert_equal(r, [-1., -1., 0., 0., 1.]) + class TestBincount: -- cgit v1.2.1 From 3cdb33f02298c3544f7a3bc312c42422a2a7b971 Mon Sep 17 00:00:00 2001 From: DCtheTall Date: Wed, 31 Mar 2021 17:11:41 -0400 Subject: Add tests np.meshgrid for higher dimensional grids. --- numpy/lib/tests/test_function_base.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index afcb81eff..4201afac3 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -2219,6 +2219,7 @@ class TestMsort: [0.64864341, 0.79115165, 0.96098397]])) +# Run test using: python3 runtests.py -t numpy.lib.tests.test_function_base class TestMeshgrid: def test_simple(self): @@ -2307,6 +2308,20 @@ class TestMeshgrid: assert_equal(x[0, :], 0) assert_equal(x[1, :], X) + def test_higher_dimensions(self): + a, b, c = np.meshgrid([0], [1, 1], [2, 2]) + assert_equal(a, [[[0, 0]], [[0, 0]]]) + assert_equal(b, [[[1, 1]], [[1, 1]]]) + assert_equal(c, [[[2, 2]], [[2, 2]]]) + + a, b, c, d, e = np.meshgrid(*([0] * i for i in range(1, 6))) + expected_shape = (2, 1, 3, 4, 5) + assert_equal(a.shape, expected_shape) + assert_equal(b.shape, expected_shape) + assert_equal(c.shape, expected_shape) + assert_equal(d.shape, expected_shape) + assert_equal(e.shape, expected_shape) + class TestPiecewise: -- cgit v1.2.1 From 2a880214c0ffb9c21b12ab51fbb364d71aa17cd1 Mon Sep 17 00:00:00 2001 From: DCtheTall Date: Wed, 31 Mar 2021 17:12:37 -0400 Subject: rm comment --- numpy/lib/tests/test_function_base.py | 1 - 1 file changed, 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 4201afac3..8dcbaa034 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -2219,7 +2219,6 @@ class TestMsort: [0.64864341, 0.79115165, 0.96098397]])) -# Run test using: python3 runtests.py -t numpy.lib.tests.test_function_base class TestMeshgrid: def test_simple(self): -- cgit v1.2.1 From 9f339758e3faeb447a629d600f7640c8735a6c4a Mon Sep 17 00:00:00 2001 From: DCtheTall Date: Mon, 5 Apr 2021 15:50:16 -0400 Subject: review comments --- numpy/lib/tests/test_function_base.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 8dcbaa034..761ea83a3 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -2307,12 +2307,7 @@ class TestMeshgrid: assert_equal(x[0, :], 0) assert_equal(x[1, :], X) - def test_higher_dimensions(self): - a, b, c = np.meshgrid([0], [1, 1], [2, 2]) - assert_equal(a, [[[0, 0]], [[0, 0]]]) - assert_equal(b, [[[1, 1]], [[1, 1]]]) - assert_equal(c, [[[2, 2]], [[2, 2]]]) - + def test_nd_shape(self): a, b, c, d, e = np.meshgrid(*([0] * i for i in range(1, 6))) expected_shape = (2, 1, 3, 4, 5) assert_equal(a.shape, expected_shape) @@ -2321,6 +2316,18 @@ class TestMeshgrid: assert_equal(d.shape, expected_shape) assert_equal(e.shape, expected_shape) + def test_nd_values(self): + a, b, c = np.meshgrid([0], [1, 2], [3, 4, 5]) + assert_equal(a, [[[0, 0, 0]], [[0, 0, 0]]]) + assert_equal(b, [[[1, 1, 1]], [[2, 2, 2]]]) + assert_equal(c, [[[3, 4, 5]], [[3, 4, 5]]]) + + def test_nd_indexing(self): + a, b, c = np.meshgrid([0], [1, 2], [3, 4, 5], indexing='ij') + assert_equal(a, [[[0, 0, 0], [0, 0, 0]]]) + assert_equal(b, [[[1, 1, 1], [2, 2, 2]]]) + assert_equal(c, [[[3, 4, 5], [3, 4, 5]]]) + class TestPiecewise: -- cgit v1.2.1 From 341316d5158477b06f877db60049b0995ab78128 Mon Sep 17 00:00:00 2001 From: Kevin Sheppard Date: Thu, 22 Apr 2021 14:35:43 +0100 Subject: BUG: Prevent nan being used in percentile (gh-18831) Reject NaN as a percentile/quantile value. Previously NaNs could pass the range check `0 <= q <= 1`. closes #18830 --- numpy/lib/tests/test_function_base.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 761ea83a3..0b66ccf8c 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -2750,6 +2750,10 @@ class TestPercentile: assert_equal(p, Fraction(7, 4)) assert_equal(type(p), Fraction) + p = np.percentile(x, [Fraction(50)]) + assert_equal(p, np.array([Fraction(7, 4)])) + assert_equal(type(p), np.ndarray) + def test_api(self): d = np.ones(5) np.percentile(d, 5, None, None, False) @@ -3144,6 +3148,16 @@ class TestPercentile: assert_equal(np.percentile( a, [0.3, 0.6], (0, 2), interpolation='nearest'), b) + def test_nan_q(self): + # GH18830 + with pytest.raises(ValueError, match="Percentiles must be in"): + np.percentile([1, 2, 3, 4.0], np.nan) + with pytest.raises(ValueError, match="Percentiles must be in"): + np.percentile([1, 2, 3, 4.0], [np.nan]) + q = np.linspace(1.0, 99.0, 16) + q[0] = np.nan + 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 @@ -3180,6 +3194,14 @@ class TestQuantile: assert_equal(q, Fraction(7, 4)) assert_equal(type(q), Fraction) + q = np.quantile(x, [Fraction(1, 2)]) + assert_equal(q, np.array([Fraction(7, 4)])) + assert_equal(type(q), np.ndarray) + + q = np.quantile(x, [[Fraction(1, 2)]]) + assert_equal(q, np.array([[Fraction(7, 4)]])) + assert_equal(type(q), np.ndarray) + # repeat with integral input but fractional quantile x = np.arange(8) assert_equal(np.quantile(x, Fraction(1, 2)), Fraction(7, 2)) -- cgit v1.2.1 From 3c892cd4f0809f5a6e736ab234a6a44fc326e29a Mon Sep 17 00:00:00 2001 From: Marten van Kerkwijk Date: Sat, 26 Jun 2021 18:01:48 -0400 Subject: API: Ensure np.vectorize outputs can be subclasses. As is, this is true for the ufunc case, but not for the gufunc case, even if the underlying function does produce a subclass. Given the care taken to ensure inputs are kept as subclasses, this is almost certainly an oversight, which is here corrected. --- numpy/lib/tests/test_function_base.py | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index a4f49a78b..e1b615223 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1665,6 +1665,26 @@ class TestVectorize: with assert_raises_regex(ValueError, 'new output dimensions'): f(x) + def test_subclasses(self): + class subclass(np.ndarray): + pass + + m = np.array([[1., 0., 0.], + [0., 0., 1.], + [0., 1., 0.]]).view(subclass) + v = np.array([[1., 2., 3.], [4., 5., 6.], [7., 8., 9.]]).view(subclass) + # generalized (gufunc) + matvec = np.vectorize(np.matmul, signature='(m,m),(m)->(m)') + r = matvec(m, v) + assert_equal(type(r), subclass) + assert_equal(r, [[1., 3., 2.], [4., 6., 5.], [7., 9., 8.]]) + + # element-wise (ufunc) + mult = np.vectorize(lambda x, y: x*y) + r = mult(m, v) + assert_equal(type(r), subclass) + assert_equal(r, m * v) + class TestLeaks: class A: @@ -1798,7 +1818,7 @@ class TestUnwrap: assert_array_equal(unwrap([1, 1 + 2 * np.pi]), [1, 1]) # check that unwrap maintains continuity assert_(np.all(diff(unwrap(rand(10) * 100)) < np.pi)) - + def test_period(self): # check that unwrap removes jumps greater that 255 assert_array_equal(unwrap([1, 1 + 256], period=255), [1, 2]) -- cgit v1.2.1 From 82ce76c0e7011f4cd88fb4cc5be7b83f8a07f3c9 Mon Sep 17 00:00:00 2001 From: Ankit Dwivedi Date: Sat, 7 Aug 2021 05:34:06 +0000 Subject: add tests to check if whitespaces are ignored in gufunc signatures --- numpy/lib/tests/test_function_base.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index e1b615223..dcfef94cf 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1528,6 +1528,20 @@ class TestVectorize: ([('x',)], [('y',), ()])) assert_equal(nfb._parse_gufunc_signature('(),(a,b,c),(d)->(d,e)'), ([(), ('a', 'b', 'c'), ('d',)], [('d', 'e')])) + + # Test if whitespaces are ignored + assert_equal(nfb._parse_gufunc_signature('(x )->()'), ([('x',)], [()])) + assert_equal(nfb._parse_gufunc_signature('( x , y )->( )'), + ([('x', 'y')], [()])) + assert_equal(nfb._parse_gufunc_signature('(x),( y) ->()'), + ([('x',), ('y',)], [()])) + assert_equal(nfb._parse_gufunc_signature('( x)-> (y ) '), + ([('x',)], [('y',)])) + assert_equal(nfb._parse_gufunc_signature(' (x)->( y),( )'), + ([('x',)], [('y',), ()])) + assert_equal(nfb._parse_gufunc_signature('( ), ( a, b,c ) ,( d) -> (d , e)'), + ([(), ('a', 'b', 'c'), ('d',)], [('d', 'e')])) + with assert_raises(ValueError): nfb._parse_gufunc_signature('(x)(y)->()') with assert_raises(ValueError): -- cgit v1.2.1 From 9d9cb200cb2d8c24d648f342ecc67b90efcf1f48 Mon Sep 17 00:00:00 2001 From: Ankit Dwivedi Date: Sat, 7 Aug 2021 16:05:07 +0000 Subject: fix lint errors --- numpy/lib/tests/test_function_base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index dcfef94cf..6e36e0969 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1539,7 +1539,8 @@ class TestVectorize: ([('x',)], [('y',)])) assert_equal(nfb._parse_gufunc_signature(' (x)->( y),( )'), ([('x',)], [('y',), ()])) - assert_equal(nfb._parse_gufunc_signature('( ), ( a, b,c ) ,( d) -> (d , e)'), + assert_equal(nfb._parse_gufunc_signature( + '( ), ( a, b,c ) ,( d) -> (d , e)'), ([(), ('a', 'b', 'c'), ('d',)], [('d', 'e')])) with assert_raises(ValueError): -- cgit v1.2.1 From 2e96755a08cee5651baa5e5da4ce054f4621b237 Mon Sep 17 00:00:00 2001 From: Ankit Dwivedi Date: Sun, 8 Aug 2021 05:06:00 +0000 Subject: dummy change to kick off another build --- numpy/lib/tests/test_function_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 6e36e0969..1d694e92f 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1529,7 +1529,7 @@ class TestVectorize: assert_equal(nfb._parse_gufunc_signature('(),(a,b,c),(d)->(d,e)'), ([(), ('a', 'b', 'c'), ('d',)], [('d', 'e')])) - # Test if whitespaces are ignored + # Tests to check if whitespaces are ignored assert_equal(nfb._parse_gufunc_signature('(x )->()'), ([('x',)], [()])) assert_equal(nfb._parse_gufunc_signature('( x , y )->( )'), ([('x', 'y')], [()])) -- cgit v1.2.1 From 64f15a94708095bf9d29af5dbfcc4b654a57248a Mon Sep 17 00:00:00 2001 From: Mike Taves Date: Mon, 30 Aug 2021 11:01:34 +1200 Subject: MAINT: refactor "for ... in range(len(" statements --- numpy/lib/tests/test_function_base.py | 5 ----- 1 file changed, 5 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 1d694e92f..829691b1c 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -2772,11 +2772,6 @@ class TestInterp: assert_almost_equal(np.interp(x, xp, fp, period=360), y) -def compare_results(res, desired): - for i in range(len(desired)): - assert_array_equal(res[i], desired[i]) - - class TestPercentile: def test_basic(self): -- cgit v1.2.1 From 6ba48721e22622403a60b7f9d3ec5cae308ba3a9 Mon Sep 17 00:00:00 2001 From: Marten van Kerkwijk Date: Mon, 13 Sep 2021 15:50:54 -0400 Subject: BUG: ensure np.median does not drop subclass for NaN result. Currently, np.median is almost completely safe for subclasses, except if the result is NaN. In that case, it assumes the result is a scalar and substitutes a NaN with the right dtype. This PR fixes that, since subclasses like astropy's Quantity generally use array scalars to preserve subclass information such as the unit. --- numpy/lib/tests/test_function_base.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 829691b1c..5f27ea655 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -3432,6 +3432,16 @@ class TestMedian: a = MySubClass([1, 2, 3]) assert_equal(np.median(a), -7) + @pytest.mark.parametrize('arr', + ([1., 2., 3.], [1., np.nan, 3.], np.nan, 0.)) + def test_subclass2(self, arr): + """Check that we return subclasses, even if a NaN scalar.""" + class MySubclass(np.ndarray): + pass + + m = np.median(np.array(arr).view(MySubclass)) + assert isinstance(m, MySubclass) + def test_out(self): o = np.zeros((4,)) d = np.ones((3, 4)) -- cgit v1.2.1 From 1a0d8b3d877bbfb6c567d675574716e496019014 Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Thu, 30 Sep 2021 16:58:30 +0200 Subject: BUG: Fix the `lib.function_base` window functions ignoring extended precision float dtypes --- numpy/lib/tests/test_function_base.py | 86 +++++++++++++++++++++++++++++------ 1 file changed, 73 insertions(+), 13 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 5f27ea655..f4f0e5542 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1528,7 +1528,7 @@ class TestVectorize: ([('x',)], [('y',), ()])) assert_equal(nfb._parse_gufunc_signature('(),(a,b,c),(d)->(d,e)'), ([(), ('a', 'b', 'c'), ('d',)], [('d', 'e')])) - + # Tests to check if whitespaces are ignored assert_equal(nfb._parse_gufunc_signature('(x )->()'), ([('x',)], [()])) assert_equal(nfb._parse_gufunc_signature('( x , y )->( )'), @@ -1853,35 +1853,95 @@ class TestUnwrap: assert sm_discont.dtype == wrap_uneven.dtype +@pytest.mark.parametrize( + "dtype", "O" + np.typecodes["AllInteger"] + np.typecodes["Float"] +) +@pytest.mark.parametrize("M", [0, 1, 10]) class TestFilterwindows: - def test_hanning(self): + def test_hanning(self, dtype: str, M: int) -> None: + scalar = np.array(M, dtype=dtype)[()] + + w = hanning(scalar) + if dtype == "O": + ref_dtype = np.float64 + else: + ref_dtype = np.result_type(scalar.dtype, np.float64) + assert w.dtype == ref_dtype + # check symmetry - w = hanning(10) assert_equal(w, flipud(w)) + # check known value - assert_almost_equal(np.sum(w, axis=0), 4.500, 4) + if scalar < 1: + assert_array_equal(w, np.array([])) + elif scalar == 1: + assert_array_equal(w, np.ones(1)) + else: + assert_almost_equal(np.sum(w, axis=0), 4.500, 4) + + def test_hamming(self, dtype: str, M: int) -> None: + scalar = np.array(M, dtype=dtype)[()] + + w = hamming(scalar) + if dtype == "O": + ref_dtype = np.float64 + else: + ref_dtype = np.result_type(scalar.dtype, np.float64) + assert w.dtype == ref_dtype - def test_hamming(self): # check symmetry - w = hamming(10) assert_equal(w, flipud(w)) + # check known value - assert_almost_equal(np.sum(w, axis=0), 4.9400, 4) + if scalar < 1: + assert_array_equal(w, np.array([])) + elif scalar == 1: + assert_array_equal(w, np.ones(1)) + else: + assert_almost_equal(np.sum(w, axis=0), 4.9400, 4) + + def test_bartlett(self, dtype: str, M: int) -> None: + scalar = np.array(M, dtype=dtype)[()] + + w = bartlett(scalar) + if dtype == "O": + ref_dtype = np.float64 + else: + ref_dtype = np.result_type(scalar.dtype, np.float64) + assert w.dtype == ref_dtype - def test_bartlett(self): # check symmetry - w = bartlett(10) assert_equal(w, flipud(w)) + # check known value - assert_almost_equal(np.sum(w, axis=0), 4.4444, 4) + if scalar < 1: + assert_array_equal(w, np.array([])) + elif scalar == 1: + assert_array_equal(w, np.ones(1)) + else: + assert_almost_equal(np.sum(w, axis=0), 4.4444, 4) + + def test_blackman(self, dtype: str, M: int) -> None: + scalar = np.array(M, dtype=dtype)[()] + + w = blackman(scalar) + if dtype == "O": + ref_dtype = np.float64 + else: + ref_dtype = np.result_type(scalar.dtype, np.float64) + assert w.dtype == ref_dtype - def test_blackman(self): # check symmetry - w = blackman(10) assert_equal(w, flipud(w)) + # check known value - assert_almost_equal(np.sum(w, axis=0), 3.7800, 4) + if scalar < 1: + assert_array_equal(w, np.array([])) + elif scalar == 1: + assert_array_equal(w, np.ones(1)) + else: + assert_almost_equal(np.sum(w, axis=0), 3.7800, 4) class TestTrapz: -- cgit v1.2.1 From e214496119f6b35819cebaa1562818d27b6c34fb Mon Sep 17 00:00:00 2001 From: Bas van Beek Date: Thu, 30 Sep 2021 17:13:32 +0200 Subject: TST: Add more tests for `np.kaiser` --- numpy/lib/tests/test_function_base.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index f4f0e5542..66110b479 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1943,6 +1943,27 @@ class TestFilterwindows: else: assert_almost_equal(np.sum(w, axis=0), 3.7800, 4) + def test_kaiser(self, dtype: str, M: int) -> None: + scalar = np.array(M, dtype=dtype)[()] + + w = kaiser(scalar, 0) + if dtype == "O": + ref_dtype = np.float64 + else: + ref_dtype = np.result_type(scalar.dtype, np.float64) + assert w.dtype == ref_dtype + + # check symmetry + assert_equal(w, flipud(w)) + + # check known value + if scalar < 1: + assert_array_equal(w, np.array([])) + elif scalar == 1: + assert_array_equal(w, np.ones(1)) + else: + assert_almost_equal(np.sum(w, axis=0), 10, 15) + class TestTrapz: -- cgit v1.2.1 From be11c06de7cf128c364c33dafbdecd2372f322e6 Mon Sep 17 00:00:00 2001 From: warren Date: Wed, 20 Oct 2021 18:00:38 -0400 Subject: BUG: lib: Fix error raised by insert. When `insert` is given a single out-of-bounds index in a list, e.g. np.insert([0, 1, 2], [99], [3, 4]) # 99 is out of bounds a TypeError was being raised because of a bug in the formatting of the message. Before this change, the error is TypeError: %i format: a number is required, not list After, we get the expected IndexError: index [99] is out of bounds for axis 0 with size 3 --- numpy/lib/tests/test_function_base.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 66110b479..c7dfe5673 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: -- cgit v1.2.1 From cd7a02a4db7e760b881f3feeb832ffd84fa8645a Mon Sep 17 00:00:00 2001 From: abel Date: Thu, 2 Sep 2021 16:34:42 +0200 Subject: MAINT, ENH [#10736] Add interpolation methods to quantile - Added the missing linear interpolation methods. - Updated the existing unit tests. - Added pytest.mark.xfail for boolean arrays See - https://github.com/numpy/numpy/pull/19857#issuecomment-919258693 - https://github.com/numpy/numpy/issues/19154 --- numpy/lib/tests/test_function_base.py | 177 +++++++++++++++++++++++++++------- 1 file changed, 141 insertions(+), 36 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index c7dfe5673..4f0db7bdb 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -2903,36 +2903,134 @@ class TestPercentile: [1, 1, 1]]) assert_array_equal(np.percentile(x, 50, axis=0), [1, 1, 1]) - def test_linear(self): - + @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, + interpolation="linear") + np.testing.assert_equal(res, np.NAN) + np.testing.assert_equal(res.dtype, arr.dtype) + + TYPE_CODES = np.typecodes["AllInteger"] + np.typecodes["AllFloat"] + "O" + + @pytest.mark.parametrize("dtype", TYPE_CODES) + def test_linear_inverted_cdf(self, dtype): + # METHOD 1 of H&F + arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=dtype) + res = np.percentile( + arr, + 40.0, + interpolation="inverted_cdf") + np.testing.assert_almost_equal(res, 20, 15) + + @pytest.mark.parametrize("dtype", TYPE_CODES) + def test_linear_averaged_inverted_cdf(self, dtype): + # METHOD 2 of H&F + arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=dtype) + res = np.percentile( + arr, + 40.0, + interpolation="averaged_inverted_cdf") + np.testing.assert_almost_equal(res, 27.5, 15) + + @pytest.mark.parametrize("dtype", TYPE_CODES) + def test_linear_closest_observation(self, dtype): + # METHOD 3 of H&F + arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=dtype) + res = np.percentile( + arr, + 40.0, + interpolation="closest_observation") + np.testing.assert_almost_equal(res, 20, 15) + + @pytest.mark.parametrize("dtype", TYPE_CODES) + def test_linear_interpolated_inverted_cdf(self, dtype): + # METHOD 4 of H&F + arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=dtype) + res = np.percentile( + arr, + 40.0, + interpolation="interpolated_inverted_cdf") + np.testing.assert_almost_equal(res, 20, 15) + + @pytest.mark.parametrize("dtype", TYPE_CODES) + def test_linear_hazen(self, dtype): + # METHOD 5 of H&F + arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=dtype) + res = np.percentile( + arr, + 40.0, + interpolation="hazen") + np.testing.assert_almost_equal(res, 27.5, 15) + + @pytest.mark.parametrize("dtype", TYPE_CODES) + def test_linear_weibull(self, dtype): + # METHOD 6 of H&F + arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=dtype) + res = np.percentile( + arr, + 40.0, + interpolation="weibull") + np.testing.assert_almost_equal(res, 26, 15) + + @pytest.mark.parametrize("dtype", TYPE_CODES) + def test_linear_linear(self, dtype): + # METHOD 7 of H&F # 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, + # explicit interpolation_method (the default) + res = np.percentile([15.0, 20.0, 35.0, 40.0, 50.0], + 40, + interpolation="linear") + np.testing.assert_almost_equal(res, 29, 15) + + @pytest.mark.parametrize("dtype", TYPE_CODES) + def test_linear_median_unbiased(self, dtype): + # METHOD 8 of H&F + arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=dtype) + res = np.percentile( + arr, + 40.0, + interpolation="median_unbiased") + np.testing.assert_almost_equal(res, 27, 14) + + @pytest.mark.parametrize("dtype", TYPE_CODES) + def test_linear_normal_unbiased(self, dtype): + # METHOD 9 of H&F + arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=dtype) + res = np.percentile( + arr, + 40.0, + interpolation="normal_unbiased") + np.testing.assert_almost_equal(res, 27.125, 15) + + @pytest.mark.parametrize("dtype", TYPE_CODES) + def test_lower_higher(self, dtype): + assert_equal(np.percentile(np.arange(10, dtype=dtype), 50, interpolation='lower'), 4) - assert_equal(np.percentile(range(10), 50, + assert_equal(np.percentile(np.arange(10, dtype=dtype), 50, interpolation='higher'), 5) - def test_midpoint(self): - assert_equal(np.percentile(range(10), 51, + @pytest.mark.parametrize("dtype", TYPE_CODES) + def test_midpoint(self, dtype): + assert_equal(np.percentile(np.arange(10, dtype=dtype), 51, interpolation='midpoint'), 4.5) - assert_equal(np.percentile(range(11), 51, + assert_equal(np.percentile(np.arange(9, dtype=dtype) + 1, 50, + interpolation='midpoint'), 5) + assert_equal(np.percentile(np.arange(11, dtype=dtype), 51, interpolation='midpoint'), 5.5) - assert_equal(np.percentile(range(11), 50, + assert_equal(np.percentile(np.arange(11, dtype=dtype), 50, interpolation='midpoint'), 5) - def test_nearest(self): - assert_equal(np.percentile(range(10), 51, + @pytest.mark.parametrize("dtype", TYPE_CODES) + def test_nearest(self, dtype): + assert_equal(np.percentile(np.arange(10, dtype=dtype), 51, interpolation='nearest'), 5) - assert_equal(np.percentile(range(10), 49, - interpolation='nearest'), 4) + assert_equal(np.percentile(np.arange(10, dtype=dtype), 49, + interpolation='nearest'), 4) def test_sequence(self): x = np.arange(8) * 0.5 @@ -3038,18 +3136,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 @@ -3293,6 +3391,7 @@ 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 @@ -3302,6 +3401,7 @@ class TestQuantile: 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) @@ -3310,12 +3410,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) @@ -3352,6 +3451,12 @@ class TestQuantile: np.quantile(np.arange(100.), p, interpolation="midpoint") assert_array_equal(p, p0) + @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], + interpolation="nearest") + assert res.dtype == dtype + def test_quantile_monotonic(self): # GH 14685 # test that the return value of quantile is monotonic if p0 is ordered @@ -3380,9 +3485,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._linear_interpolation_formula(a, b, t0) + l1 = nfb._linear_interpolation_formula(a, b, t1) if t0 == t1 or a == b: assert l0 == l1 # uninteresting elif (t0 < t1) == (a < b): @@ -3396,11 +3501,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._linear_interpolation_formula(a, b, t) <= b else: - assert b <= np.lib.function_base._lerp(a, b, t) <= a + assert b <= nfb._linear_interpolation_formula(a, b, t) <= a @hypothesis.given(t=st.floats(allow_nan=False, allow_infinity=False, min_value=0, max_value=1), @@ -3408,17 +3513,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._linear_interpolation_formula(a, b, 1 - (1 - t)) + right = nfb._linear_interpolation_formula(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._linear_interpolation_formula(a, b, t) == 2.6 class TestMedian: -- cgit v1.2.1 From ab19ed256bf9b20340c92cebcfd6158241122c88 Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 19 Oct 2021 12:10:16 +0200 Subject: Fix _lerp - some changes were unrelated to the PR and have been reverted, including, renaming and moving the logic around. - Also renamed _quantile_ureduce_func to its original name --- numpy/lib/tests/test_function_base.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 4f0db7bdb..d59f3a85d 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -3486,8 +3486,8 @@ class TestLerp: b = st.floats(allow_nan=False, allow_infinity=False, min_value=-1e300, max_value=1e300)) def test_linear_interpolation_formula_monotonic(self, t0, t1, a, b): - l0 = nfb._linear_interpolation_formula(a, b, t0) - l1 = nfb._linear_interpolation_formula(a, b, t1) + 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): @@ -3503,9 +3503,9 @@ class TestLerp: min_value=-1e300, max_value=1e300)) def test_linear_interpolation_formula_bounded(self, t, a, b): if a <= b: - assert a <= nfb._linear_interpolation_formula(a, b, t) <= b + assert a <= nfb._lerp(a, b, t) <= b else: - assert b <= nfb._linear_interpolation_formula(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), @@ -3515,15 +3515,15 @@ class TestLerp: min_value=-1e300, max_value=1e300)) def test_linear_interpolation_formula_symmetric(self, t, a, b): # double subtraction is needed to remove the extra precision of t < 0.5 - left = nfb._linear_interpolation_formula(a, b, 1 - (1 - t)) - right = nfb._linear_interpolation_formula(b, a, 1 - t) + left = nfb._lerp(a, b, 1 - (1 - t)) + right = nfb._lerp(b, a, 1 - t) assert left == right def test_linear_interpolation_formula_0d_inputs(self): a = np.array(2) b = np.array(5) t = np.array(0.2) - assert nfb._linear_interpolation_formula(a, b, t) == 2.6 + assert nfb._lerp(a, b, t) == 2.6 class TestMedian: -- cgit v1.2.1 From 2a5422da7cb6759d75477738cc192fee3ca2a19c Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 19 Oct 2021 17:55:06 +0200 Subject: Fix issue with nan scalar Also added unit test for it. --- numpy/lib/tests/test_function_base.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index d59f3a85d..f9854c568 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -3475,6 +3475,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, -- cgit v1.2.1 From 98cf811e27138c41e365222cb70f06d70c0db4ee Mon Sep 17 00:00:00 2001 From: abel Date: Thu, 21 Oct 2021 12:31:06 +0200 Subject: TST: Add extrapolation tests --- numpy/lib/tests/test_function_base.py | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index f9854c568..53254c3e5 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -3032,6 +3032,15 @@ class TestPercentile: assert_equal(np.percentile(np.arange(10, dtype=dtype), 49, interpolation='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 assert_equal(np.percentile(x, [0, 100, 50]), [0, 3.5, 1.75]) -- cgit v1.2.1 From 2faf8edd635c8c700a3f5215cc747e268541b6bc Mon Sep 17 00:00:00 2001 From: abel Date: Thu, 21 Oct 2021 16:13:29 +0200 Subject: TST: Add parametrize for interpolation methods --- numpy/lib/tests/test_function_base.py | 134 +++++++++++----------------------- 1 file changed, 43 insertions(+), 91 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 53254c3e5..22228405a 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -2914,98 +2914,50 @@ class TestPercentile: np.testing.assert_equal(res, np.NAN) np.testing.assert_equal(res.dtype, arr.dtype) - TYPE_CODES = np.typecodes["AllInteger"] + np.typecodes["AllFloat"] + "O" - - @pytest.mark.parametrize("dtype", TYPE_CODES) - def test_linear_inverted_cdf(self, dtype): - # METHOD 1 of H&F - arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=dtype) - res = np.percentile( - arr, - 40.0, - interpolation="inverted_cdf") - np.testing.assert_almost_equal(res, 20, 15) - - @pytest.mark.parametrize("dtype", TYPE_CODES) - def test_linear_averaged_inverted_cdf(self, dtype): - # METHOD 2 of H&F - arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=dtype) - res = np.percentile( - arr, - 40.0, - interpolation="averaged_inverted_cdf") - np.testing.assert_almost_equal(res, 27.5, 15) - - @pytest.mark.parametrize("dtype", TYPE_CODES) - def test_linear_closest_observation(self, dtype): - # METHOD 3 of H&F - arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=dtype) - res = np.percentile( - arr, - 40.0, - interpolation="closest_observation") - np.testing.assert_almost_equal(res, 20, 15) - - @pytest.mark.parametrize("dtype", TYPE_CODES) - def test_linear_interpolated_inverted_cdf(self, dtype): - # METHOD 4 of H&F - arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=dtype) - res = np.percentile( - arr, - 40.0, - interpolation="interpolated_inverted_cdf") - np.testing.assert_almost_equal(res, 20, 15) - - @pytest.mark.parametrize("dtype", TYPE_CODES) - def test_linear_hazen(self, dtype): - # METHOD 5 of H&F - arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=dtype) - res = np.percentile( - arr, - 40.0, - interpolation="hazen") - np.testing.assert_almost_equal(res, 27.5, 15) - - @pytest.mark.parametrize("dtype", TYPE_CODES) - def test_linear_weibull(self, dtype): - # METHOD 6 of H&F - arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=dtype) - res = np.percentile( - arr, - 40.0, - interpolation="weibull") - np.testing.assert_almost_equal(res, 26, 15) - - @pytest.mark.parametrize("dtype", TYPE_CODES) - def test_linear_linear(self, dtype): - # METHOD 7 of H&F - # Test defaults - assert_equal(np.percentile(range(10), 50), 4.5) - # explicit interpolation_method (the default) - res = np.percentile([15.0, 20.0, 35.0, 40.0, 50.0], - 40, - interpolation="linear") - np.testing.assert_almost_equal(res, 29, 15) - - @pytest.mark.parametrize("dtype", TYPE_CODES) - def test_linear_median_unbiased(self, dtype): - # METHOD 8 of H&F - arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=dtype) - res = np.percentile( - arr, - 40.0, - interpolation="median_unbiased") - np.testing.assert_almost_equal(res, 27, 14) + 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.float128, np.float128), + (np.complex64, np.complex128), + (np.complex128, np.complex128), + (np.complex256, np.complex256), + (np.dtype("O"), np.float64)] + + @pytest.mark.parametrize(["input_dtype", "expected_dtype"], H_F_TYPE_CODES) + @pytest.mark.parametrize(["interpolation", "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, + interpolation, + 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, interpolation=interpolation) + + np.testing.assert_almost_equal(actual, expected, 14) + + if interpolation 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)) - @pytest.mark.parametrize("dtype", TYPE_CODES) - def test_linear_normal_unbiased(self, dtype): - # METHOD 9 of H&F - arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=dtype) - res = np.percentile( - arr, - 40.0, - interpolation="normal_unbiased") - np.testing.assert_almost_equal(res, 27.125, 15) + TYPE_CODES = np.typecodes["AllInteger"] + np.typecodes["AllFloat"] + "O" @pytest.mark.parametrize("dtype", TYPE_CODES) def test_lower_higher(self, dtype): -- cgit v1.2.1 From a8218af306e7639f2136c8e915a5b9ea1f34356a Mon Sep 17 00:00:00 2001 From: abel Date: Fri, 22 Oct 2021 13:35:40 +0200 Subject: TST: Make use of clongdouble and longdouble On some platforms float128 and complex256 do not exist. Using (c)longdouble aliases should work on all platforms. --- numpy/lib/tests/test_function_base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 22228405a..d5fa012f1 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -2919,10 +2919,10 @@ class TestPercentile: ] + [(np.float16, np.float64), (np.float32, np.float64), (np.float64, np.float64), - (np.float128, np.float128), + (np.longdouble, np.longdouble), (np.complex64, np.complex128), (np.complex128, np.complex128), - (np.complex256, np.complex256), + (np.clongdouble, np.clongdouble), (np.dtype("O"), np.float64)] @pytest.mark.parametrize(["input_dtype", "expected_dtype"], H_F_TYPE_CODES) -- cgit v1.2.1 From 53e3df3c99a26791cc07e2ea1570e87643fdf7e0 Mon Sep 17 00:00:00 2001 From: abel Date: Tue, 9 Nov 2021 17:35:03 +0100 Subject: TST: Add test for max ulp in default quantile calculation --- numpy/lib/tests/test_function_base.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index d5fa012f1..1c274afae 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -3356,6 +3356,14 @@ class TestPercentile: 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.) -- cgit v1.2.1 From 3993408877ab414cb5e3639ac0e20fdec972933f Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Mon, 8 Nov 2021 15:38:30 -0600 Subject: API,DEP: Rename percentile/quantile `interpolation=` to `method=` --- numpy/lib/tests/test_function_base.py | 92 +++++++++++++++++------------------ 1 file changed, 46 insertions(+), 46 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 1c274afae..0b94b9a85 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -2867,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)] @@ -2910,7 +2910,7 @@ class TestPercentile: res = np.percentile( arr, 40.0, - interpolation="linear") + method="linear") np.testing.assert_equal(res, np.NAN) np.testing.assert_equal(res.dtype, arr.dtype) @@ -2926,7 +2926,7 @@ class TestPercentile: (np.dtype("O"), np.float64)] @pytest.mark.parametrize(["input_dtype", "expected_dtype"], H_F_TYPE_CODES) - @pytest.mark.parametrize(["interpolation", "expected"], + @pytest.mark.parametrize(["method", "expected"], [("inverted_cdf", 20), ("averaged_inverted_cdf", 27.5), ("closest_observation", 20), @@ -2938,16 +2938,16 @@ class TestPercentile: ("normal_unbiased", 27.125), ]) def test_linear_interpolation(self, - interpolation, + 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, interpolation=interpolation) + actual = np.percentile(arr, 40.0, method=method) np.testing.assert_almost_equal(actual, expected, 14) - if interpolation in ["inverted_cdf", "closest_observation"]: + if method in ["inverted_cdf", "closest_observation"]: if input_dtype == "O": np.testing.assert_equal(np.asarray(actual).dtype, np.float64) else: @@ -2962,27 +2962,27 @@ class TestPercentile: @pytest.mark.parametrize("dtype", TYPE_CODES) def test_lower_higher(self, dtype): assert_equal(np.percentile(np.arange(10, dtype=dtype), 50, - interpolation='lower'), 4) + method='lower'), 4) assert_equal(np.percentile(np.arange(10, dtype=dtype), 50, - interpolation='higher'), 5) + method='higher'), 5) @pytest.mark.parametrize("dtype", TYPE_CODES) def test_midpoint(self, dtype): assert_equal(np.percentile(np.arange(10, dtype=dtype), 51, - interpolation='midpoint'), 4.5) + method='midpoint'), 4.5) assert_equal(np.percentile(np.arange(9, dtype=dtype) + 1, 50, - interpolation='midpoint'), 5) + method='midpoint'), 5) assert_equal(np.percentile(np.arange(11, dtype=dtype), 51, - interpolation='midpoint'), 5.5) + method='midpoint'), 5.5) assert_equal(np.percentile(np.arange(11, dtype=dtype), 50, - interpolation='midpoint'), 5) + method='midpoint'), 5) @pytest.mark.parametrize("dtype", TYPE_CODES) def test_nearest(self, dtype): assert_equal(np.percentile(np.arange(10, dtype=dtype), 51, - interpolation='nearest'), 5) + method='nearest'), 5) assert_equal(np.percentile(np.arange(10, dtype=dtype), 49, - interpolation='nearest'), 4) + method='nearest'), 4) def test_linear_interpolation_extrapolation(self): arr = np.random.rand(5) @@ -3019,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 @@ -3057,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]) @@ -3124,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) @@ -3146,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, @@ -3172,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): @@ -3253,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): @@ -3270,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) @@ -3333,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 @@ -3412,18 +3412,18 @@ 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) @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], - interpolation="nearest") + method="nearest") assert res.dtype == dtype def test_quantile_monotonic(self): -- cgit v1.2.1 From 85f3ddab60e522968dd6222a92a19a81eda036a8 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Mon, 8 Nov 2021 16:37:41 -0600 Subject: BUG: quantile discrete methods ended up using -1 as index sometimes Also, the closest-observation did not correctly support multiple quantiles calculated at the same time (broadcasting error). --- numpy/lib/tests/test_function_base.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 0b94b9a85..b67a31b18 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -3426,12 +3426,22 @@ class TestQuantile: method="nearest") assert res.dtype == dtype - def test_quantile_monotonic(self): + @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( -- cgit v1.2.1 From 3c81e3020a5b65c1590fc73a53ee9193a2c8b224 Mon Sep 17 00:00:00 2001 From: Devin Shanahan Date: Sun, 16 Jan 2022 05:14:04 -0700 Subject: MAINT: single value identification and test --- numpy/lib/tests/test_function_base.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index b67a31b18..874754a64 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -890,6 +890,19 @@ class TestDelete: with pytest.raises(IndexError): np.delete([0, 1, 2], np.array([], dtype=float)) + def test_single_item_array(self): + a_del = delete(self.a, 1) + a_del_arr = delete(self.a, np.array([1])) + a_del_lst = delete(self.a, [1]) + a_del_obj = delete(self.a, np.array([1], dtype=object)) + assert_equal(a_del, a_del_arr, a_del_lst, a_del_obj) + + nd_a_del = delete(self.nd_a, 1, axis=1) + nd_a_del_arr = delete(self.nd_a, np.array([1]), axis=1) + nd_a_del_lst = delete(self.nd_a, [1], axis=1) + nd_a_del_obj = delete(self.nd_a, np.array([1], dtype=object), axis=1) + assert_equal(nd_a_del, nd_a_del_arr, nd_a_del_lst, nd_a_del_obj) + class TestGradient: -- cgit v1.2.1 From c27f7817acb63ad05200c9c240a00cc5a7280394 Mon Sep 17 00:00:00 2001 From: warren Date: Mon, 9 May 2022 21:50:55 -0400 Subject: ENH: Add 'keepdims' to 'average()' and 'ma.average()'. --- numpy/lib/tests/test_function_base.py | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 874754a64..bdcbef91d 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -305,6 +305,29 @@ class TestAverage: assert_almost_equal(y5.mean(0), average(y5, 0)) assert_almost_equal(y5.mean(1), average(y5, 1)) + @pytest.mark.parametrize( + 'x, axis, expected_avg, weights, expected_wavg, expected_wsum', + [([1, 2, 3], None, [2.0], [3, 4, 1], [1.75], [8.0]), + ([[1, 2, 5], [1, 6, 11]], 0, [[1.0, 4.0, 8.0]], + [1, 3], [[1.0, 5.0, 9.5]], [[4, 4, 4]])], + ) + def test_basic_keepdims(self, x, axis, expected_avg, + weights, expected_wavg, expected_wsum): + avg = np.average(x, axis=axis, keepdims=True) + assert avg.shape == np.shape(expected_avg) + assert_array_equal(avg, expected_avg) + + wavg = np.average(x, axis=axis, weights=weights, keepdims=True) + assert wavg.shape == np.shape(expected_wavg) + assert_array_equal(wavg, expected_wavg) + + wavg, wsum = np.average(x, axis=axis, weights=weights, returned=True, + keepdims=True) + assert wavg.shape == np.shape(expected_wavg) + assert_array_equal(wavg, expected_wavg) + assert wsum.shape == np.shape(expected_wsum) + assert_array_equal(wsum, expected_wsum) + def test_weights(self): y = np.arange(10) w = np.arange(10) @@ -1242,11 +1265,11 @@ class TestTrimZeros: res = trim_zeros(arr) assert_array_equal(arr, res) - def test_list_to_list(self): res = trim_zeros(self.a.tolist()) assert isinstance(res, list) + class TestExtins: def test_basic(self): @@ -1759,6 +1782,7 @@ class TestLeaks: finally: gc.enable() + class TestDigitize: def test_forward(self): @@ -2339,6 +2363,7 @@ class Test_I0: with pytest.raises(TypeError, match="i0 not supported for complex values"): res = i0(a) + class TestKaiser: def test_simple(self): @@ -3474,6 +3499,7 @@ class TestQuantile: 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, min_value=0, max_value=1), -- cgit v1.2.1 From 9a5c5e886a4222e769e2f251ec7705c565d0cc4f Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Fri, 27 May 2022 15:14:39 -0700 Subject: TST: Adapt percentile test to changed promotion Promotion in percentile will now more aggressively preserve the input dtype for floating point types (rather than upgrading the type to at least float64). --- numpy/lib/tests/test_function_base.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index bdcbef91d..b6ea12158 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -2954,11 +2954,11 @@ class TestPercentile: H_F_TYPE_CODES = [(int_type, np.float64) for int_type in np.typecodes["AllInteger"] - ] + [(np.float16, np.float64), - (np.float32, np.float64), + ] + [(np.float16, np.float16), + (np.float32, np.float32), (np.float64, np.float64), (np.longdouble, np.longdouble), - (np.complex64, np.complex128), + (np.complex64, np.complex64), (np.complex128, np.complex128), (np.clongdouble, np.clongdouble), (np.dtype("O"), np.float64)] @@ -2980,10 +2980,15 @@ class TestPercentile: expected, input_dtype, expected_dtype): + expected_dtype = np.dtype(expected_dtype) + if np.get_promotion_state() == "legacy": + expected_dtype = np.promote_types(expected_dtype, np.float64) + 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) + np.testing.assert_almost_equal( + actual, expected_dtype.type(expected), 14) if method in ["inverted_cdf", "closest_observation"]: if input_dtype == "O": -- cgit v1.2.1 From 974c865219223742a07375bea1f6da246e3326ef Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Wed, 8 Jun 2022 16:35:31 -0700 Subject: API: Add leading underscore to `no_nep50_warning` and `get/set_promotion_state` --- numpy/lib/tests/test_function_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index b6ea12158..64318255b 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -2981,7 +2981,7 @@ class TestPercentile: input_dtype, expected_dtype): expected_dtype = np.dtype(expected_dtype) - if np.get_promotion_state() == "legacy": + if np._get_promotion_state() == "legacy": expected_dtype = np.promote_types(expected_dtype, np.float64) arr = np.asarray([15.0, 20.0, 35.0, 40.0, 50.0], dtype=input_dtype) -- cgit v1.2.1 From e67fe9f1a86013dbfd4a5ad2bd69aa6e7f60e1fb Mon Sep 17 00:00:00 2001 From: Srimukh Sripada Date: Mon, 27 Jun 2022 05:06:00 +0200 Subject: BUG: Use `keepdims` during normalization in `np.average` and `np.ma.average` (#21851) The keepdims flag needs to be applied during the calculation of the sum of the weights in np.average and np.ma.average. Not passing it causes weights to broadcast incorrectly. Fixes #21850 --- numpy/lib/tests/test_function_base.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 64318255b..9cc18a5e4 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -360,6 +360,18 @@ class TestAverage: assert_(np.average(y3, weights=w3).dtype == np.result_type(y3, w3)) + # test weights with `keepdims=False` and `keepdims=True` + x = np.array([2, 3, 4]).reshape(3, 1) + w = np.array([4, 5, 6]).reshape(3, 1) + + actual = np.average(x, weights=w, axis=1, keepdims=False) + desired = np.array([2., 3., 4.]) + assert_array_equal(actual, desired) + + actual = np.average(x, weights=w, axis=1, keepdims=True) + desired = np.array([[2.], [3.], [4.]]) + assert_array_equal(actual, desired) + def test_returned(self): y = np.array([[1, 2, 3], [4, 5, 6]]) -- cgit v1.2.1 From 6ac7142eedf3edd4e5432b8756ea0b0f6d869998 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Tue, 28 Jun 2022 01:06:26 -0700 Subject: BUG: Reject non integer array-likes with size 1 in delete (#21857) Non integer array-likes were not correctly rejected when a new fast-path was added to `np.delete` in gh-16895. This includes the _explicitly_ added `dtype=object` which should not be allowed since it is not allowed in normal indexing either. Closes gh-21840 --- numpy/lib/tests/test_function_base.py | 45 +++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 12 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 9cc18a5e4..8457551ca 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -925,18 +925,39 @@ class TestDelete: with pytest.raises(IndexError): np.delete([0, 1, 2], np.array([], dtype=float)) - def test_single_item_array(self): - a_del = delete(self.a, 1) - a_del_arr = delete(self.a, np.array([1])) - a_del_lst = delete(self.a, [1]) - a_del_obj = delete(self.a, np.array([1], dtype=object)) - assert_equal(a_del, a_del_arr, a_del_lst, a_del_obj) - - nd_a_del = delete(self.nd_a, 1, axis=1) - nd_a_del_arr = delete(self.nd_a, np.array([1]), axis=1) - nd_a_del_lst = delete(self.nd_a, [1], axis=1) - nd_a_del_obj = delete(self.nd_a, np.array([1], dtype=object), axis=1) - assert_equal(nd_a_del, nd_a_del_arr, nd_a_del_lst, nd_a_del_obj) + @pytest.mark.parametrize("indexer", [np.array([1]), [1]]) + def test_single_item_array(self, indexer): + a_del_int = delete(self.a, 1) + a_del = delete(self.a, indexer) + assert_equal(a_del_int, a_del) + + nd_a_del_int = delete(self.nd_a, 1, axis=1) + nd_a_del = delete(self.nd_a, np.array([1]), axis=1) + assert_equal(nd_a_del_int, nd_a_del) + + def test_single_item_array_non_int(self): + # Special handling for integer arrays must not affect non-integer ones. + # If `False` was cast to `0` it would delete the element: + res = delete(np.ones(1), np.array([False])) + assert_array_equal(res, np.ones(1)) + + # Test the more complicated (with axis) case from gh-21840 + x = np.ones((3, 1)) + false_mask = np.array([False], dtype=bool) + true_mask = np.array([True], dtype=bool) + + res = delete(x, false_mask, axis=-1) + assert_array_equal(res, x) + res = delete(x, true_mask, axis=-1) + assert_array_equal(res, x[:, :0]) + + # Object or e.g. timedeltas should *not* be allowed + with pytest.raises(IndexError): + delete(np.ones(2), np.array([0], dtype=object)) + + with pytest.raises(IndexError): + # timedeltas are sometimes "integral, but clearly not allowed: + delete(np.ones(2), np.array([0], dtype="m8[ns]")) class TestGradient: -- cgit v1.2.1 From 6d77c591c59b5678f14ae5af2127eebb7d2415bc Mon Sep 17 00:00:00 2001 From: Greg Lucas Date: Wed, 15 Apr 2020 10:28:02 -0600 Subject: ENH: Adding __array_ufunc__ capability to MaskedArrays. This enables any ufunc numpy operations that are called on a MaskedArray to use the masked version of that function automatically without needing to resort to np.ma.func() calls. --- numpy/lib/tests/test_function_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 8457551ca..1c3c32bdd 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -780,7 +780,7 @@ class TestDiff: mask=[[False, False], [True, False], [False, True], [True, True], [False, False]]) out = diff(x) - assert_array_equal(out.data, [[1], [1], [1], [1], [1]]) + assert_array_equal(out.data, [[1], [4], [6], [8], [1]]) assert_array_equal(out.mask, [[False], [True], [True], [True], [False]]) assert_(type(out) is type(x)) -- cgit v1.2.1 From 072ae770150a70e1821f71302b43cee4bba7055c Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Sat, 9 Jul 2022 21:22:16 +0300 Subject: Revert "ENH: Adding __array_ufunc__ capability to MaskedArrays" --- numpy/lib/tests/test_function_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 1c3c32bdd..8457551ca 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -780,7 +780,7 @@ class TestDiff: mask=[[False, False], [True, False], [False, True], [True, True], [False, False]]) out = diff(x) - assert_array_equal(out.data, [[1], [4], [6], [8], [1]]) + assert_array_equal(out.data, [[1], [1], [1], [1], [1]]) assert_array_equal(out.mask, [[False], [True], [True], [True], [False]]) assert_(type(out) is type(x)) -- cgit v1.2.1 From 8cd6f4ca00b6e0da3833fc267d50067b2ddbc069 Mon Sep 17 00:00:00 2001 From: Greg Lucas Date: Wed, 15 Apr 2020 10:28:02 -0600 Subject: ENH: Adding __array_ufunc__ capability to MaskedArrays. This enables any ufunc numpy operations that are called on a MaskedArray to use the masked version of that function automatically without needing to resort to np.ma.func() calls. --- numpy/lib/tests/test_function_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 8457551ca..1c3c32bdd 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -780,7 +780,7 @@ class TestDiff: mask=[[False, False], [True, False], [False, True], [True, True], [False, False]]) out = diff(x) - assert_array_equal(out.data, [[1], [1], [1], [1], [1]]) + assert_array_equal(out.data, [[1], [4], [6], [8], [1]]) assert_array_equal(out.mask, [[False], [True], [True], [True], [False]]) assert_(type(out) is type(x)) -- cgit v1.2.1 From 3321bc59ca5e47a8d8677fa4d1a9af37d570a835 Mon Sep 17 00:00:00 2001 From: mattip Date: Wed, 20 Jul 2022 09:23:32 +0300 Subject: Revert "ENH: Adding __array_ufunc__ capability to MaskedArrays." This reverts commit 8cd6f4ca00b6e0da3833fc267d50067b2ddbc069. --- numpy/lib/tests/test_function_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 1c3c32bdd..8457551ca 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -780,7 +780,7 @@ class TestDiff: mask=[[False, False], [True, False], [False, True], [True, True], [False, False]]) out = diff(x) - assert_array_equal(out.data, [[1], [4], [6], [8], [1]]) + assert_array_equal(out.data, [[1], [1], [1], [1], [1]]) assert_array_equal(out.mask, [[False], [True], [True], [True], [False]]) assert_(type(out) is type(x)) -- cgit v1.2.1 From 002df0e20f109dd001053f42bdc9a90632f536ff Mon Sep 17 00:00:00 2001 From: Pal Barta Date: Wed, 10 Aug 2022 11:20:50 -0400 Subject: TST: fix test_linear_interpolation_formula_symmetric The lerp test compared the output of the original and the symmetric functions by using basic assertion. Double precision errors could accumulate in a way that the 2 outputs mismatch by epsilon. For more information on the precision issue, see #22073 Fix: use assert_allclose instead for float comparison. --- numpy/lib/tests/test_function_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 8457551ca..56081b4f0 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -3579,7 +3579,7 @@ class TestLerp: # double subtraction is needed to remove the extra precision of t < 0.5 left = nfb._lerp(a, b, 1 - (1 - t)) right = nfb._lerp(b, a, 1 - t) - assert left == right + assert_allclose(left, right) def test_linear_interpolation_formula_0d_inputs(self): a = np.array(2) -- cgit v1.2.1 From 25d5e385ec537f911702f905ca050815e320865a Mon Sep 17 00:00:00 2001 From: Pieter Eendebak Date: Mon, 18 Jul 2022 21:54:00 +0200 Subject: BUG: fix np.average for Fraction elements --- numpy/lib/tests/test_function_base.py | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 56081b4f0..277843222 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -421,6 +421,11 @@ class TestAverage: w /= w.sum() assert_almost_equal(a.mean(0), average(a, weights=w)) + def test_average_class_without_dtype(self): + # see gh-21988 + a = np.array([Fraction(1, 5), Fraction(3, 5)]) + assert_equal(np.average(a), Fraction(2, 5)) + class TestSelect: choices = [np.array([1, 2, 3]), np.array([4, 5, 6]), -- cgit v1.2.1 From 8ca9221ec58e65dbf2ac9d669de216c0366088c1 Mon Sep 17 00:00:00 2001 From: Ross Barnowski Date: Wed, 19 Oct 2022 19:35:25 -0700 Subject: DEP: Add deprecation warning and check warning in test. --- numpy/lib/tests/test_function_base.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 277843222..e407fc78c 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -2427,11 +2427,12 @@ class TestMsort: A = np.array([[0.44567325, 0.79115165, 0.54900530], [0.36844147, 0.37325583, 0.96098397], [0.64864341, 0.52929049, 0.39172155]]) - assert_almost_equal( - msort(A), - np.array([[0.36844147, 0.37325583, 0.39172155], - [0.44567325, 0.52929049, 0.54900530], - [0.64864341, 0.79115165, 0.96098397]])) + with pytest.warns(DeprecationWarning, match="msort is deprecated"): + assert_almost_equal( + msort(A), + np.array([[0.36844147, 0.37325583, 0.39172155], + [0.44567325, 0.52929049, 0.54900530], + [0.64864341, 0.79115165, 0.96098397]])) class TestMeshgrid: -- cgit v1.2.1 From 67841947b458f6bdc6c40d014512da9bc4717a3e Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Thu, 27 Oct 2022 14:57:14 +0200 Subject: TST,MAINT: Replace most `setup` with `setup_method` (also teardown) In some cases, the replacement is clearly not what is intended, in those (where setup was called explicitly), I mostly renamed `setup` to `_setup`. The `test_ccompile_opt` is a bit confusing, so left it right now (this will probably fail) --- numpy/lib/tests/test_function_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index e407fc78c..88d4987e6 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -850,7 +850,7 @@ class TestDiff: class TestDelete: - def setup(self): + def setup_method(self): self.a = np.arange(5) self.nd_a = np.arange(5).repeat(2).reshape(1, 5, 2) -- cgit v1.2.1 From 08c6e9c142e619ac5175b6a13342ba2f2c571ddd Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Thu, 10 Nov 2022 11:54:21 -0800 Subject: TST: Skip tests that are not currently supported in wasm --- numpy/lib/tests/test_function_base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 88d4987e6..c5b31ebf4 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -15,7 +15,7 @@ from numpy import ma from numpy.testing import ( assert_, assert_equal, assert_array_equal, assert_almost_equal, assert_array_almost_equal, assert_raises, assert_allclose, IS_PYPY, - assert_warns, assert_raises_regex, suppress_warnings, HAS_REFCOUNT, + assert_warns, assert_raises_regex, suppress_warnings, HAS_REFCOUNT, IS_WASM ) import numpy.lib.function_base as nfb from numpy.random import rand @@ -3754,6 +3754,7 @@ class TestMedian: b[2] = np.nan assert_equal(np.median(a, (0, 2)), b) + @pytest.mark.skipif(IS_WASM, reason="fp errors don't work correctly") def test_empty(self): # mean(empty array) emits two warnings: empty slice and divide by 0 a = np.array([], dtype=float) -- cgit v1.2.1 From 91432a36a3611c2374ea9e2d45592f0ac5e71adb Mon Sep 17 00:00:00 2001 From: Roy Smart Date: Fri, 2 Dec 2022 16:09:33 -0700 Subject: BUG: `keepdims=True` is ignored if `out` is not `None` in `numpy.median()`, `numpy.percentile()`, and `numpy.quantile()`. Closes #22714, #22544. --- numpy/lib/tests/test_function_base.py | 50 +++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index c5b31ebf4..1bb4c4efa 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -25,6 +25,7 @@ from numpy.lib import ( i0, insert, interp, kaiser, meshgrid, msort, piecewise, place, rot90, select, setxor1d, sinc, trapz, trim_zeros, unwrap, unique, vectorize ) +from numpy.core.numeric import normalize_axis_tuple def get_mat(n): @@ -3331,6 +3332,32 @@ class TestPercentile: assert_equal(np.percentile(d, [1, 7], axis=(0, 3), keepdims=True).shape, (2, 1, 5, 7, 1)) + @pytest.mark.parametrize('q', [7, [1, 7]]) + @pytest.mark.parametrize( + argnames='axis', + argvalues=[ + None, + 1, + (1,), + (0, 1), + (-3, -1), + ] + ) + def test_keepdims_out(self, q, axis): + d = np.ones((3, 5, 7, 11)) + if axis is None: + shape_out = (1,) * d.ndim + else: + axis_norm = normalize_axis_tuple(axis, d.ndim) + shape_out = tuple( + 1 if i in axis_norm else d.shape[i] for i in range(d.ndim)) + shape_out = np.shape(q) + shape_out + + out = np.empty(shape_out) + result = np.percentile(d, q, axis=axis, keepdims=True, out=out) + assert result is out + assert_equal(result.shape, shape_out) + def test_out(self): o = np.zeros((4,)) d = np.ones((3, 4)) @@ -3843,6 +3870,29 @@ class TestMedian: assert_equal(np.median(d, axis=(0, 1, 3), keepdims=True).shape, (1, 1, 7, 1)) + @pytest.mark.parametrize( + argnames='axis', + argvalues=[ + None, + 1, + (1, ), + (0, 1), + (-3, -1), + ] + ) + def test_keepdims_out(self, axis): + d = np.ones((3, 5, 7, 11)) + if axis is None: + shape_out = (1,) * d.ndim + else: + axis_norm = normalize_axis_tuple(axis, d.ndim) + shape_out = tuple( + 1 if i in axis_norm else d.shape[i] for i in range(d.ndim)) + out = np.empty(shape_out) + result = np.median(d, axis=axis, keepdims=True, out=out) + assert result is out + assert_equal(result.shape, shape_out) + class TestAdd_newdoc_ufunc: -- cgit v1.2.1 From b3c0960a54c81a26bd07912dda96db9e356b34d1 Mon Sep 17 00:00:00 2001 From: Matteo Raso <33975162+MatteoRaso@users.noreply.github.com> Date: Thu, 8 Dec 2022 07:01:59 -0500 Subject: BUG: Quantile function on complex number now throws an error (#22652) (#22703) Since percentile is more or less identical to quantile, I also made it throw an error if it receives a complex input. I also made nanquantile and nanpercentile throw errors as well. * Made the changes recommended by seberg * Fixed a test for PR 22703 * Fixed tests for quantile * Shortened some more lines * Fixup more lines Co-authored-by: Sebastian Berg --- numpy/lib/tests/test_function_base.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 1bb4c4efa..e38a187d8 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -2973,6 +2973,14 @@ class TestPercentile: o = np.ones((1,)) np.percentile(d, 5, None, o, False, 'linear') + def test_complex(self): + arr_c = np.array([0.5+3.0j, 2.1+0.5j, 1.6+2.3j], dtype='G') + assert_raises(TypeError, np.percentile, arr_c, 0.5) + arr_c = np.array([0.5+3.0j, 2.1+0.5j, 1.6+2.3j], dtype='D') + assert_raises(TypeError, np.percentile, arr_c, 0.5) + arr_c = np.array([0.5+3.0j, 2.1+0.5j, 1.6+2.3j], dtype='F') + assert_raises(TypeError, np.percentile, arr_c, 0.5) + def test_2D(self): x = np.array([[1, 1, 1], [1, 1, 1], @@ -2981,7 +2989,7 @@ class TestPercentile: [1, 1, 1]]) assert_array_equal(np.percentile(x, 50, axis=0), [1, 1, 1]) - @pytest.mark.parametrize("dtype", np.typecodes["AllFloat"]) + @pytest.mark.parametrize("dtype", np.typecodes["Float"]) 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) @@ -2998,9 +3006,6 @@ class TestPercentile: (np.float32, np.float32), (np.float64, np.float64), (np.longdouble, np.longdouble), - (np.complex64, np.complex64), - (np.complex128, np.complex128), - (np.clongdouble, np.clongdouble), (np.dtype("O"), np.float64)] @pytest.mark.parametrize(["input_dtype", "expected_dtype"], H_F_TYPE_CODES) @@ -3040,7 +3045,7 @@ class TestPercentile: np.testing.assert_equal(np.asarray(actual).dtype, np.dtype(expected_dtype)) - TYPE_CODES = np.typecodes["AllInteger"] + np.typecodes["AllFloat"] + "O" + TYPE_CODES = np.typecodes["AllInteger"] + np.typecodes["Float"] + "O" @pytest.mark.parametrize("dtype", TYPE_CODES) def test_lower_higher(self, dtype): @@ -3517,6 +3522,15 @@ class TestQuantile: x = np.arange(8) assert_equal(np.quantile(x, Fraction(1, 2)), Fraction(7, 2)) + def test_complex(self): + #See gh-22652 + arr_c = np.array([0.5+3.0j, 2.1+0.5j, 1.6+2.3j], dtype='G') + assert_raises(TypeError, np.quantile, arr_c, 0.5) + arr_c = np.array([0.5+3.0j, 2.1+0.5j, 1.6+2.3j], dtype='D') + assert_raises(TypeError, np.quantile, arr_c, 0.5) + arr_c = np.array([0.5+3.0j, 2.1+0.5j, 1.6+2.3j], dtype='F') + assert_raises(TypeError, np.quantile, arr_c, 0.5) + def test_no_p_overwrite(self): # this is worth retesting, because quantile does not make a copy p0 = np.array([0, 0.75, 0.25, 0.5, 1.0]) -- cgit v1.2.1 From dfc4c174d6a0e16da154d525db2fc29ce569f1b4 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Wed, 14 Dec 2022 15:02:58 +0100 Subject: TST: Remove outdated xfail from quantile tests There should be more tests for this, but this now passes. --- numpy/lib/tests/test_function_base.py | 1 - 1 file changed, 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index e38a187d8..ecba35f2d 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -3484,7 +3484,6 @@ class TestQuantile: 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) -- cgit v1.2.1 From 88cdaa21aea87ec7d56d1d583500ab2659a5e65e Mon Sep 17 00:00:00 2001 From: Matteo Raso Date: Wed, 18 Jan 2023 02:25:00 -0500 Subject: BUG: Added __name__ atribute to vectorize class (#23021) --- numpy/lib/tests/test_function_base.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index ecba35f2d..69e4c4848 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1780,6 +1780,13 @@ class TestVectorize: assert_equal(type(r), subclass) assert_equal(r, m * v) + def test_name(self): + #See gh-23021 + @np.vectorize + def f2(a, b): + return a + b + + assert f2.__name__ == 'f2' class TestLeaks: class A: -- cgit v1.2.1 From ade008bf5fba3cbc43ffbdf5ee261953a8a71a3a Mon Sep 17 00:00:00 2001 From: Matteo Raso Date: Sat, 21 Jan 2023 20:20:30 -0500 Subject: ENH: Enabled use of numpy.vectorize as decorator (#9477) Most of this code comes from PR-9593, but with the default value for pyfunc being numpy._NoValue instead of None, no override of __new__, and no effort to make subclassing possible. Co-Authored-By: Michael Lamparski --- numpy/lib/tests/test_function_base.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 69e4c4848..169484a09 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1788,6 +1788,36 @@ class TestVectorize: assert f2.__name__ == 'f2' + def test_decorator(self): + @vectorize + def addsubtract(a, b): + if a > b: + return a - b + else: + return a + b + + r = addsubtract([0, 3, 6, 9], [1, 3, 5, 7]) + assert_array_equal(r, [1, 6, 1, 2]) + + def test_signature_otypes_decorator(self): + @vectorize(signature='(n)->(n)', otypes=['float64']) + def f(x): + return x + + r = f([1, 2, 3]) + assert_equal(r.dtype, np.dtype('float64')) + assert_array_equal(r, [1, 2, 3]) + assert f.__name__ == 'f' + + def test_positional_regression_9477(self): + # This supplies the first keyword argument as a positional, + # to ensure that they are still properly forwarded after the + # enhancement for #9477 + f = vectorize((lambda x: x), ['float64']) + r = f([2]) + assert_equal(r.dtype, np.dtype('float64')) + + class TestLeaks: class A: iters = 20 -- cgit v1.2.1 From 84596aeec1682de93d82c60b53726838b29ad311 Mon Sep 17 00:00:00 2001 From: Matteo Raso Date: Fri, 27 Jan 2023 02:03:00 -0500 Subject: Added test for vectorize decorator project This test makes sure a function's docstring is properly preserved after calling the vectorize decorator. --- numpy/lib/tests/test_function_base.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 169484a09..6499b78b7 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1799,6 +1799,14 @@ class TestVectorize: r = addsubtract([0, 3, 6, 9], [1, 3, 5, 7]) assert_array_equal(r, [1, 6, 1, 2]) + def test_docstring(self): + @vectorize + def f(x): + """Docstring""" + return x + + assert f.__doc__ == "Docstring" + def test_signature_otypes_decorator(self): @vectorize(signature='(n)->(n)', otypes=['float64']) def f(x): -- cgit v1.2.1 From 7a2ded1522305cfbab4e34a18198f3cbcae7755c Mon Sep 17 00:00:00 2001 From: Matteo Raso Date: Wed, 8 Feb 2023 20:39:55 -0500 Subject: Added a test for positional args (PR-23061) --- numpy/lib/tests/test_function_base.py | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 6499b78b7..b56d776cb 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1817,6 +1817,17 @@ class TestVectorize: assert_array_equal(r, [1, 2, 3]) assert f.__name__ == 'f' + def test_decorator_positional_args(self): + A = np.vectorize(abs, ['float64'], "return float absolute value") + y1 = A([1, -1, 0, 0.3, 5]) + + @vectorize(['float64'], "return float absolute value") + def myabs(a): + return abs(a) + + y2 = myabs([1, -1, 0, 0.3, 5]) + assert_array_equal(y1, y2) + def test_positional_regression_9477(self): # This supplies the first keyword argument as a positional, # to ensure that they are still properly forwarded after the -- cgit v1.2.1 From 4b82e29a18cd2c17b258bab0e2d937ab2157377b Mon Sep 17 00:00:00 2001 From: Matteo Raso Date: Thu, 9 Feb 2023 22:59:46 -0500 Subject: @vectorize now requires arguments to specify keywords This reverses commit 7a2ded1522305 --- numpy/lib/tests/test_function_base.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index b56d776cb..416a9431b 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1817,16 +1817,15 @@ class TestVectorize: assert_array_equal(r, [1, 2, 3]) assert f.__name__ == 'f' - def test_decorator_positional_args(self): - A = np.vectorize(abs, ['float64'], "return float absolute value") - y1 = A([1, -1, 0, 0.3, 5]) - - @vectorize(['float64'], "return float absolute value") - def myabs(a): - return abs(a) - - y2 = myabs([1, -1, 0, 0.3, 5]) - assert_array_equal(y1, y2) + def test_bad_input(self): + with assert_raises(TypeError): + A = np.vectorize(pyfunc = 3) + + def test_no_keywords(self): + with assert_raises(TypeError): + @np.vectorize("string") + def foo(): + return "bar" def test_positional_regression_9477(self): # This supplies the first keyword argument as a positional, -- cgit v1.2.1 From c03e84044a05f0b2358a1cbfc4158e83cba4b835 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Thu, 26 Jan 2023 12:16:23 +0100 Subject: API: Modify `gradient` to return a tuple rather than a list This change is staged for NumPy 2.0, I assume we could get away with it otherwise, but it is a nice example and probably not pressing. --- numpy/lib/tests/test_function_base.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index ecba35f2d..fb98a94cd 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1217,6 +1217,13 @@ class TestGradient: dfdx = gradient(f, x) assert_array_equal(dfdx, [0.5, 0.5]) + def test_return_type(self): + res = np.gradient(([1, 2], [2, 3])) + if np._numpy2_behavior: + assert type(res) is tuple + else: + assert type(res) is list + class TestAngle: -- cgit v1.2.1 From 9d5eafe596e75e30a85c01ed62bb5bea9389adc8 Mon Sep 17 00:00:00 2001 From: Sebastian Berg Date: Fri, 10 Feb 2023 15:51:57 +0100 Subject: MAINT: Use `np._using_numpy2_behavior()` and initialize it in C --- numpy/lib/tests/test_function_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index fb98a94cd..cc8003f61 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1219,7 +1219,7 @@ class TestGradient: def test_return_type(self): res = np.gradient(([1, 2], [2, 3])) - if np._numpy2_behavior: + if np._using_numpy2_behavior(): assert type(res) is tuple else: assert type(res) is list -- cgit v1.2.1 From 9990f98f2e9e1a55f5d42206cbc6709a3efff418 Mon Sep 17 00:00:00 2001 From: Ralf Gommers Date: Thu, 2 Mar 2023 14:57:43 +0000 Subject: DEP: deprecate `product`, `cumproduct`, `sometrue`, `alltrue` [skip cirrus] --- numpy/lib/tests/test_function_base.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index cc8003f61..3ec46735c 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -229,8 +229,8 @@ class TestAny: def test_nd(self): y1 = [[0, 0, 0], [0, 1, 0], [1, 1, 0]] assert_(np.any(y1)) - assert_array_equal(np.sometrue(y1, axis=0), [1, 1, 0]) - assert_array_equal(np.sometrue(y1, axis=1), [0, 1, 1]) + assert_array_equal(np.any(y1, axis=0), [1, 1, 0]) + assert_array_equal(np.any(y1, axis=1), [0, 1, 1]) class TestAll: @@ -247,8 +247,8 @@ class TestAll: def test_nd(self): y1 = [[0, 0, 1], [0, 1, 1], [1, 1, 1]] assert_(not np.all(y1)) - assert_array_equal(np.alltrue(y1, axis=0), [0, 0, 1]) - assert_array_equal(np.alltrue(y1, axis=1), [0, 0, 1]) + assert_array_equal(np.all(y1, axis=0), [0, 0, 1]) + assert_array_equal(np.all(y1, axis=1), [0, 0, 1]) class TestCopy: -- cgit v1.2.1 From ed1732410f51293e4c5f63dcf162d9f1d417335a Mon Sep 17 00:00:00 2001 From: Matti Picus Date: Mon, 27 Mar 2023 09:36:25 +0300 Subject: Revert "ENH: Enabled the use of numpy.vectorize as a decorator" --- numpy/lib/tests/test_function_base.py | 55 ----------------------------------- 1 file changed, 55 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 97ca13bfb..3ec46735c 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1787,61 +1787,6 @@ class TestVectorize: assert_equal(type(r), subclass) assert_equal(r, m * v) - def test_name(self): - #See gh-23021 - @np.vectorize - def f2(a, b): - return a + b - - assert f2.__name__ == 'f2' - - def test_decorator(self): - @vectorize - def addsubtract(a, b): - if a > b: - return a - b - else: - return a + b - - r = addsubtract([0, 3, 6, 9], [1, 3, 5, 7]) - assert_array_equal(r, [1, 6, 1, 2]) - - def test_docstring(self): - @vectorize - def f(x): - """Docstring""" - return x - - assert f.__doc__ == "Docstring" - - def test_signature_otypes_decorator(self): - @vectorize(signature='(n)->(n)', otypes=['float64']) - def f(x): - return x - - r = f([1, 2, 3]) - assert_equal(r.dtype, np.dtype('float64')) - assert_array_equal(r, [1, 2, 3]) - assert f.__name__ == 'f' - - def test_bad_input(self): - with assert_raises(TypeError): - A = np.vectorize(pyfunc = 3) - - def test_no_keywords(self): - with assert_raises(TypeError): - @np.vectorize("string") - def foo(): - return "bar" - - def test_positional_regression_9477(self): - # This supplies the first keyword argument as a positional, - # to ensure that they are still properly forwarded after the - # enhancement for #9477 - f = vectorize((lambda x: x), ['float64']) - r = f([2]) - assert_equal(r.dtype, np.dtype('float64')) - class TestLeaks: class A: -- cgit v1.2.1 From dfaa72d72453b8738ec711180e03da824651e46b Mon Sep 17 00:00:00 2001 From: Matteo Raso Date: Sat, 1 Apr 2023 21:45:16 -0400 Subject: Fixed edge case where pyfunc has no attribute `__name__` --- numpy/lib/tests/test_function_base.py | 80 +++++++++++++++++++++++++++++------ 1 file changed, 68 insertions(+), 12 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 3ec46735c..6f4449c68 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -8,7 +8,7 @@ import pytest import hypothesis from hypothesis.extra.numpy import arrays import hypothesis.strategies as st - +from functools import partial import numpy as np from numpy import ma @@ -229,8 +229,8 @@ class TestAny: def test_nd(self): y1 = [[0, 0, 0], [0, 1, 0], [1, 1, 0]] assert_(np.any(y1)) - assert_array_equal(np.any(y1, axis=0), [1, 1, 0]) - assert_array_equal(np.any(y1, axis=1), [0, 1, 1]) + assert_array_equal(np.sometrue(y1, axis=0), [1, 1, 0]) + assert_array_equal(np.sometrue(y1, axis=1), [0, 1, 1]) class TestAll: @@ -247,8 +247,8 @@ class TestAll: def test_nd(self): y1 = [[0, 0, 1], [0, 1, 1], [1, 1, 1]] assert_(not np.all(y1)) - assert_array_equal(np.all(y1, axis=0), [0, 0, 1]) - assert_array_equal(np.all(y1, axis=1), [0, 0, 1]) + assert_array_equal(np.alltrue(y1, axis=0), [0, 0, 1]) + assert_array_equal(np.alltrue(y1, axis=1), [0, 0, 1]) class TestCopy: @@ -1217,13 +1217,6 @@ class TestGradient: dfdx = gradient(f, x) assert_array_equal(dfdx, [0.5, 0.5]) - def test_return_type(self): - res = np.gradient(([1, 2], [2, 3])) - if np._using_numpy2_behavior(): - assert type(res) is tuple - else: - assert type(res) is list - class TestAngle: @@ -1787,6 +1780,69 @@ class TestVectorize: assert_equal(type(r), subclass) assert_equal(r, m * v) + def test_name(self): + #See gh-23021 + @np.vectorize + def f2(a, b): + return a + b + + assert f2.__name__ == 'f2' + + def test_decorator(self): + @vectorize + def addsubtract(a, b): + if a > b: + return a - b + else: + return a + b + + r = addsubtract([0, 3, 6, 9], [1, 3, 5, 7]) + assert_array_equal(r, [1, 6, 1, 2]) + + def test_docstring(self): + @vectorize + def f(x): + """Docstring""" + return x + + assert f.__doc__ == "Docstring" + + def test_partial(self): + def foo(x, y): + return x + y + + bar = partial(foo, 3) + vbar = np.vectorize(bar) + assert vbar(1) == 4 + + def test_signature_otypes_decorator(self): + @vectorize(signature='(n)->(n)', otypes=['float64']) + def f(x): + return x + + r = f([1, 2, 3]) + assert_equal(r.dtype, np.dtype('float64')) + assert_array_equal(r, [1, 2, 3]) + assert f.__name__ == 'f' + + def test_bad_input(self): + with assert_raises(TypeError): + A = np.vectorize(pyfunc = 3) + + def test_no_keywords(self): + with assert_raises(TypeError): + @np.vectorize("string") + def foo(): + return "bar" + + def test_positional_regression_9477(self): + # This supplies the first keyword argument as a positional, + # to ensure that they are still properly forwarded after the + # enhancement for #9477 + f = vectorize((lambda x: x), ['float64']) + r = f([2]) + assert_equal(r.dtype, np.dtype('float64')) + class TestLeaks: class A: -- cgit v1.2.1 From cf07cd7c715d42913c4d92d0a8bef128fd2e8367 Mon Sep 17 00:00:00 2001 From: Matteo Raso Date: Sat, 1 Apr 2023 21:51:59 -0400 Subject: Fixed docstring test --- numpy/lib/tests/test_function_base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 6f4449c68..df0c4a003 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1805,7 +1805,8 @@ class TestVectorize: """Docstring""" return x - assert f.__doc__ == "Docstring" + if sys.flags.optimize < 2: + assert f.__doc__ == "Docstring" def test_partial(self): def foo(x, y): -- cgit v1.2.1 From f283fe07eb302df130c5dafaf07d06a8fb9c34fd Mon Sep 17 00:00:00 2001 From: Matteo Raso Date: Sat, 1 Apr 2023 23:11:26 -0400 Subject: Fixed failing tests --- numpy/lib/tests/test_function_base.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index df0c4a003..09d1195ad 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -229,8 +229,8 @@ class TestAny: def test_nd(self): y1 = [[0, 0, 0], [0, 1, 0], [1, 1, 0]] assert_(np.any(y1)) - assert_array_equal(np.sometrue(y1, axis=0), [1, 1, 0]) - assert_array_equal(np.sometrue(y1, axis=1), [0, 1, 1]) + assert_array_equal(np.any(y1, axis=0), [1, 1, 0]) + assert_array_equal(np.any(y1, axis=1), [0, 1, 1]) class TestAll: @@ -247,8 +247,8 @@ class TestAll: def test_nd(self): y1 = [[0, 0, 1], [0, 1, 1], [1, 1, 1]] assert_(not np.all(y1)) - assert_array_equal(np.alltrue(y1, axis=0), [0, 0, 1]) - assert_array_equal(np.alltrue(y1, axis=1), [0, 0, 1]) + assert_array_equal(np.all(y1, axis=0), [0, 0, 1]) + assert_array_equal(np.all(y1, axis=1), [0, 0, 1]) class TestCopy: @@ -1217,6 +1217,13 @@ class TestGradient: dfdx = gradient(f, x) assert_array_equal(dfdx, [0.5, 0.5]) + def test_return_type(self): + res = np.gradient(([1, 2], [2, 3])) + if np._using_numpy2_behavior(): + assert type(res) is tuple + else: + assert type(res) is list + class TestAngle: -- cgit v1.2.1 From 30c047cdb2e0c0b233e5dc3b61c081ce1f6df3d3 Mon Sep 17 00:00:00 2001 From: Christian Lorentzen Date: Fri, 28 Apr 2023 13:34:53 +0200 Subject: TST: add tests for numpy.quantile (#23129) This PR adds additional tests for quantiles: 1. Identification equation $E[V(q, Y)] = 0$ 2. Adding a constant $c > 0$: $q(c + Y) = c + q(Y)$ 3. Multiplying by a constant $c > 0$: $q(c \cdot Y) = c \cdot q(y)$ 4. Multiplying by $-1$: $q_{\alpha}(-Y) = -q_{1-\alpha}(Y)$ (Note by seberg as reviewer: These tests are fairly complex, but may be useful for future development. But if they seem too complicated, they are probably not really vital and could be shortened or removed.) --- numpy/lib/tests/test_function_base.py | 105 ++++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 5 deletions(-) (limited to 'numpy/lib/tests/test_function_base.py') diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 09d1195ad..b0944ec85 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -3538,9 +3538,20 @@ class TestPercentile: np.percentile([1, 2, 3, 4.0], q) +quantile_methods = [ + 'inverted_cdf', 'averaged_inverted_cdf', 'closest_observation', + 'interpolated_inverted_cdf', 'hazen', 'weibull', 'linear', + 'median_unbiased', 'normal_unbiased', 'nearest', 'lower', 'higher', + 'midpoint'] + + class TestQuantile: # most of this is already tested by TestPercentile + def V(self, x, y, alpha): + # Identification function used in several tests. + return (x >= y) - alpha + def test_max_ulp(self): x = [0.0, 0.2, 0.4] a = np.quantile(x, 0.45) @@ -3619,11 +3630,7 @@ class TestQuantile: 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']) + @pytest.mark.parametrize("method", quantile_methods) def test_quantile_monotonic(self, method): # GH 14685 # test that the return value of quantile is monotonic if p0 is ordered @@ -3654,6 +3661,94 @@ class TestQuantile: assert np.isscalar(actual) assert_equal(np.quantile(a, 0.5), np.nan) + @pytest.mark.parametrize("method", quantile_methods) + @pytest.mark.parametrize("alpha", [0.2, 0.5, 0.9]) + def test_quantile_identification_equation(self, method, alpha): + # Test that the identification equation holds for the empirical + # CDF: + # E[V(x, Y)] = 0 <=> x is quantile + # with Y the random variable for which we have observed values and + # V(x, y) the canonical identification function for the quantile (at + # level alpha), see + # https://doi.org/10.48550/arXiv.0912.0902 + rng = np.random.default_rng(4321) + # We choose n and alpha such that we cover 3 cases: + # - n * alpha is an integer + # - n * alpha is a float that gets rounded down + # - n * alpha is a float that gest rounded up + n = 102 # n * alpha = 20.4, 51. , 91.8 + y = rng.random(n) + x = np.quantile(y, alpha, method=method) + if method in ("higher",): + # These methods do not fulfill the identification equation. + assert np.abs(np.mean(self.V(x, y, alpha))) > 0.1 / n + elif int(n * alpha) == n * alpha: + # We can expect exact results, up to machine precision. + assert_allclose(np.mean(self.V(x, y, alpha)), 0, atol=1e-14) + else: + # V = (x >= y) - alpha cannot sum to zero exactly but within + # "sample precision". + assert_allclose(np.mean(self.V(x, y, alpha)), 0, + atol=1 / n / np.amin([alpha, 1 - alpha])) + + @pytest.mark.parametrize("method", quantile_methods) + @pytest.mark.parametrize("alpha", [0.2, 0.5, 0.9]) + def test_quantile_add_and_multiply_constant(self, method, alpha): + # Test that + # 1. quantile(c + x) = c + quantile(x) + # 2. quantile(c * x) = c * quantile(x) + # 3. quantile(-x) = -quantile(x, 1 - alpha) + # On empirical quantiles, this equation does not hold exactly. + # Koenker (2005) "Quantile Regression" Chapter 2.2.3 calls these + # properties equivariance. + rng = np.random.default_rng(4321) + # We choose n and alpha such that we have cases for + # - n * alpha is an integer + # - n * alpha is a float that gets rounded down + # - n * alpha is a float that gest rounded up + n = 102 # n * alpha = 20.4, 51. , 91.8 + y = rng.random(n) + q = np.quantile(y, alpha, method=method) + c = 13.5 + + # 1 + assert_allclose(np.quantile(c + y, alpha, method=method), c + q) + # 2 + assert_allclose(np.quantile(c * y, alpha, method=method), c * q) + # 3 + q = -np.quantile(-y, 1 - alpha, method=method) + if method == "inverted_cdf": + if ( + n * alpha == int(n * alpha) + or np.round(n * alpha) == int(n * alpha) + 1 + ): + assert_allclose(q, np.quantile(y, alpha, method="higher")) + else: + assert_allclose(q, np.quantile(y, alpha, method="lower")) + elif method == "closest_observation": + if n * alpha == int(n * alpha): + assert_allclose(q, np.quantile(y, alpha, method="higher")) + elif np.round(n * alpha) == int(n * alpha) + 1: + assert_allclose( + q, np.quantile(y, alpha + 1/n, method="higher")) + else: + assert_allclose(q, np.quantile(y, alpha, method="lower")) + elif method == "interpolated_inverted_cdf": + assert_allclose(q, np.quantile(y, alpha + 1/n, method=method)) + elif method == "nearest": + if n * alpha == int(n * alpha): + assert_allclose(q, np.quantile(y, alpha + 1/n, method=method)) + else: + assert_allclose(q, np.quantile(y, alpha, method=method)) + elif method == "lower": + assert_allclose(q, np.quantile(y, alpha, method="higher")) + elif method == "higher": + assert_allclose(q, np.quantile(y, alpha, method="lower")) + else: + # "averaged_inverted_cdf", "hazen", "weibull", "linear", + # "median_unbiased", "normal_unbiased", "midpoint" + assert_allclose(q, np.quantile(y, alpha, method=method)) + class TestLerp: @hypothesis.given(t0=st.floats(allow_nan=False, allow_infinity=False, -- cgit v1.2.1