From 07cbe999f84be4d1b0a35fdb15b53cc17bc4341d Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Wed, 28 Aug 2013 20:40:17 -0500 Subject: ENH: percentile function with additional parameters and vecorization The percentile function was enhanced by adding limit and interpolation parameters to give it similar functionality to SciPy's stats.scoreatpercentile function. In addition the function was vecorized along q and rewritten to use the partition method for better performance. --- numpy/lib/tests/test_function_base.py | 137 +++++++++++++++++++++++++++++----- 1 file changed, 117 insertions(+), 20 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 f52eb5fbe..02597c78b 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1440,27 +1440,124 @@ def compare_results(res, desired): assert_array_equal(res[i], desired[i]) -def test_percentile_list(): - assert_equal(np.percentile([1, 2, 3], 0), 1) +class TestScoreatpercentile(TestCase): - -def test_percentile_out(): - x = np.array([1, 2, 3]) - y = np.zeros((3,)) - p = (1, 2, 3) - np.percentile(x, p, out=y) - assert_equal(y, np.percentile(x, p)) - - 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)) - - y = np.zeros((3, 2)) - np.percentile(x, p, axis=1, out=y) - assert_equal(y, np.percentile(x, p, axis=1)) + def test_basic(self): + x = np.arange(8) * 0.5 + assert_equal(np.percentile(x, 0), 0.) + assert_equal(np.percentile(x, 100), 3.5) + assert_equal(np.percentile(x, 50), 1.75) + + def test_2D(self): + x = np.array([[1, 1, 1], + [1, 1, 1], + [4, 4, 3], + [1, 1, 1], + [1, 1, 1]]) + assert_array_equal(np.percentile(x, 50, axis=0), [[1, 1, 1]]) + + def test_limit(self): + x = np.arange(10) + assert_equal(np.percentile(x, 50, limit=(2, 5)), 3.5) + assert_equal(np.percentile([2, 3, 4, 5], 50), 3.5) + + assert_equal(np.percentile(x, 50, limit=(-1, 8)), 4) + assert_equal(np.percentile([0, 1, 2, 3, 4, 5, 6, 7, 8], 50), 4) + + assert_equal(np.percentile(x, 50, limit=(4, 11)), 6.5) + assert_equal(np.percentile([4, 5, 6, 7, 8, 9], 50, ), 6.5) + + def test_linear(self): + + # Test defaults + assert_equal(np.percentile(range(10), 50), 4.5) + assert_equal(np.percentile(range(10), 50, (2, 7)), 4.5) + assert_equal(np.percentile(range(100), 50, limit=(1, 8)), 4.5) + assert_equal(np.percentile(np.array([1, 10, 100]), 50, (10, 100)), 55) + assert_equal(np.percentile(np.array([1, 10, 100]), 50, (1, 10)), 5.5) + + # explicitly specify interpolation_method 'fraction' (the default) + assert_equal(np.percentile(range(10), 50, + interpolation='linear'), 4.5) + assert_equal(np.percentile(range(10), 50, limit=(2, 7), + interpolation='linear'), 4.5) + assert_equal(np.percentile(range(100), 50, limit=(1, 8), + interpolation='linear'), 4.5) + assert_equal(np.percentile(np.array([1, 10, 100]), 50, (10, 100), + interpolation='linear'), 55) + assert_equal(np.percentile(np.array([1, 10, 100]), 50, (1, 10), + interpolation='linear'), 5.5) + + def test_lower_higher(self): + + # interpolation_method 'lower'/'higher' + assert_equal(np.percentile(range(10), 50, + interpolation='lower'), 4) + assert_equal(np.percentile(range(10), 50, + interpolation='higher'), 5) + assert_equal(np.percentile(range(10), 50, (2, 7), + interpolation='lower'), 4) + assert_equal(np.percentile(range(10), 50, limit=(2, 7), + interpolation='higher'), 5) + assert_equal(np.percentile(range(100), 50, (1, 8), + interpolation='lower'), 4) + assert_equal(np.percentile(range(100), 50, (1, 8), + interpolation='higher'), 5) + assert_equal(np.percentile(np.array([1, 10, 100]), 50, (10, 100), + interpolation='lower'), 10) + assert_equal(np.percentile(np.array([1, 10, 100]), 50, limit=(10, 100), + interpolation='higher'), 100) + assert_equal(np.percentile(np.array([1, 10, 100]), 50, (1, 10), + interpolation='lower'), 1) + assert_equal(np.percentile(np.array([1, 10, 100]), 50, limit=(1, 10), + interpolation='higher'), 10) + + def test_sequence(self): + x = np.arange(8) * 0.5 + assert_equal(np.percentile(x, [0, 100, 50]), [0, 3.5, 1.75]) + + def test_axis(self): + x = np.arange(12).reshape(3, 4) + + assert_equal(np.percentile(x, (25, 50, 100)), [2.75, 5.5, 11.0]) + + r0 = [[2, 3, 4, 5], [4, 5, 6, 7], [8, 9, 10, 11]] + assert_equal(np.percentile(x, (25, 50, 100), axis=0), r0) + + r1 = [[0.75, 1.5, 3], [4.75, 5.5, 7], [8.75, 9.5, 11]] + assert_equal(np.percentile(x, (25, 50, 100), axis=1), r1) + + def test_exception(self): + assert_raises(ValueError, np.percentile, [1, 2], 56, + interpolation='foobar') + assert_raises(ValueError, np.percentile, [1], 101) + assert_raises(ValueError, np.percentile, [1], -1) + + def test_percentile_list(self): + assert_equal(np.percentile([1, 2, 3], 0), 1) + + def test_percentile_out(self): + x = np.array([1, 2, 3]) + y = np.zeros((3,)) + p = (1, 2, 3) + np.percentile(x, p, out=y) + assert_equal(y, np.percentile(x, p)) + + 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)) + + y = np.zeros((2, 3)) + np.percentile(x, p, axis=1, out=y) + assert_equal(y, np.percentile(x, p, axis=1)) + + def test_percentile_no_overwrite(self): + a = np.array([2, 3, 4, 1]) + np.percentile(a, [50], overwrite_input=False) + assert_equal(a, np.array([2, 3, 4, 1])) class TestMedian(TestCase): -- cgit v1.2.1 From 4a084a0d77bbb7ade065e75d3602fd8b47369d76 Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Thu, 5 Sep 2013 11:20:56 -0500 Subject: MAINT: cleaning up percentile function. --- numpy/lib/tests/test_function_base.py | 49 +++++++---------------------------- 1 file changed, 10 insertions(+), 39 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 02597c78b..f0512420e 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1456,37 +1456,14 @@ class TestScoreatpercentile(TestCase): [1, 1, 1]]) assert_array_equal(np.percentile(x, 50, axis=0), [[1, 1, 1]]) - def test_limit(self): - x = np.arange(10) - assert_equal(np.percentile(x, 50, limit=(2, 5)), 3.5) - assert_equal(np.percentile([2, 3, 4, 5], 50), 3.5) - - assert_equal(np.percentile(x, 50, limit=(-1, 8)), 4) - assert_equal(np.percentile([0, 1, 2, 3, 4, 5, 6, 7, 8], 50), 4) - - assert_equal(np.percentile(x, 50, limit=(4, 11)), 6.5) - assert_equal(np.percentile([4, 5, 6, 7, 8, 9], 50, ), 6.5) - def test_linear(self): # Test defaults assert_equal(np.percentile(range(10), 50), 4.5) - assert_equal(np.percentile(range(10), 50, (2, 7)), 4.5) - assert_equal(np.percentile(range(100), 50, limit=(1, 8)), 4.5) - assert_equal(np.percentile(np.array([1, 10, 100]), 50, (10, 100)), 55) - assert_equal(np.percentile(np.array([1, 10, 100]), 50, (1, 10)), 5.5) # explicitly specify interpolation_method 'fraction' (the default) assert_equal(np.percentile(range(10), 50, interpolation='linear'), 4.5) - assert_equal(np.percentile(range(10), 50, limit=(2, 7), - interpolation='linear'), 4.5) - assert_equal(np.percentile(range(100), 50, limit=(1, 8), - interpolation='linear'), 4.5) - assert_equal(np.percentile(np.array([1, 10, 100]), 50, (10, 100), - interpolation='linear'), 55) - assert_equal(np.percentile(np.array([1, 10, 100]), 50, (1, 10), - interpolation='linear'), 5.5) def test_lower_higher(self): @@ -1495,22 +1472,16 @@ class TestScoreatpercentile(TestCase): interpolation='lower'), 4) assert_equal(np.percentile(range(10), 50, interpolation='higher'), 5) - assert_equal(np.percentile(range(10), 50, (2, 7), - interpolation='lower'), 4) - assert_equal(np.percentile(range(10), 50, limit=(2, 7), - interpolation='higher'), 5) - assert_equal(np.percentile(range(100), 50, (1, 8), - interpolation='lower'), 4) - assert_equal(np.percentile(range(100), 50, (1, 8), - interpolation='higher'), 5) - assert_equal(np.percentile(np.array([1, 10, 100]), 50, (10, 100), - interpolation='lower'), 10) - assert_equal(np.percentile(np.array([1, 10, 100]), 50, limit=(10, 100), - interpolation='higher'), 100) - assert_equal(np.percentile(np.array([1, 10, 100]), 50, (1, 10), - interpolation='lower'), 1) - assert_equal(np.percentile(np.array([1, 10, 100]), 50, limit=(1, 10), - interpolation='higher'), 10) + + def test_midpoint(self): + assert_equal(np.percentile(range(10), 51, + interpolation='midpoint'), 4.5) + + def test_closest(self): + assert_equal(np.percentile(range(10), 51, + interpolation='closest'), 5) + assert_equal(np.percentile(range(10), 49, + interpolation='closest'), 4) def test_sequence(self): x = np.arange(8) * 0.5 -- cgit v1.2.1 From 9aed31a8ba1607241947bfe886821e9eb09f6ebb Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Fri, 13 Sep 2013 17:00:27 -0500 Subject: TST: additional test for percentile --- numpy/lib/tests/test_function_base.py | 3 +++ 1 file changed, 3 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 f0512420e..6923f0004 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1530,6 +1530,9 @@ class TestScoreatpercentile(TestCase): np.percentile(a, [50], overwrite_input=False) assert_equal(a, np.array([2, 3, 4, 1])) + np.percentile(a, [50]) + assert_equal(a, np.array([2, 3, 4, 1])) + class TestMedian(TestCase): def test_basic(self): -- cgit v1.2.1 From 9dd212cee1c9ccab6013d52e776bcf6ef712a5e0 Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Mon, 16 Sep 2013 10:32:25 -0600 Subject: MAINT: changed 'closest' interpolation to 'nearest' --- numpy/lib/tests/test_function_base.py | 6 +++--- 1 file changed, 3 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 6923f0004..a69c82e18 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1477,11 +1477,11 @@ class TestScoreatpercentile(TestCase): assert_equal(np.percentile(range(10), 51, interpolation='midpoint'), 4.5) - def test_closest(self): + def test_nearest(self): assert_equal(np.percentile(range(10), 51, - interpolation='closest'), 5) + interpolation='nearest'), 5) assert_equal(np.percentile(range(10), 49, - interpolation='closest'), 4) + interpolation='nearest'), 4) def test_sequence(self): x = np.arange(8) * 0.5 -- cgit v1.2.1 From 9316110a42c370616cbb80ae3e1769534d04de10 Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Mon, 16 Sep 2013 10:44:26 -0600 Subject: TST: note on overwrite_input parameter in percentile * added note that `overwrite_input` has not effect when `a` is not an array in the percentile function. * added unit test to verify that no error is raised when `a` is not an array and `overwrite_input` is True. --- 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 a69c82e18..dd0b6e0ee 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -1530,9 +1530,19 @@ class TestScoreatpercentile(TestCase): np.percentile(a, [50], overwrite_input=False) assert_equal(a, np.array([2, 3, 4, 1])) + a = np.array([2, 3, 4, 1]) np.percentile(a, [50]) assert_equal(a, np.array([2, 3, 4, 1])) + def test_percentile_overwrite(self): + a = np.array([2, 3, 4, 1]) + b = np.percentile(a, [50], overwrite_input=True) + assert_equal(b, np.array([2.5])) + + b = np.percentile([2, 3, 4, 1], [50], overwrite_input=True) + assert_equal(b, np.array([2.5])) + + class TestMedian(TestCase): def test_basic(self): -- cgit v1.2.1