summaryrefslogtreecommitdiff
path: root/numpy/lib
diff options
context:
space:
mode:
authorEric Wieser <wieser.eric@gmail.com>2019-04-23 01:55:21 -0700
committerEric Wieser <wieser.eric@gmail.com>2019-04-23 22:48:02 -0700
commit9a23f16b67958205468f7f5c4e0966f393558d9a (patch)
tree9f42fe0fec010d33a0708a16f9d7af13c71b1c73 /numpy/lib
parentf91b033aa35b929610c0db12f16b1b0c1ddc08e6 (diff)
downloadnumpy-9a23f16b67958205468f7f5c4e0966f393558d9a.tar.gz
ENH: Add support for Fraction to percentile and quantile
With true division available, using `.0` to convert integers to floats offers no value, and harms compatibility with precise rational types.
Diffstat (limited to 'numpy/lib')
-rw-r--r--numpy/lib/function_base.py5
-rw-r--r--numpy/lib/tests/test_function_base.py36
2 files changed, 39 insertions, 2 deletions
diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py
index 2e82fa075..cab680751 100644
--- a/numpy/lib/function_base.py
+++ b/numpy/lib/function_base.py
@@ -3706,7 +3706,8 @@ def percentile(a, q, axis=None, out=None,
plt.show()
"""
- q = np.true_divide(q, 100.0) # handles the asarray for us too
+ q = np.true_divide(q, 100)
+ q = asanyarray(q) # undo any decay that the ufunc performed (see gh-13105)
if not _quantile_is_valid(q):
raise ValueError("Percentiles must be in the range [0, 100]")
return _quantile_unchecked(
@@ -3924,7 +3925,7 @@ def _quantile_ureduce_func(a, q, axis=None, out=None, overwrite_input=False,
indices_above = concatenate((indices_above, [-1]))
weights_above = indices - indices_below
- weights_below = 1.0 - weights_above
+ weights_below = 1 - weights_above
weights_shape = [1, ] * ap.ndim
weights_shape[axis] = len(indices)
diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py
index e2c24a123..6d32c365a 100644
--- a/numpy/lib/tests/test_function_base.py
+++ b/numpy/lib/tests/test_function_base.py
@@ -5,6 +5,7 @@ import warnings
import sys
import decimal
import types
+from fractions import Fraction
import pytest
import numpy as np
@@ -2508,6 +2509,21 @@ class TestPercentile(object):
assert_equal(np.percentile(x, 0), np.nan)
assert_equal(np.percentile(x, 0, interpolation='nearest'), np.nan)
+ def test_fraction(self):
+ x = [Fraction(i, 2) for i in np.arange(8)]
+
+ p = np.percentile(x, Fraction(0))
+ assert_equal(p, Fraction(0))
+ assert_equal(type(p), Fraction)
+
+ p = np.percentile(x, Fraction(100))
+ assert_equal(p, Fraction(7, 2))
+ assert_equal(type(p), Fraction)
+
+ p = np.percentile(x, Fraction(50))
+ assert_equal(p, Fraction(7, 4))
+ assert_equal(type(p), Fraction)
+
def test_api(self):
d = np.ones(5)
np.percentile(d, 5, None, None, False)
@@ -2912,6 +2928,26 @@ class TestQuantile(object):
assert_equal(np.quantile(x, 1), 3.5)
assert_equal(np.quantile(x, 0.5), 1.75)
+ def test_fraction(self):
+ # fractional input, integral quantile
+ x = [Fraction(i, 2) for i in np.arange(8)]
+
+ q = np.quantile(x, 0)
+ assert_equal(q, 0)
+ assert_equal(type(q), Fraction)
+
+ q = np.quantile(x, 1)
+ assert_equal(q, Fraction(7, 2))
+ assert_equal(type(q), Fraction)
+
+ q = np.quantile(x, Fraction(1, 2))
+ assert_equal(q, Fraction(7, 4))
+ assert_equal(type(q), Fraction)
+
+ # repeat with integral input but fractional quantile
+ x = np.arange(8)
+ assert_equal(np.quantile(x, Fraction(1, 2)), Fraction(7, 2))
+
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])