Skip to content

Commit

Permalink
MAINT: fix rdist methods in scipy.stats
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisb83 committed Sep 9, 2019
1 parent f2ae7b8 commit 8f2d3fb
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 15 deletions.
29 changes: 17 additions & 12 deletions scipy/stats/_continuous_distns.py
Original file line number Diff line number Diff line change
Expand Up @@ -5927,7 +5927,7 @@ def _ppf(self, q, c):


class rdist_gen(rv_continuous):
r"""An R-distributed continuous random variable.
r"""An R-distributed (symmetric beta) continuous random variable.
%(before_notes)s
Expand All @@ -5939,7 +5939,10 @@ class rdist_gen(rv_continuous):
f(x, c) = \frac{(1-x^2)^{c/2-1}}{B(1/2, c/2)}
for :math:`-1 \le x \le 1`, :math:`c > 0`.
for :math:`-1 \le x \le 1`, :math:`c > 0`. `rdist` is also called the
symmetric beta distribution: if B has a `beta` distribution with
parameters (c/2, c/2), then X = 2*B - 1 follows a R-distribution with
parameter c.
`rdist` takes ``c`` as a shape parameter for :math:`c`.
Expand All @@ -5956,19 +5959,21 @@ class rdist_gen(rv_continuous):
%(example)s
"""
# use relation to the beta distribution for pdf, cdf, etc
def _pdf(self, x, c):
# rdist.pdf(x, c) = (1-x**2)**(c/2-1) / B(1/2, c/2)
return np.power((1.0 - x**2), c / 2.0 - 1) / sc.beta(0.5, c / 2.0)
return 0.5*beta._pdf((x+1)/2, c/2, c/2)

def _logpdf(self, x, c):
return -np.log(2) + beta._logpdf((x+1)/2, c/2, c/2)

def _cdf(self, x, c):
term1 = x / sc.beta(0.5, c / 2.0)
res = 0.5 + term1 * sc.hyp2f1(0.5, 1 - c / 2.0, 1.5, x**2)
# There's an issue with hyp2f1, it returns nans near x = +-1, c > 100.
# Use the generic implementation in that case. See gh-1285 for
# background.
if np.any(np.isnan(res)):
return rv_continuous._cdf(self, x, c)
return res
return beta._cdf((x+1)/2, c/2, c/2)

def _ppf(self, q, c):
return 2*beta._ppf(q, c/2, c/2) - 1

def _rvs(self, c):
return 2 * self._random_state.beta(c/2, c/2, self._size) - 1

def _munp(self, n, c):
numerator = (1 - (n % 2)) * sc.beta((n + 1.0) / 2, c / 2.0)
Expand Down
4 changes: 2 additions & 2 deletions scipy/stats/tests/test_continuous_basic.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
]


distslow = ['kappa4', 'rdist', 'gausshyper', 'recipinvgauss', 'genexpon',
distslow = ['kappa4', 'gausshyper', 'recipinvgauss', 'genexpon',
'vonmises', 'vonmises_line', 'cosine', 'invweibull',
'powerlognorm', 'johnsonsu', 'kstwobign']
# distslow are sorted by speed (very slow to slow)
Expand All @@ -62,7 +62,7 @@
'gennorm', 'genpareto', 'halfgennorm', 'invgamma',
'ksone', 'kstwobign', 'levy_l', 'loggamma', 'logistic',
'maxwell', 'nakagami', 'ncf', 'nct', 'ncx2', 'norminvgauss',
'pearson3', 'rice', 't', 'skewnorm', 'tukeylambda',
'pearson3', 'rdist', 'rice', 'skewnorm', 't', 'tukeylambda',
'vonmises', 'vonmises_line', 'rv_histogram_instance'])

_h = np.histogram([1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6,
Expand Down
8 changes: 7 additions & 1 deletion scipy/stats/tests/test_distributions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2743,14 +2743,20 @@ def test_with_maxima_distrib(self):


class TestRdist(object):
@pytest.mark.slow
def test_rdist_cdf_gh1285(self):
# check workaround in rdist._cdf for issue gh-1285.
distfn = stats.rdist
values = [0.001, 0.5, 0.999]
assert_almost_equal(distfn.cdf(distfn.ppf(values, 541.0), 541.0),
values, decimal=5)

def test_rdist_beta(self):
# rdist is a special case of stats.beta
x = np.linspace(-0.99, 0.99, 10)
c = 2.7
assert_almost_equal(0.5*stats.beta(c/2, c/2).pdf((x+1)/2),
stats.rdist(c).pdf(x))


class TestTrapz(object):
def test_reduces_to_triang(self):
Expand Down

0 comments on commit 8f2d3fb

Please sign in to comment.