_distn_infrastructure.py 117 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446
  1. #
  2. # Author: Travis Oliphant 2002-2011 with contributions from
  3. # SciPy Developers 2004-2011
  4. #
  5. from __future__ import division, print_function, absolute_import
  6. from scipy._lib.six import string_types, exec_, PY3
  7. from scipy._lib._util import getargspec_no_self as _getargspec
  8. import sys
  9. import keyword
  10. import re
  11. import types
  12. import warnings
  13. from scipy.misc import doccer
  14. from ._distr_params import distcont, distdiscrete
  15. from scipy._lib._util import check_random_state
  16. from scipy._lib._util import _valarray as valarray
  17. from scipy.special import (comb, chndtr, entr, rel_entr, xlogy, ive)
  18. # for root finding for discrete distribution ppf, and max likelihood estimation
  19. from scipy import optimize
  20. # for functions of continuous distributions (e.g. moments, entropy, cdf)
  21. from scipy import integrate
  22. # to approximate the pdf of a continuous distribution given its cdf
  23. from scipy.misc import derivative
  24. from numpy import (arange, putmask, ravel, ones, shape, ndarray, zeros, floor,
  25. logical_and, log, sqrt, place, argmax, vectorize, asarray,
  26. nan, inf, isinf, NINF, empty)
  27. import numpy as np
  28. from ._constants import _XMAX
  29. if PY3:
  30. def instancemethod(func, obj, cls):
  31. return types.MethodType(func, obj)
  32. else:
  33. instancemethod = types.MethodType
  34. # These are the docstring parts used for substitution in specific
  35. # distribution docstrings
  36. docheaders = {'methods': """\nMethods\n-------\n""",
  37. 'notes': """\nNotes\n-----\n""",
  38. 'examples': """\nExamples\n--------\n"""}
  39. _doc_rvs = """\
  40. rvs(%(shapes)s, loc=0, scale=1, size=1, random_state=None)
  41. Random variates.
  42. """
  43. _doc_pdf = """\
  44. pdf(x, %(shapes)s, loc=0, scale=1)
  45. Probability density function.
  46. """
  47. _doc_logpdf = """\
  48. logpdf(x, %(shapes)s, loc=0, scale=1)
  49. Log of the probability density function.
  50. """
  51. _doc_pmf = """\
  52. pmf(k, %(shapes)s, loc=0, scale=1)
  53. Probability mass function.
  54. """
  55. _doc_logpmf = """\
  56. logpmf(k, %(shapes)s, loc=0, scale=1)
  57. Log of the probability mass function.
  58. """
  59. _doc_cdf = """\
  60. cdf(x, %(shapes)s, loc=0, scale=1)
  61. Cumulative distribution function.
  62. """
  63. _doc_logcdf = """\
  64. logcdf(x, %(shapes)s, loc=0, scale=1)
  65. Log of the cumulative distribution function.
  66. """
  67. _doc_sf = """\
  68. sf(x, %(shapes)s, loc=0, scale=1)
  69. Survival function (also defined as ``1 - cdf``, but `sf` is sometimes more accurate).
  70. """
  71. _doc_logsf = """\
  72. logsf(x, %(shapes)s, loc=0, scale=1)
  73. Log of the survival function.
  74. """
  75. _doc_ppf = """\
  76. ppf(q, %(shapes)s, loc=0, scale=1)
  77. Percent point function (inverse of ``cdf`` --- percentiles).
  78. """
  79. _doc_isf = """\
  80. isf(q, %(shapes)s, loc=0, scale=1)
  81. Inverse survival function (inverse of ``sf``).
  82. """
  83. _doc_moment = """\
  84. moment(n, %(shapes)s, loc=0, scale=1)
  85. Non-central moment of order n
  86. """
  87. _doc_stats = """\
  88. stats(%(shapes)s, loc=0, scale=1, moments='mv')
  89. Mean('m'), variance('v'), skew('s'), and/or kurtosis('k').
  90. """
  91. _doc_entropy = """\
  92. entropy(%(shapes)s, loc=0, scale=1)
  93. (Differential) entropy of the RV.
  94. """
  95. _doc_fit = """\
  96. fit(data, %(shapes)s, loc=0, scale=1)
  97. Parameter estimates for generic data.
  98. """
  99. _doc_expect = """\
  100. expect(func, args=(%(shapes_)s), loc=0, scale=1, lb=None, ub=None, conditional=False, **kwds)
  101. Expected value of a function (of one argument) with respect to the distribution.
  102. """
  103. _doc_expect_discrete = """\
  104. expect(func, args=(%(shapes_)s), loc=0, lb=None, ub=None, conditional=False)
  105. Expected value of a function (of one argument) with respect to the distribution.
  106. """
  107. _doc_median = """\
  108. median(%(shapes)s, loc=0, scale=1)
  109. Median of the distribution.
  110. """
  111. _doc_mean = """\
  112. mean(%(shapes)s, loc=0, scale=1)
  113. Mean of the distribution.
  114. """
  115. _doc_var = """\
  116. var(%(shapes)s, loc=0, scale=1)
  117. Variance of the distribution.
  118. """
  119. _doc_std = """\
  120. std(%(shapes)s, loc=0, scale=1)
  121. Standard deviation of the distribution.
  122. """
  123. _doc_interval = """\
  124. interval(alpha, %(shapes)s, loc=0, scale=1)
  125. Endpoints of the range that contains alpha percent of the distribution
  126. """
  127. _doc_allmethods = ''.join([docheaders['methods'], _doc_rvs, _doc_pdf,
  128. _doc_logpdf, _doc_cdf, _doc_logcdf, _doc_sf,
  129. _doc_logsf, _doc_ppf, _doc_isf, _doc_moment,
  130. _doc_stats, _doc_entropy, _doc_fit,
  131. _doc_expect, _doc_median,
  132. _doc_mean, _doc_var, _doc_std, _doc_interval])
  133. _doc_default_longsummary = """\
  134. As an instance of the `rv_continuous` class, `%(name)s` object inherits from it
  135. a collection of generic methods (see below for the full list),
  136. and completes them with details specific for this particular distribution.
  137. """
  138. _doc_default_frozen_note = """
  139. Alternatively, the object may be called (as a function) to fix the shape,
  140. location, and scale parameters returning a "frozen" continuous RV object:
  141. rv = %(name)s(%(shapes)s, loc=0, scale=1)
  142. - Frozen RV object with the same methods but holding the given shape,
  143. location, and scale fixed.
  144. """
  145. _doc_default_example = """\
  146. Examples
  147. --------
  148. >>> from scipy.stats import %(name)s
  149. >>> import matplotlib.pyplot as plt
  150. >>> fig, ax = plt.subplots(1, 1)
  151. Calculate a few first moments:
  152. %(set_vals_stmt)s
  153. >>> mean, var, skew, kurt = %(name)s.stats(%(shapes)s, moments='mvsk')
  154. Display the probability density function (``pdf``):
  155. >>> x = np.linspace(%(name)s.ppf(0.01, %(shapes)s),
  156. ... %(name)s.ppf(0.99, %(shapes)s), 100)
  157. >>> ax.plot(x, %(name)s.pdf(x, %(shapes)s),
  158. ... 'r-', lw=5, alpha=0.6, label='%(name)s pdf')
  159. Alternatively, the distribution object can be called (as a function)
  160. to fix the shape, location and scale parameters. This returns a "frozen"
  161. RV object holding the given parameters fixed.
  162. Freeze the distribution and display the frozen ``pdf``:
  163. >>> rv = %(name)s(%(shapes)s)
  164. >>> ax.plot(x, rv.pdf(x), 'k-', lw=2, label='frozen pdf')
  165. Check accuracy of ``cdf`` and ``ppf``:
  166. >>> vals = %(name)s.ppf([0.001, 0.5, 0.999], %(shapes)s)
  167. >>> np.allclose([0.001, 0.5, 0.999], %(name)s.cdf(vals, %(shapes)s))
  168. True
  169. Generate random numbers:
  170. >>> r = %(name)s.rvs(%(shapes)s, size=1000)
  171. And compare the histogram:
  172. >>> ax.hist(r, density=True, histtype='stepfilled', alpha=0.2)
  173. >>> ax.legend(loc='best', frameon=False)
  174. >>> plt.show()
  175. """
  176. _doc_default_locscale = """\
  177. The probability density above is defined in the "standardized" form. To shift
  178. and/or scale the distribution use the ``loc`` and ``scale`` parameters.
  179. Specifically, ``%(name)s.pdf(x, %(shapes)s, loc, scale)`` is identically
  180. equivalent to ``%(name)s.pdf(y, %(shapes)s) / scale`` with
  181. ``y = (x - loc) / scale``.
  182. """
  183. _doc_default = ''.join([_doc_default_longsummary,
  184. _doc_allmethods,
  185. '\n',
  186. _doc_default_example])
  187. _doc_default_before_notes = ''.join([_doc_default_longsummary,
  188. _doc_allmethods])
  189. docdict = {
  190. 'rvs': _doc_rvs,
  191. 'pdf': _doc_pdf,
  192. 'logpdf': _doc_logpdf,
  193. 'cdf': _doc_cdf,
  194. 'logcdf': _doc_logcdf,
  195. 'sf': _doc_sf,
  196. 'logsf': _doc_logsf,
  197. 'ppf': _doc_ppf,
  198. 'isf': _doc_isf,
  199. 'stats': _doc_stats,
  200. 'entropy': _doc_entropy,
  201. 'fit': _doc_fit,
  202. 'moment': _doc_moment,
  203. 'expect': _doc_expect,
  204. 'interval': _doc_interval,
  205. 'mean': _doc_mean,
  206. 'std': _doc_std,
  207. 'var': _doc_var,
  208. 'median': _doc_median,
  209. 'allmethods': _doc_allmethods,
  210. 'longsummary': _doc_default_longsummary,
  211. 'frozennote': _doc_default_frozen_note,
  212. 'example': _doc_default_example,
  213. 'default': _doc_default,
  214. 'before_notes': _doc_default_before_notes,
  215. 'after_notes': _doc_default_locscale
  216. }
  217. # Reuse common content between continuous and discrete docs, change some
  218. # minor bits.
  219. docdict_discrete = docdict.copy()
  220. docdict_discrete['pmf'] = _doc_pmf
  221. docdict_discrete['logpmf'] = _doc_logpmf
  222. docdict_discrete['expect'] = _doc_expect_discrete
  223. _doc_disc_methods = ['rvs', 'pmf', 'logpmf', 'cdf', 'logcdf', 'sf', 'logsf',
  224. 'ppf', 'isf', 'stats', 'entropy', 'expect', 'median',
  225. 'mean', 'var', 'std', 'interval']
  226. for obj in _doc_disc_methods:
  227. docdict_discrete[obj] = docdict_discrete[obj].replace(', scale=1', '')
  228. _doc_disc_methods_err_varname = ['cdf', 'logcdf', 'sf', 'logsf']
  229. for obj in _doc_disc_methods_err_varname:
  230. docdict_discrete[obj] = docdict_discrete[obj].replace('(x, ', '(k, ')
  231. docdict_discrete.pop('pdf')
  232. docdict_discrete.pop('logpdf')
  233. _doc_allmethods = ''.join([docdict_discrete[obj] for obj in _doc_disc_methods])
  234. docdict_discrete['allmethods'] = docheaders['methods'] + _doc_allmethods
  235. docdict_discrete['longsummary'] = _doc_default_longsummary.replace(
  236. 'rv_continuous', 'rv_discrete')
  237. _doc_default_frozen_note = """
  238. Alternatively, the object may be called (as a function) to fix the shape and
  239. location parameters returning a "frozen" discrete RV object:
  240. rv = %(name)s(%(shapes)s, loc=0)
  241. - Frozen RV object with the same methods but holding the given shape and
  242. location fixed.
  243. """
  244. docdict_discrete['frozennote'] = _doc_default_frozen_note
  245. _doc_default_discrete_example = """\
  246. Examples
  247. --------
  248. >>> from scipy.stats import %(name)s
  249. >>> import matplotlib.pyplot as plt
  250. >>> fig, ax = plt.subplots(1, 1)
  251. Calculate a few first moments:
  252. %(set_vals_stmt)s
  253. >>> mean, var, skew, kurt = %(name)s.stats(%(shapes)s, moments='mvsk')
  254. Display the probability mass function (``pmf``):
  255. >>> x = np.arange(%(name)s.ppf(0.01, %(shapes)s),
  256. ... %(name)s.ppf(0.99, %(shapes)s))
  257. >>> ax.plot(x, %(name)s.pmf(x, %(shapes)s), 'bo', ms=8, label='%(name)s pmf')
  258. >>> ax.vlines(x, 0, %(name)s.pmf(x, %(shapes)s), colors='b', lw=5, alpha=0.5)
  259. Alternatively, the distribution object can be called (as a function)
  260. to fix the shape and location. This returns a "frozen" RV object holding
  261. the given parameters fixed.
  262. Freeze the distribution and display the frozen ``pmf``:
  263. >>> rv = %(name)s(%(shapes)s)
  264. >>> ax.vlines(x, 0, rv.pmf(x), colors='k', linestyles='-', lw=1,
  265. ... label='frozen pmf')
  266. >>> ax.legend(loc='best', frameon=False)
  267. >>> plt.show()
  268. Check accuracy of ``cdf`` and ``ppf``:
  269. >>> prob = %(name)s.cdf(x, %(shapes)s)
  270. >>> np.allclose(x, %(name)s.ppf(prob, %(shapes)s))
  271. True
  272. Generate random numbers:
  273. >>> r = %(name)s.rvs(%(shapes)s, size=1000)
  274. """
  275. _doc_default_discrete_locscale = """\
  276. The probability mass function above is defined in the "standardized" form.
  277. To shift distribution use the ``loc`` parameter.
  278. Specifically, ``%(name)s.pmf(k, %(shapes)s, loc)`` is identically
  279. equivalent to ``%(name)s.pmf(k - loc, %(shapes)s)``.
  280. """
  281. docdict_discrete['example'] = _doc_default_discrete_example
  282. docdict_discrete['after_notes'] = _doc_default_discrete_locscale
  283. _doc_default_before_notes = ''.join([docdict_discrete['longsummary'],
  284. docdict_discrete['allmethods']])
  285. docdict_discrete['before_notes'] = _doc_default_before_notes
  286. _doc_default_disc = ''.join([docdict_discrete['longsummary'],
  287. docdict_discrete['allmethods'],
  288. docdict_discrete['frozennote'],
  289. docdict_discrete['example']])
  290. docdict_discrete['default'] = _doc_default_disc
  291. # clean up all the separate docstring elements, we do not need them anymore
  292. for obj in [s for s in dir() if s.startswith('_doc_')]:
  293. exec('del ' + obj)
  294. del obj
  295. try:
  296. del s
  297. except NameError:
  298. # in Python 3, loop variables are not visible after the loop
  299. pass
  300. def _moment(data, n, mu=None):
  301. if mu is None:
  302. mu = data.mean()
  303. return ((data - mu)**n).mean()
  304. def _moment_from_stats(n, mu, mu2, g1, g2, moment_func, args):
  305. if (n == 0):
  306. return 1.0
  307. elif (n == 1):
  308. if mu is None:
  309. val = moment_func(1, *args)
  310. else:
  311. val = mu
  312. elif (n == 2):
  313. if mu2 is None or mu is None:
  314. val = moment_func(2, *args)
  315. else:
  316. val = mu2 + mu*mu
  317. elif (n == 3):
  318. if g1 is None or mu2 is None or mu is None:
  319. val = moment_func(3, *args)
  320. else:
  321. mu3 = g1 * np.power(mu2, 1.5) # 3rd central moment
  322. val = mu3+3*mu*mu2+mu*mu*mu # 3rd non-central moment
  323. elif (n == 4):
  324. if g1 is None or g2 is None or mu2 is None or mu is None:
  325. val = moment_func(4, *args)
  326. else:
  327. mu4 = (g2+3.0)*(mu2**2.0) # 4th central moment
  328. mu3 = g1*np.power(mu2, 1.5) # 3rd central moment
  329. val = mu4+4*mu*mu3+6*mu*mu*mu2+mu*mu*mu*mu
  330. else:
  331. val = moment_func(n, *args)
  332. return val
  333. def _skew(data):
  334. """
  335. skew is third central moment / variance**(1.5)
  336. """
  337. data = np.ravel(data)
  338. mu = data.mean()
  339. m2 = ((data - mu)**2).mean()
  340. m3 = ((data - mu)**3).mean()
  341. return m3 / np.power(m2, 1.5)
  342. def _kurtosis(data):
  343. """
  344. kurtosis is fourth central moment / variance**2 - 3
  345. """
  346. data = np.ravel(data)
  347. mu = data.mean()
  348. m2 = ((data - mu)**2).mean()
  349. m4 = ((data - mu)**4).mean()
  350. return m4 / m2**2 - 3
  351. # Frozen RV class
  352. class rv_frozen(object):
  353. def __init__(self, dist, *args, **kwds):
  354. self.args = args
  355. self.kwds = kwds
  356. # create a new instance
  357. self.dist = dist.__class__(**dist._updated_ctor_param())
  358. # a, b may be set in _argcheck, depending on *args, **kwds. Ouch.
  359. shapes, _, _ = self.dist._parse_args(*args, **kwds)
  360. self.dist._argcheck(*shapes)
  361. self.a, self.b = self.dist.a, self.dist.b
  362. @property
  363. def random_state(self):
  364. return self.dist._random_state
  365. @random_state.setter
  366. def random_state(self, seed):
  367. self.dist._random_state = check_random_state(seed)
  368. def pdf(self, x): # raises AttributeError in frozen discrete distribution
  369. return self.dist.pdf(x, *self.args, **self.kwds)
  370. def logpdf(self, x):
  371. return self.dist.logpdf(x, *self.args, **self.kwds)
  372. def cdf(self, x):
  373. return self.dist.cdf(x, *self.args, **self.kwds)
  374. def logcdf(self, x):
  375. return self.dist.logcdf(x, *self.args, **self.kwds)
  376. def ppf(self, q):
  377. return self.dist.ppf(q, *self.args, **self.kwds)
  378. def isf(self, q):
  379. return self.dist.isf(q, *self.args, **self.kwds)
  380. def rvs(self, size=None, random_state=None):
  381. kwds = self.kwds.copy()
  382. kwds.update({'size': size, 'random_state': random_state})
  383. return self.dist.rvs(*self.args, **kwds)
  384. def sf(self, x):
  385. return self.dist.sf(x, *self.args, **self.kwds)
  386. def logsf(self, x):
  387. return self.dist.logsf(x, *self.args, **self.kwds)
  388. def stats(self, moments='mv'):
  389. kwds = self.kwds.copy()
  390. kwds.update({'moments': moments})
  391. return self.dist.stats(*self.args, **kwds)
  392. def median(self):
  393. return self.dist.median(*self.args, **self.kwds)
  394. def mean(self):
  395. return self.dist.mean(*self.args, **self.kwds)
  396. def var(self):
  397. return self.dist.var(*self.args, **self.kwds)
  398. def std(self):
  399. return self.dist.std(*self.args, **self.kwds)
  400. def moment(self, n):
  401. return self.dist.moment(n, *self.args, **self.kwds)
  402. def entropy(self):
  403. return self.dist.entropy(*self.args, **self.kwds)
  404. def pmf(self, k):
  405. return self.dist.pmf(k, *self.args, **self.kwds)
  406. def logpmf(self, k):
  407. return self.dist.logpmf(k, *self.args, **self.kwds)
  408. def interval(self, alpha):
  409. return self.dist.interval(alpha, *self.args, **self.kwds)
  410. def expect(self, func=None, lb=None, ub=None, conditional=False, **kwds):
  411. # expect method only accepts shape parameters as positional args
  412. # hence convert self.args, self.kwds, also loc/scale
  413. # See the .expect method docstrings for the meaning of
  414. # other parameters.
  415. a, loc, scale = self.dist._parse_args(*self.args, **self.kwds)
  416. if isinstance(self.dist, rv_discrete):
  417. return self.dist.expect(func, a, loc, lb, ub, conditional, **kwds)
  418. else:
  419. return self.dist.expect(func, a, loc, scale, lb, ub,
  420. conditional, **kwds)
  421. # This should be rewritten
  422. def argsreduce(cond, *args):
  423. """Return the sequence of ravel(args[i]) where ravel(condition) is
  424. True in 1D.
  425. Examples
  426. --------
  427. >>> import numpy as np
  428. >>> rand = np.random.random_sample
  429. >>> A = rand((4, 5))
  430. >>> B = 2
  431. >>> C = rand((1, 5))
  432. >>> cond = np.ones(A.shape)
  433. >>> [A1, B1, C1] = argsreduce(cond, A, B, C)
  434. >>> B1.shape
  435. (20,)
  436. >>> cond[2,:] = 0
  437. >>> [A2, B2, C2] = argsreduce(cond, A, B, C)
  438. >>> B2.shape
  439. (15,)
  440. """
  441. newargs = np.atleast_1d(*args)
  442. if not isinstance(newargs, list):
  443. newargs = [newargs, ]
  444. expand_arr = (cond == cond)
  445. return [np.extract(cond, arr1 * expand_arr) for arr1 in newargs]
  446. parse_arg_template = """
  447. def _parse_args(self, %(shape_arg_str)s %(locscale_in)s):
  448. return (%(shape_arg_str)s), %(locscale_out)s
  449. def _parse_args_rvs(self, %(shape_arg_str)s %(locscale_in)s, size=None):
  450. return self._argcheck_rvs(%(shape_arg_str)s %(locscale_out)s, size=size)
  451. def _parse_args_stats(self, %(shape_arg_str)s %(locscale_in)s, moments='mv'):
  452. return (%(shape_arg_str)s), %(locscale_out)s, moments
  453. """
  454. # Both the continuous and discrete distributions depend on ncx2.
  455. # The function name ncx2 is an abbreviation for noncentral chi squared.
  456. def _ncx2_log_pdf(x, df, nc):
  457. # We use (xs**2 + ns**2)/2 = (xs - ns)**2/2 + xs*ns, and include the
  458. # factor of exp(-xs*ns) into the ive function to improve numerical
  459. # stability at large values of xs. See also `rice.pdf`.
  460. df2 = df/2.0 - 1.0
  461. xs, ns = np.sqrt(x), np.sqrt(nc)
  462. res = xlogy(df2/2.0, x/nc) - 0.5*(xs - ns)**2
  463. res += np.log(ive(df2, xs*ns) / 2.0)
  464. return res
  465. def _ncx2_pdf(x, df, nc):
  466. return np.exp(_ncx2_log_pdf(x, df, nc))
  467. def _ncx2_cdf(x, df, nc):
  468. return chndtr(x, df, nc)
  469. class rv_generic(object):
  470. """Class which encapsulates common functionality between rv_discrete
  471. and rv_continuous.
  472. """
  473. def __init__(self, seed=None):
  474. super(rv_generic, self).__init__()
  475. # figure out if _stats signature has 'moments' keyword
  476. sign = _getargspec(self._stats)
  477. self._stats_has_moments = ((sign[2] is not None) or
  478. ('moments' in sign[0]))
  479. self._random_state = check_random_state(seed)
  480. @property
  481. def random_state(self):
  482. """ Get or set the RandomState object for generating random variates.
  483. This can be either None or an existing RandomState object.
  484. If None (or np.random), use the RandomState singleton used by np.random.
  485. If already a RandomState instance, use it.
  486. If an int, use a new RandomState instance seeded with seed.
  487. """
  488. return self._random_state
  489. @random_state.setter
  490. def random_state(self, seed):
  491. self._random_state = check_random_state(seed)
  492. def __getstate__(self):
  493. return self._updated_ctor_param(), self._random_state
  494. def __setstate__(self, state):
  495. ctor_param, r = state
  496. self.__init__(**ctor_param)
  497. self._random_state = r
  498. return self
  499. def _construct_argparser(
  500. self, meths_to_inspect, locscale_in, locscale_out):
  501. """Construct the parser for the shape arguments.
  502. Generates the argument-parsing functions dynamically and attaches
  503. them to the instance.
  504. Is supposed to be called in __init__ of a class for each distribution.
  505. If self.shapes is a non-empty string, interprets it as a
  506. comma-separated list of shape parameters.
  507. Otherwise inspects the call signatures of `meths_to_inspect`
  508. and constructs the argument-parsing functions from these.
  509. In this case also sets `shapes` and `numargs`.
  510. """
  511. if self.shapes:
  512. # sanitize the user-supplied shapes
  513. if not isinstance(self.shapes, string_types):
  514. raise TypeError('shapes must be a string.')
  515. shapes = self.shapes.replace(',', ' ').split()
  516. for field in shapes:
  517. if keyword.iskeyword(field):
  518. raise SyntaxError('keywords cannot be used as shapes.')
  519. if not re.match('^[_a-zA-Z][_a-zA-Z0-9]*$', field):
  520. raise SyntaxError(
  521. 'shapes must be valid python identifiers')
  522. else:
  523. # find out the call signatures (_pdf, _cdf etc), deduce shape
  524. # arguments. Generic methods only have 'self, x', any further args
  525. # are shapes.
  526. shapes_list = []
  527. for meth in meths_to_inspect:
  528. shapes_args = _getargspec(meth) # NB: does not contain self
  529. args = shapes_args.args[1:] # peel off 'x', too
  530. if args:
  531. shapes_list.append(args)
  532. # *args or **kwargs are not allowed w/automatic shapes
  533. if shapes_args.varargs is not None:
  534. raise TypeError(
  535. '*args are not allowed w/out explicit shapes')
  536. if shapes_args.keywords is not None:
  537. raise TypeError(
  538. '**kwds are not allowed w/out explicit shapes')
  539. if shapes_args.defaults is not None:
  540. raise TypeError('defaults are not allowed for shapes')
  541. if shapes_list:
  542. shapes = shapes_list[0]
  543. # make sure the signatures are consistent
  544. for item in shapes_list:
  545. if item != shapes:
  546. raise TypeError('Shape arguments are inconsistent.')
  547. else:
  548. shapes = []
  549. # have the arguments, construct the method from template
  550. shapes_str = ', '.join(shapes) + ', ' if shapes else '' # NB: not None
  551. dct = dict(shape_arg_str=shapes_str,
  552. locscale_in=locscale_in,
  553. locscale_out=locscale_out,
  554. )
  555. ns = {}
  556. exec_(parse_arg_template % dct, ns)
  557. # NB: attach to the instance, not class
  558. for name in ['_parse_args', '_parse_args_stats', '_parse_args_rvs']:
  559. setattr(self, name,
  560. instancemethod(ns[name], self, self.__class__)
  561. )
  562. self.shapes = ', '.join(shapes) if shapes else None
  563. if not hasattr(self, 'numargs'):
  564. # allows more general subclassing with *args
  565. self.numargs = len(shapes)
  566. def _construct_doc(self, docdict, shapes_vals=None):
  567. """Construct the instance docstring with string substitutions."""
  568. tempdict = docdict.copy()
  569. tempdict['name'] = self.name or 'distname'
  570. tempdict['shapes'] = self.shapes or ''
  571. if shapes_vals is None:
  572. shapes_vals = ()
  573. vals = ', '.join('%.3g' % val for val in shapes_vals)
  574. tempdict['vals'] = vals
  575. tempdict['shapes_'] = self.shapes or ''
  576. if self.shapes and self.numargs == 1:
  577. tempdict['shapes_'] += ','
  578. if self.shapes:
  579. tempdict['set_vals_stmt'] = '>>> %s = %s' % (self.shapes, vals)
  580. else:
  581. tempdict['set_vals_stmt'] = ''
  582. if self.shapes is None:
  583. # remove shapes from call parameters if there are none
  584. for item in ['default', 'before_notes']:
  585. tempdict[item] = tempdict[item].replace(
  586. "\n%(shapes)s : array_like\n shape parameters", "")
  587. for i in range(2):
  588. if self.shapes is None:
  589. # necessary because we use %(shapes)s in two forms (w w/o ", ")
  590. self.__doc__ = self.__doc__.replace("%(shapes)s, ", "")
  591. self.__doc__ = doccer.docformat(self.__doc__, tempdict)
  592. # correct for empty shapes
  593. self.__doc__ = self.__doc__.replace('(, ', '(').replace(', )', ')')
  594. def _construct_default_doc(self, longname=None, extradoc=None,
  595. docdict=None, discrete='continuous'):
  596. """Construct instance docstring from the default template."""
  597. if longname is None:
  598. longname = 'A'
  599. if extradoc is None:
  600. extradoc = ''
  601. if extradoc.startswith('\n\n'):
  602. extradoc = extradoc[2:]
  603. self.__doc__ = ''.join(['%s %s random variable.' % (longname, discrete),
  604. '\n\n%(before_notes)s\n', docheaders['notes'],
  605. extradoc, '\n%(example)s'])
  606. self._construct_doc(docdict)
  607. def freeze(self, *args, **kwds):
  608. """Freeze the distribution for the given arguments.
  609. Parameters
  610. ----------
  611. arg1, arg2, arg3,... : array_like
  612. The shape parameter(s) for the distribution. Should include all
  613. the non-optional arguments, may include ``loc`` and ``scale``.
  614. Returns
  615. -------
  616. rv_frozen : rv_frozen instance
  617. The frozen distribution.
  618. """
  619. return rv_frozen(self, *args, **kwds)
  620. def __call__(self, *args, **kwds):
  621. return self.freeze(*args, **kwds)
  622. __call__.__doc__ = freeze.__doc__
  623. # The actual calculation functions (no basic checking need be done)
  624. # If these are defined, the others won't be looked at.
  625. # Otherwise, the other set can be defined.
  626. def _stats(self, *args, **kwds):
  627. return None, None, None, None
  628. # Central moments
  629. def _munp(self, n, *args):
  630. # Silence floating point warnings from integration.
  631. olderr = np.seterr(all='ignore')
  632. vals = self.generic_moment(n, *args)
  633. np.seterr(**olderr)
  634. return vals
  635. def _argcheck_rvs(self, *args, **kwargs):
  636. # Handle broadcasting and size validation of the rvs method.
  637. # Subclasses should not have to override this method.
  638. # The rule is that if `size` is not None, then `size` gives the
  639. # shape of the result (integer values of `size` are treated as
  640. # tuples with length 1; i.e. `size=3` is the same as `size=(3,)`.)
  641. #
  642. # `args` is expected to contain the shape parameters (if any), the
  643. # location and the scale in a flat tuple (e.g. if there are two
  644. # shape parameters `a` and `b`, `args` will be `(a, b, loc, scale)`).
  645. # The only keyword argument expected is 'size'.
  646. size = kwargs.get('size', None)
  647. all_bcast = np.broadcast_arrays(*args)
  648. def squeeze_left(a):
  649. while a.ndim > 0 and a.shape[0] == 1:
  650. a = a[0]
  651. return a
  652. # Eliminate trivial leading dimensions. In the convention
  653. # used by numpy's random variate generators, trivial leading
  654. # dimensions are effectively ignored. In other words, when `size`
  655. # is given, trivial leading dimensions of the broadcast parameters
  656. # in excess of the number of dimensions in size are ignored, e.g.
  657. # >>> np.random.normal([[1, 3, 5]], [[[[0.01]]]], size=3)
  658. # array([ 1.00104267, 3.00422496, 4.99799278])
  659. # If `size` is not given, the exact broadcast shape is preserved:
  660. # >>> np.random.normal([[1, 3, 5]], [[[[0.01]]]])
  661. # array([[[[ 1.00862899, 3.00061431, 4.99867122]]]])
  662. #
  663. all_bcast = [squeeze_left(a) for a in all_bcast]
  664. bcast_shape = all_bcast[0].shape
  665. bcast_ndim = all_bcast[0].ndim
  666. if size is None:
  667. size_ = bcast_shape
  668. else:
  669. size_ = tuple(np.atleast_1d(size))
  670. # Check compatibility of size_ with the broadcast shape of all
  671. # the parameters. This check is intended to be consistent with
  672. # how the numpy random variate generators (e.g. np.random.normal,
  673. # np.random.beta) handle their arguments. The rule is that, if size
  674. # is given, it determines the shape of the output. Broadcasting
  675. # can't change the output size.
  676. # This is the standard broadcasting convention of extending the
  677. # shape with fewer dimensions with enough dimensions of length 1
  678. # so that the two shapes have the same number of dimensions.
  679. ndiff = bcast_ndim - len(size_)
  680. if ndiff < 0:
  681. bcast_shape = (1,)*(-ndiff) + bcast_shape
  682. elif ndiff > 0:
  683. size_ = (1,)*ndiff + size_
  684. # This compatibility test is not standard. In "regular" broadcasting,
  685. # two shapes are compatible if for each dimension, the lengths are the
  686. # same or one of the lengths is 1. Here, the length of a dimension in
  687. # size_ must not be less than the corresponding length in bcast_shape.
  688. ok = all([bcdim == 1 or bcdim == szdim
  689. for (bcdim, szdim) in zip(bcast_shape, size_)])
  690. if not ok:
  691. raise ValueError("size does not match the broadcast shape of "
  692. "the parameters.")
  693. param_bcast = all_bcast[:-2]
  694. loc_bcast = all_bcast[-2]
  695. scale_bcast = all_bcast[-1]
  696. return param_bcast, loc_bcast, scale_bcast, size_
  697. ## These are the methods you must define (standard form functions)
  698. ## NB: generic _pdf, _logpdf, _cdf are different for
  699. ## rv_continuous and rv_discrete hence are defined in there
  700. def _argcheck(self, *args):
  701. """Default check for correct values on args and keywords.
  702. Returns condition array of 1's where arguments are correct and
  703. 0's where they are not.
  704. """
  705. cond = 1
  706. for arg in args:
  707. cond = logical_and(cond, (asarray(arg) > 0))
  708. return cond
  709. def _support_mask(self, x):
  710. return (self.a <= x) & (x <= self.b)
  711. def _open_support_mask(self, x):
  712. return (self.a < x) & (x < self.b)
  713. def _rvs(self, *args):
  714. # This method must handle self._size being a tuple, and it must
  715. # properly broadcast *args and self._size. self._size might be
  716. # an empty tuple, which means a scalar random variate is to be
  717. # generated.
  718. ## Use basic inverse cdf algorithm for RV generation as default.
  719. U = self._random_state.random_sample(self._size)
  720. Y = self._ppf(U, *args)
  721. return Y
  722. def _logcdf(self, x, *args):
  723. return log(self._cdf(x, *args))
  724. def _sf(self, x, *args):
  725. return 1.0-self._cdf(x, *args)
  726. def _logsf(self, x, *args):
  727. return log(self._sf(x, *args))
  728. def _ppf(self, q, *args):
  729. return self._ppfvec(q, *args)
  730. def _isf(self, q, *args):
  731. return self._ppf(1.0-q, *args) # use correct _ppf for subclasses
  732. # These are actually called, and should not be overwritten if you
  733. # want to keep error checking.
  734. def rvs(self, *args, **kwds):
  735. """
  736. Random variates of given type.
  737. Parameters
  738. ----------
  739. arg1, arg2, arg3,... : array_like
  740. The shape parameter(s) for the distribution (see docstring of the
  741. instance object for more information).
  742. loc : array_like, optional
  743. Location parameter (default=0).
  744. scale : array_like, optional
  745. Scale parameter (default=1).
  746. size : int or tuple of ints, optional
  747. Defining number of random variates (default is 1).
  748. random_state : None or int or ``np.random.RandomState`` instance, optional
  749. If int or RandomState, use it for drawing the random variates.
  750. If None, rely on ``self.random_state``.
  751. Default is None.
  752. Returns
  753. -------
  754. rvs : ndarray or scalar
  755. Random variates of given `size`.
  756. """
  757. discrete = kwds.pop('discrete', None)
  758. rndm = kwds.pop('random_state', None)
  759. args, loc, scale, size = self._parse_args_rvs(*args, **kwds)
  760. cond = logical_and(self._argcheck(*args), (scale >= 0))
  761. if not np.all(cond):
  762. raise ValueError("Domain error in arguments.")
  763. if np.all(scale == 0):
  764. return loc*ones(size, 'd')
  765. # extra gymnastics needed for a custom random_state
  766. if rndm is not None:
  767. random_state_saved = self._random_state
  768. self._random_state = check_random_state(rndm)
  769. # `size` should just be an argument to _rvs(), but for, um,
  770. # historical reasons, it is made an attribute that is read
  771. # by _rvs().
  772. self._size = size
  773. vals = self._rvs(*args)
  774. vals = vals * scale + loc
  775. # do not forget to restore the _random_state
  776. if rndm is not None:
  777. self._random_state = random_state_saved
  778. # Cast to int if discrete
  779. if discrete:
  780. if size == ():
  781. vals = int(vals)
  782. else:
  783. vals = vals.astype(int)
  784. return vals
  785. def stats(self, *args, **kwds):
  786. """
  787. Some statistics of the given RV.
  788. Parameters
  789. ----------
  790. arg1, arg2, arg3,... : array_like
  791. The shape parameter(s) for the distribution (see docstring of the
  792. instance object for more information)
  793. loc : array_like, optional
  794. location parameter (default=0)
  795. scale : array_like, optional (continuous RVs only)
  796. scale parameter (default=1)
  797. moments : str, optional
  798. composed of letters ['mvsk'] defining which moments to compute:
  799. 'm' = mean,
  800. 'v' = variance,
  801. 's' = (Fisher's) skew,
  802. 'k' = (Fisher's) kurtosis.
  803. (default is 'mv')
  804. Returns
  805. -------
  806. stats : sequence
  807. of requested moments.
  808. """
  809. args, loc, scale, moments = self._parse_args_stats(*args, **kwds)
  810. # scale = 1 by construction for discrete RVs
  811. loc, scale = map(asarray, (loc, scale))
  812. args = tuple(map(asarray, args))
  813. cond = self._argcheck(*args) & (scale > 0) & (loc == loc)
  814. output = []
  815. default = valarray(shape(cond), self.badvalue)
  816. # Use only entries that are valid in calculation
  817. if np.any(cond):
  818. goodargs = argsreduce(cond, *(args+(scale, loc)))
  819. scale, loc, goodargs = goodargs[-2], goodargs[-1], goodargs[:-2]
  820. if self._stats_has_moments:
  821. mu, mu2, g1, g2 = self._stats(*goodargs,
  822. **{'moments': moments})
  823. else:
  824. mu, mu2, g1, g2 = self._stats(*goodargs)
  825. if g1 is None:
  826. mu3 = None
  827. else:
  828. if mu2 is None:
  829. mu2 = self._munp(2, *goodargs)
  830. if g2 is None:
  831. # (mu2**1.5) breaks down for nan and inf
  832. mu3 = g1 * np.power(mu2, 1.5)
  833. if 'm' in moments:
  834. if mu is None:
  835. mu = self._munp(1, *goodargs)
  836. out0 = default.copy()
  837. place(out0, cond, mu * scale + loc)
  838. output.append(out0)
  839. if 'v' in moments:
  840. if mu2 is None:
  841. mu2p = self._munp(2, *goodargs)
  842. if mu is None:
  843. mu = self._munp(1, *goodargs)
  844. mu2 = mu2p - mu * mu
  845. if np.isinf(mu):
  846. # if mean is inf then var is also inf
  847. mu2 = np.inf
  848. out0 = default.copy()
  849. place(out0, cond, mu2 * scale * scale)
  850. output.append(out0)
  851. if 's' in moments:
  852. if g1 is None:
  853. mu3p = self._munp(3, *goodargs)
  854. if mu is None:
  855. mu = self._munp(1, *goodargs)
  856. if mu2 is None:
  857. mu2p = self._munp(2, *goodargs)
  858. mu2 = mu2p - mu * mu
  859. with np.errstate(invalid='ignore'):
  860. mu3 = mu3p - 3 * mu * mu2 - mu**3
  861. g1 = mu3 / np.power(mu2, 1.5)
  862. out0 = default.copy()
  863. place(out0, cond, g1)
  864. output.append(out0)
  865. if 'k' in moments:
  866. if g2 is None:
  867. mu4p = self._munp(4, *goodargs)
  868. if mu is None:
  869. mu = self._munp(1, *goodargs)
  870. if mu2 is None:
  871. mu2p = self._munp(2, *goodargs)
  872. mu2 = mu2p - mu * mu
  873. if mu3 is None:
  874. mu3p = self._munp(3, *goodargs)
  875. with np.errstate(invalid='ignore'):
  876. mu3 = mu3p - 3 * mu * mu2 - mu**3
  877. with np.errstate(invalid='ignore'):
  878. mu4 = mu4p - 4 * mu * mu3 - 6 * mu * mu * mu2 - mu**4
  879. g2 = mu4 / mu2**2.0 - 3.0
  880. out0 = default.copy()
  881. place(out0, cond, g2)
  882. output.append(out0)
  883. else: # no valid args
  884. output = []
  885. for _ in moments:
  886. out0 = default.copy()
  887. output.append(out0)
  888. if len(output) == 1:
  889. return output[0]
  890. else:
  891. return tuple(output)
  892. def entropy(self, *args, **kwds):
  893. """
  894. Differential entropy of the RV.
  895. Parameters
  896. ----------
  897. arg1, arg2, arg3,... : array_like
  898. The shape parameter(s) for the distribution (see docstring of the
  899. instance object for more information).
  900. loc : array_like, optional
  901. Location parameter (default=0).
  902. scale : array_like, optional (continuous distributions only).
  903. Scale parameter (default=1).
  904. Notes
  905. -----
  906. Entropy is defined base `e`:
  907. >>> drv = rv_discrete(values=((0, 1), (0.5, 0.5)))
  908. >>> np.allclose(drv.entropy(), np.log(2.0))
  909. True
  910. """
  911. args, loc, scale = self._parse_args(*args, **kwds)
  912. # NB: for discrete distributions scale=1 by construction in _parse_args
  913. loc, scale = map(asarray, (loc, scale))
  914. args = tuple(map(asarray, args))
  915. cond0 = self._argcheck(*args) & (scale > 0) & (loc == loc)
  916. output = zeros(shape(cond0), 'd')
  917. place(output, (1-cond0), self.badvalue)
  918. goodargs = argsreduce(cond0, scale, *args)
  919. goodscale = goodargs[0]
  920. goodargs = goodargs[1:]
  921. place(output, cond0, self.vecentropy(*goodargs) + log(goodscale))
  922. return output
  923. def moment(self, n, *args, **kwds):
  924. """
  925. n-th order non-central moment of distribution.
  926. Parameters
  927. ----------
  928. n : int, n >= 1
  929. Order of moment.
  930. arg1, arg2, arg3,... : float
  931. The shape parameter(s) for the distribution (see docstring of the
  932. instance object for more information).
  933. loc : array_like, optional
  934. location parameter (default=0)
  935. scale : array_like, optional
  936. scale parameter (default=1)
  937. """
  938. args, loc, scale = self._parse_args(*args, **kwds)
  939. if not (self._argcheck(*args) and (scale > 0)):
  940. return nan
  941. if (floor(n) != n):
  942. raise ValueError("Moment must be an integer.")
  943. if (n < 0):
  944. raise ValueError("Moment must be positive.")
  945. mu, mu2, g1, g2 = None, None, None, None
  946. if (n > 0) and (n < 5):
  947. if self._stats_has_moments:
  948. mdict = {'moments': {1: 'm', 2: 'v', 3: 'vs', 4: 'vk'}[n]}
  949. else:
  950. mdict = {}
  951. mu, mu2, g1, g2 = self._stats(*args, **mdict)
  952. val = _moment_from_stats(n, mu, mu2, g1, g2, self._munp, args)
  953. # Convert to transformed X = L + S*Y
  954. # E[X^n] = E[(L+S*Y)^n] = L^n sum(comb(n, k)*(S/L)^k E[Y^k], k=0...n)
  955. if loc == 0:
  956. return scale**n * val
  957. else:
  958. result = 0
  959. fac = float(scale) / float(loc)
  960. for k in range(n):
  961. valk = _moment_from_stats(k, mu, mu2, g1, g2, self._munp, args)
  962. result += comb(n, k, exact=True)*(fac**k) * valk
  963. result += fac**n * val
  964. return result * loc**n
  965. def median(self, *args, **kwds):
  966. """
  967. Median of the distribution.
  968. Parameters
  969. ----------
  970. arg1, arg2, arg3,... : array_like
  971. The shape parameter(s) for the distribution (see docstring of the
  972. instance object for more information)
  973. loc : array_like, optional
  974. Location parameter, Default is 0.
  975. scale : array_like, optional
  976. Scale parameter, Default is 1.
  977. Returns
  978. -------
  979. median : float
  980. The median of the distribution.
  981. See Also
  982. --------
  983. stats.distributions.rv_discrete.ppf
  984. Inverse of the CDF
  985. """
  986. return self.ppf(0.5, *args, **kwds)
  987. def mean(self, *args, **kwds):
  988. """
  989. Mean of the distribution.
  990. Parameters
  991. ----------
  992. arg1, arg2, arg3,... : array_like
  993. The shape parameter(s) for the distribution (see docstring of the
  994. instance object for more information)
  995. loc : array_like, optional
  996. location parameter (default=0)
  997. scale : array_like, optional
  998. scale parameter (default=1)
  999. Returns
  1000. -------
  1001. mean : float
  1002. the mean of the distribution
  1003. """
  1004. kwds['moments'] = 'm'
  1005. res = self.stats(*args, **kwds)
  1006. if isinstance(res, ndarray) and res.ndim == 0:
  1007. return res[()]
  1008. return res
  1009. def var(self, *args, **kwds):
  1010. """
  1011. Variance of the distribution.
  1012. Parameters
  1013. ----------
  1014. arg1, arg2, arg3,... : array_like
  1015. The shape parameter(s) for the distribution (see docstring of the
  1016. instance object for more information)
  1017. loc : array_like, optional
  1018. location parameter (default=0)
  1019. scale : array_like, optional
  1020. scale parameter (default=1)
  1021. Returns
  1022. -------
  1023. var : float
  1024. the variance of the distribution
  1025. """
  1026. kwds['moments'] = 'v'
  1027. res = self.stats(*args, **kwds)
  1028. if isinstance(res, ndarray) and res.ndim == 0:
  1029. return res[()]
  1030. return res
  1031. def std(self, *args, **kwds):
  1032. """
  1033. Standard deviation of the distribution.
  1034. Parameters
  1035. ----------
  1036. arg1, arg2, arg3,... : array_like
  1037. The shape parameter(s) for the distribution (see docstring of the
  1038. instance object for more information)
  1039. loc : array_like, optional
  1040. location parameter (default=0)
  1041. scale : array_like, optional
  1042. scale parameter (default=1)
  1043. Returns
  1044. -------
  1045. std : float
  1046. standard deviation of the distribution
  1047. """
  1048. kwds['moments'] = 'v'
  1049. res = sqrt(self.stats(*args, **kwds))
  1050. return res
  1051. def interval(self, alpha, *args, **kwds):
  1052. """
  1053. Confidence interval with equal areas around the median.
  1054. Parameters
  1055. ----------
  1056. alpha : array_like of float
  1057. Probability that an rv will be drawn from the returned range.
  1058. Each value should be in the range [0, 1].
  1059. arg1, arg2, ... : array_like
  1060. The shape parameter(s) for the distribution (see docstring of the
  1061. instance object for more information).
  1062. loc : array_like, optional
  1063. location parameter, Default is 0.
  1064. scale : array_like, optional
  1065. scale parameter, Default is 1.
  1066. Returns
  1067. -------
  1068. a, b : ndarray of float
  1069. end-points of range that contain ``100 * alpha %`` of the rv's
  1070. possible values.
  1071. """
  1072. alpha = asarray(alpha)
  1073. if np.any((alpha > 1) | (alpha < 0)):
  1074. raise ValueError("alpha must be between 0 and 1 inclusive")
  1075. q1 = (1.0-alpha)/2
  1076. q2 = (1.0+alpha)/2
  1077. a = self.ppf(q1, *args, **kwds)
  1078. b = self.ppf(q2, *args, **kwds)
  1079. return a, b
  1080. ## continuous random variables: implement maybe later
  1081. ##
  1082. ## hf --- Hazard Function (PDF / SF)
  1083. ## chf --- Cumulative hazard function (-log(SF))
  1084. ## psf --- Probability sparsity function (reciprocal of the pdf) in
  1085. ## units of percent-point-function (as a function of q).
  1086. ## Also, the derivative of the percent-point function.
  1087. class rv_continuous(rv_generic):
  1088. """
  1089. A generic continuous random variable class meant for subclassing.
  1090. `rv_continuous` is a base class to construct specific distribution classes
  1091. and instances for continuous random variables. It cannot be used
  1092. directly as a distribution.
  1093. Parameters
  1094. ----------
  1095. momtype : int, optional
  1096. The type of generic moment calculation to use: 0 for pdf, 1 (default)
  1097. for ppf.
  1098. a : float, optional
  1099. Lower bound of the support of the distribution, default is minus
  1100. infinity.
  1101. b : float, optional
  1102. Upper bound of the support of the distribution, default is plus
  1103. infinity.
  1104. xtol : float, optional
  1105. The tolerance for fixed point calculation for generic ppf.
  1106. badvalue : float, optional
  1107. The value in a result arrays that indicates a value that for which
  1108. some argument restriction is violated, default is np.nan.
  1109. name : str, optional
  1110. The name of the instance. This string is used to construct the default
  1111. example for distributions.
  1112. longname : str, optional
  1113. This string is used as part of the first line of the docstring returned
  1114. when a subclass has no docstring of its own. Note: `longname` exists
  1115. for backwards compatibility, do not use for new subclasses.
  1116. shapes : str, optional
  1117. The shape of the distribution. For example ``"m, n"`` for a
  1118. distribution that takes two integers as the two shape arguments for all
  1119. its methods. If not provided, shape parameters will be inferred from
  1120. the signature of the private methods, ``_pdf`` and ``_cdf`` of the
  1121. instance.
  1122. extradoc : str, optional, deprecated
  1123. This string is used as the last part of the docstring returned when a
  1124. subclass has no docstring of its own. Note: `extradoc` exists for
  1125. backwards compatibility, do not use for new subclasses.
  1126. seed : None or int or ``numpy.random.RandomState`` instance, optional
  1127. This parameter defines the RandomState object to use for drawing
  1128. random variates.
  1129. If None (or np.random), the global np.random state is used.
  1130. If integer, it is used to seed the local RandomState instance.
  1131. Default is None.
  1132. Methods
  1133. -------
  1134. rvs
  1135. pdf
  1136. logpdf
  1137. cdf
  1138. logcdf
  1139. sf
  1140. logsf
  1141. ppf
  1142. isf
  1143. moment
  1144. stats
  1145. entropy
  1146. expect
  1147. median
  1148. mean
  1149. std
  1150. var
  1151. interval
  1152. __call__
  1153. fit
  1154. fit_loc_scale
  1155. nnlf
  1156. Notes
  1157. -----
  1158. Public methods of an instance of a distribution class (e.g., ``pdf``,
  1159. ``cdf``) check their arguments and pass valid arguments to private,
  1160. computational methods (``_pdf``, ``_cdf``). For ``pdf(x)``, ``x`` is valid
  1161. if it is within the support of a distribution, ``self.a <= x <= self.b``.
  1162. Whether a shape parameter is valid is decided by an ``_argcheck`` method
  1163. (which defaults to checking that its arguments are strictly positive.)
  1164. **Subclassing**
  1165. New random variables can be defined by subclassing the `rv_continuous` class
  1166. and re-defining at least the ``_pdf`` or the ``_cdf`` method (normalized
  1167. to location 0 and scale 1).
  1168. If positive argument checking is not correct for your RV
  1169. then you will also need to re-define the ``_argcheck`` method.
  1170. Correct, but potentially slow defaults exist for the remaining
  1171. methods but for speed and/or accuracy you can over-ride::
  1172. _logpdf, _cdf, _logcdf, _ppf, _rvs, _isf, _sf, _logsf
  1173. The default method ``_rvs`` relies on the inverse of the cdf, ``_ppf``,
  1174. applied to a uniform random variate. In order to generate random variates
  1175. efficiently, either the default ``_ppf`` needs to be overwritten (e.g.
  1176. if the inverse cdf can expressed in an explicit form) or a sampling
  1177. method needs to be implemented in a custom ``_rvs`` method.
  1178. If possible, you should override ``_isf``, ``_sf`` or ``_logsf``.
  1179. The main reason would be to improve numerical accuracy: for example,
  1180. the survival function ``_sf`` is computed as ``1 - _cdf`` which can
  1181. result in loss of precision if ``_cdf(x)`` is close to one.
  1182. **Methods that can be overwritten by subclasses**
  1183. ::
  1184. _rvs
  1185. _pdf
  1186. _cdf
  1187. _sf
  1188. _ppf
  1189. _isf
  1190. _stats
  1191. _munp
  1192. _entropy
  1193. _argcheck
  1194. There are additional (internal and private) generic methods that can
  1195. be useful for cross-checking and for debugging, but might work in all
  1196. cases when directly called.
  1197. A note on ``shapes``: subclasses need not specify them explicitly. In this
  1198. case, `shapes` will be automatically deduced from the signatures of the
  1199. overridden methods (`pdf`, `cdf` etc).
  1200. If, for some reason, you prefer to avoid relying on introspection, you can
  1201. specify ``shapes`` explicitly as an argument to the instance constructor.
  1202. **Frozen Distributions**
  1203. Normally, you must provide shape parameters (and, optionally, location and
  1204. scale parameters to each call of a method of a distribution.
  1205. Alternatively, the object may be called (as a function) to fix the shape,
  1206. location, and scale parameters returning a "frozen" continuous RV object:
  1207. rv = generic(<shape(s)>, loc=0, scale=1)
  1208. `rv_frozen` object with the same methods but holding the given shape,
  1209. location, and scale fixed
  1210. **Statistics**
  1211. Statistics are computed using numerical integration by default.
  1212. For speed you can redefine this using ``_stats``:
  1213. - take shape parameters and return mu, mu2, g1, g2
  1214. - If you can't compute one of these, return it as None
  1215. - Can also be defined with a keyword argument ``moments``, which is a
  1216. string composed of "m", "v", "s", and/or "k".
  1217. Only the components appearing in string should be computed and
  1218. returned in the order "m", "v", "s", or "k" with missing values
  1219. returned as None.
  1220. Alternatively, you can override ``_munp``, which takes ``n`` and shape
  1221. parameters and returns the n-th non-central moment of the distribution.
  1222. Examples
  1223. --------
  1224. To create a new Gaussian distribution, we would do the following:
  1225. >>> from scipy.stats import rv_continuous
  1226. >>> class gaussian_gen(rv_continuous):
  1227. ... "Gaussian distribution"
  1228. ... def _pdf(self, x):
  1229. ... return np.exp(-x**2 / 2.) / np.sqrt(2.0 * np.pi)
  1230. >>> gaussian = gaussian_gen(name='gaussian')
  1231. ``scipy.stats`` distributions are *instances*, so here we subclass
  1232. `rv_continuous` and create an instance. With this, we now have
  1233. a fully functional distribution with all relevant methods automagically
  1234. generated by the framework.
  1235. Note that above we defined a standard normal distribution, with zero mean
  1236. and unit variance. Shifting and scaling of the distribution can be done
  1237. by using ``loc`` and ``scale`` parameters: ``gaussian.pdf(x, loc, scale)``
  1238. essentially computes ``y = (x - loc) / scale`` and
  1239. ``gaussian._pdf(y) / scale``.
  1240. """
  1241. def __init__(self, momtype=1, a=None, b=None, xtol=1e-14,
  1242. badvalue=None, name=None, longname=None,
  1243. shapes=None, extradoc=None, seed=None):
  1244. super(rv_continuous, self).__init__(seed)
  1245. # save the ctor parameters, cf generic freeze
  1246. self._ctor_param = dict(
  1247. momtype=momtype, a=a, b=b, xtol=xtol,
  1248. badvalue=badvalue, name=name, longname=longname,
  1249. shapes=shapes, extradoc=extradoc, seed=seed)
  1250. if badvalue is None:
  1251. badvalue = nan
  1252. if name is None:
  1253. name = 'Distribution'
  1254. self.badvalue = badvalue
  1255. self.name = name
  1256. self.a = a
  1257. self.b = b
  1258. if a is None:
  1259. self.a = -inf
  1260. if b is None:
  1261. self.b = inf
  1262. self.xtol = xtol
  1263. self.moment_type = momtype
  1264. self.shapes = shapes
  1265. self._construct_argparser(meths_to_inspect=[self._pdf, self._cdf],
  1266. locscale_in='loc=0, scale=1',
  1267. locscale_out='loc, scale')
  1268. # nin correction
  1269. self._ppfvec = vectorize(self._ppf_single, otypes='d')
  1270. self._ppfvec.nin = self.numargs + 1
  1271. self.vecentropy = vectorize(self._entropy, otypes='d')
  1272. self._cdfvec = vectorize(self._cdf_single, otypes='d')
  1273. self._cdfvec.nin = self.numargs + 1
  1274. self.extradoc = extradoc
  1275. if momtype == 0:
  1276. self.generic_moment = vectorize(self._mom0_sc, otypes='d')
  1277. else:
  1278. self.generic_moment = vectorize(self._mom1_sc, otypes='d')
  1279. # Because of the *args argument of _mom0_sc, vectorize cannot count the
  1280. # number of arguments correctly.
  1281. self.generic_moment.nin = self.numargs + 1
  1282. if longname is None:
  1283. if name[0] in ['aeiouAEIOU']:
  1284. hstr = "An "
  1285. else:
  1286. hstr = "A "
  1287. longname = hstr + name
  1288. if sys.flags.optimize < 2:
  1289. # Skip adding docstrings if interpreter is run with -OO
  1290. if self.__doc__ is None:
  1291. self._construct_default_doc(longname=longname,
  1292. extradoc=extradoc,
  1293. docdict=docdict,
  1294. discrete='continuous')
  1295. else:
  1296. dct = dict(distcont)
  1297. self._construct_doc(docdict, dct.get(self.name))
  1298. def _updated_ctor_param(self):
  1299. """ Return the current version of _ctor_param, possibly updated by user.
  1300. Used by freezing and pickling.
  1301. Keep this in sync with the signature of __init__.
  1302. """
  1303. dct = self._ctor_param.copy()
  1304. dct['a'] = self.a
  1305. dct['b'] = self.b
  1306. dct['xtol'] = self.xtol
  1307. dct['badvalue'] = self.badvalue
  1308. dct['name'] = self.name
  1309. dct['shapes'] = self.shapes
  1310. dct['extradoc'] = self.extradoc
  1311. return dct
  1312. def _ppf_to_solve(self, x, q, *args):
  1313. return self.cdf(*(x, )+args)-q
  1314. def _ppf_single(self, q, *args):
  1315. left = right = None
  1316. if self.a > -np.inf:
  1317. left = self.a
  1318. if self.b < np.inf:
  1319. right = self.b
  1320. factor = 10.
  1321. if not left: # i.e. self.a = -inf
  1322. left = -1.*factor
  1323. while self._ppf_to_solve(left, q, *args) > 0.:
  1324. right = left
  1325. left *= factor
  1326. # left is now such that cdf(left) < q
  1327. if not right: # i.e. self.b = inf
  1328. right = factor
  1329. while self._ppf_to_solve(right, q, *args) < 0.:
  1330. left = right
  1331. right *= factor
  1332. # right is now such that cdf(right) > q
  1333. return optimize.brentq(self._ppf_to_solve,
  1334. left, right, args=(q,)+args, xtol=self.xtol)
  1335. # moment from definition
  1336. def _mom_integ0(self, x, m, *args):
  1337. return x**m * self.pdf(x, *args)
  1338. def _mom0_sc(self, m, *args):
  1339. return integrate.quad(self._mom_integ0, self.a, self.b,
  1340. args=(m,)+args)[0]
  1341. # moment calculated using ppf
  1342. def _mom_integ1(self, q, m, *args):
  1343. return (self.ppf(q, *args))**m
  1344. def _mom1_sc(self, m, *args):
  1345. return integrate.quad(self._mom_integ1, 0, 1, args=(m,)+args)[0]
  1346. def _pdf(self, x, *args):
  1347. return derivative(self._cdf, x, dx=1e-5, args=args, order=5)
  1348. ## Could also define any of these
  1349. def _logpdf(self, x, *args):
  1350. return log(self._pdf(x, *args))
  1351. def _cdf_single(self, x, *args):
  1352. return integrate.quad(self._pdf, self.a, x, args=args)[0]
  1353. def _cdf(self, x, *args):
  1354. return self._cdfvec(x, *args)
  1355. ## generic _argcheck, _logcdf, _sf, _logsf, _ppf, _isf, _rvs are defined
  1356. ## in rv_generic
  1357. def pdf(self, x, *args, **kwds):
  1358. """
  1359. Probability density function at x of the given RV.
  1360. Parameters
  1361. ----------
  1362. x : array_like
  1363. quantiles
  1364. arg1, arg2, arg3,... : array_like
  1365. The shape parameter(s) for the distribution (see docstring of the
  1366. instance object for more information)
  1367. loc : array_like, optional
  1368. location parameter (default=0)
  1369. scale : array_like, optional
  1370. scale parameter (default=1)
  1371. Returns
  1372. -------
  1373. pdf : ndarray
  1374. Probability density function evaluated at x
  1375. """
  1376. args, loc, scale = self._parse_args(*args, **kwds)
  1377. x, loc, scale = map(asarray, (x, loc, scale))
  1378. args = tuple(map(asarray, args))
  1379. dtyp = np.find_common_type([x.dtype, np.float64], [])
  1380. x = np.asarray((x - loc)/scale, dtype=dtyp)
  1381. cond0 = self._argcheck(*args) & (scale > 0)
  1382. cond1 = self._support_mask(x) & (scale > 0)
  1383. cond = cond0 & cond1
  1384. output = zeros(shape(cond), dtyp)
  1385. putmask(output, (1-cond0)+np.isnan(x), self.badvalue)
  1386. if np.any(cond):
  1387. goodargs = argsreduce(cond, *((x,)+args+(scale,)))
  1388. scale, goodargs = goodargs[-1], goodargs[:-1]
  1389. place(output, cond, self._pdf(*goodargs) / scale)
  1390. if output.ndim == 0:
  1391. return output[()]
  1392. return output
  1393. def logpdf(self, x, *args, **kwds):
  1394. """
  1395. Log of the probability density function at x of the given RV.
  1396. This uses a more numerically accurate calculation if available.
  1397. Parameters
  1398. ----------
  1399. x : array_like
  1400. quantiles
  1401. arg1, arg2, arg3,... : array_like
  1402. The shape parameter(s) for the distribution (see docstring of the
  1403. instance object for more information)
  1404. loc : array_like, optional
  1405. location parameter (default=0)
  1406. scale : array_like, optional
  1407. scale parameter (default=1)
  1408. Returns
  1409. -------
  1410. logpdf : array_like
  1411. Log of the probability density function evaluated at x
  1412. """
  1413. args, loc, scale = self._parse_args(*args, **kwds)
  1414. x, loc, scale = map(asarray, (x, loc, scale))
  1415. args = tuple(map(asarray, args))
  1416. dtyp = np.find_common_type([x.dtype, np.float64], [])
  1417. x = np.asarray((x - loc)/scale, dtype=dtyp)
  1418. cond0 = self._argcheck(*args) & (scale > 0)
  1419. cond1 = self._support_mask(x) & (scale > 0)
  1420. cond = cond0 & cond1
  1421. output = empty(shape(cond), dtyp)
  1422. output.fill(NINF)
  1423. putmask(output, (1-cond0)+np.isnan(x), self.badvalue)
  1424. if np.any(cond):
  1425. goodargs = argsreduce(cond, *((x,)+args+(scale,)))
  1426. scale, goodargs = goodargs[-1], goodargs[:-1]
  1427. place(output, cond, self._logpdf(*goodargs) - log(scale))
  1428. if output.ndim == 0:
  1429. return output[()]
  1430. return output
  1431. def cdf(self, x, *args, **kwds):
  1432. """
  1433. Cumulative distribution function of the given RV.
  1434. Parameters
  1435. ----------
  1436. x : array_like
  1437. quantiles
  1438. arg1, arg2, arg3,... : array_like
  1439. The shape parameter(s) for the distribution (see docstring of the
  1440. instance object for more information)
  1441. loc : array_like, optional
  1442. location parameter (default=0)
  1443. scale : array_like, optional
  1444. scale parameter (default=1)
  1445. Returns
  1446. -------
  1447. cdf : ndarray
  1448. Cumulative distribution function evaluated at `x`
  1449. """
  1450. args, loc, scale = self._parse_args(*args, **kwds)
  1451. x, loc, scale = map(asarray, (x, loc, scale))
  1452. args = tuple(map(asarray, args))
  1453. dtyp = np.find_common_type([x.dtype, np.float64], [])
  1454. x = np.asarray((x - loc)/scale, dtype=dtyp)
  1455. cond0 = self._argcheck(*args) & (scale > 0)
  1456. cond1 = self._open_support_mask(x) & (scale > 0)
  1457. cond2 = (x >= self.b) & cond0
  1458. cond = cond0 & cond1
  1459. output = zeros(shape(cond), dtyp)
  1460. place(output, (1-cond0)+np.isnan(x), self.badvalue)
  1461. place(output, cond2, 1.0)
  1462. if np.any(cond): # call only if at least 1 entry
  1463. goodargs = argsreduce(cond, *((x,)+args))
  1464. place(output, cond, self._cdf(*goodargs))
  1465. if output.ndim == 0:
  1466. return output[()]
  1467. return output
  1468. def logcdf(self, x, *args, **kwds):
  1469. """
  1470. Log of the cumulative distribution function at x of the given RV.
  1471. Parameters
  1472. ----------
  1473. x : array_like
  1474. quantiles
  1475. arg1, arg2, arg3,... : array_like
  1476. The shape parameter(s) for the distribution (see docstring of the
  1477. instance object for more information)
  1478. loc : array_like, optional
  1479. location parameter (default=0)
  1480. scale : array_like, optional
  1481. scale parameter (default=1)
  1482. Returns
  1483. -------
  1484. logcdf : array_like
  1485. Log of the cumulative distribution function evaluated at x
  1486. """
  1487. args, loc, scale = self._parse_args(*args, **kwds)
  1488. x, loc, scale = map(asarray, (x, loc, scale))
  1489. args = tuple(map(asarray, args))
  1490. dtyp = np.find_common_type([x.dtype, np.float64], [])
  1491. x = np.asarray((x - loc)/scale, dtype=dtyp)
  1492. cond0 = self._argcheck(*args) & (scale > 0)
  1493. cond1 = self._open_support_mask(x) & (scale > 0)
  1494. cond2 = (x >= self.b) & cond0
  1495. cond = cond0 & cond1
  1496. output = empty(shape(cond), dtyp)
  1497. output.fill(NINF)
  1498. place(output, (1-cond0)*(cond1 == cond1)+np.isnan(x), self.badvalue)
  1499. place(output, cond2, 0.0)
  1500. if np.any(cond): # call only if at least 1 entry
  1501. goodargs = argsreduce(cond, *((x,)+args))
  1502. place(output, cond, self._logcdf(*goodargs))
  1503. if output.ndim == 0:
  1504. return output[()]
  1505. return output
  1506. def sf(self, x, *args, **kwds):
  1507. """
  1508. Survival function (1 - `cdf`) at x of the given RV.
  1509. Parameters
  1510. ----------
  1511. x : array_like
  1512. quantiles
  1513. arg1, arg2, arg3,... : array_like
  1514. The shape parameter(s) for the distribution (see docstring of the
  1515. instance object for more information)
  1516. loc : array_like, optional
  1517. location parameter (default=0)
  1518. scale : array_like, optional
  1519. scale parameter (default=1)
  1520. Returns
  1521. -------
  1522. sf : array_like
  1523. Survival function evaluated at x
  1524. """
  1525. args, loc, scale = self._parse_args(*args, **kwds)
  1526. x, loc, scale = map(asarray, (x, loc, scale))
  1527. args = tuple(map(asarray, args))
  1528. dtyp = np.find_common_type([x.dtype, np.float64], [])
  1529. x = np.asarray((x - loc)/scale, dtype=dtyp)
  1530. cond0 = self._argcheck(*args) & (scale > 0)
  1531. cond1 = self._open_support_mask(x) & (scale > 0)
  1532. cond2 = cond0 & (x <= self.a)
  1533. cond = cond0 & cond1
  1534. output = zeros(shape(cond), dtyp)
  1535. place(output, (1-cond0)+np.isnan(x), self.badvalue)
  1536. place(output, cond2, 1.0)
  1537. if np.any(cond):
  1538. goodargs = argsreduce(cond, *((x,)+args))
  1539. place(output, cond, self._sf(*goodargs))
  1540. if output.ndim == 0:
  1541. return output[()]
  1542. return output
  1543. def logsf(self, x, *args, **kwds):
  1544. """
  1545. Log of the survival function of the given RV.
  1546. Returns the log of the "survival function," defined as (1 - `cdf`),
  1547. evaluated at `x`.
  1548. Parameters
  1549. ----------
  1550. x : array_like
  1551. quantiles
  1552. arg1, arg2, arg3,... : array_like
  1553. The shape parameter(s) for the distribution (see docstring of the
  1554. instance object for more information)
  1555. loc : array_like, optional
  1556. location parameter (default=0)
  1557. scale : array_like, optional
  1558. scale parameter (default=1)
  1559. Returns
  1560. -------
  1561. logsf : ndarray
  1562. Log of the survival function evaluated at `x`.
  1563. """
  1564. args, loc, scale = self._parse_args(*args, **kwds)
  1565. x, loc, scale = map(asarray, (x, loc, scale))
  1566. args = tuple(map(asarray, args))
  1567. dtyp = np.find_common_type([x.dtype, np.float64], [])
  1568. x = np.asarray((x - loc)/scale, dtype=dtyp)
  1569. cond0 = self._argcheck(*args) & (scale > 0)
  1570. cond1 = self._open_support_mask(x) & (scale > 0)
  1571. cond2 = cond0 & (x <= self.a)
  1572. cond = cond0 & cond1
  1573. output = empty(shape(cond), dtyp)
  1574. output.fill(NINF)
  1575. place(output, (1-cond0)+np.isnan(x), self.badvalue)
  1576. place(output, cond2, 0.0)
  1577. if np.any(cond):
  1578. goodargs = argsreduce(cond, *((x,)+args))
  1579. place(output, cond, self._logsf(*goodargs))
  1580. if output.ndim == 0:
  1581. return output[()]
  1582. return output
  1583. def ppf(self, q, *args, **kwds):
  1584. """
  1585. Percent point function (inverse of `cdf`) at q of the given RV.
  1586. Parameters
  1587. ----------
  1588. q : array_like
  1589. lower tail probability
  1590. arg1, arg2, arg3,... : array_like
  1591. The shape parameter(s) for the distribution (see docstring of the
  1592. instance object for more information)
  1593. loc : array_like, optional
  1594. location parameter (default=0)
  1595. scale : array_like, optional
  1596. scale parameter (default=1)
  1597. Returns
  1598. -------
  1599. x : array_like
  1600. quantile corresponding to the lower tail probability q.
  1601. """
  1602. args, loc, scale = self._parse_args(*args, **kwds)
  1603. q, loc, scale = map(asarray, (q, loc, scale))
  1604. args = tuple(map(asarray, args))
  1605. cond0 = self._argcheck(*args) & (scale > 0) & (loc == loc)
  1606. cond1 = (0 < q) & (q < 1)
  1607. cond2 = cond0 & (q == 0)
  1608. cond3 = cond0 & (q == 1)
  1609. cond = cond0 & cond1
  1610. output = valarray(shape(cond), value=self.badvalue)
  1611. lower_bound = self.a * scale + loc
  1612. upper_bound = self.b * scale + loc
  1613. place(output, cond2, argsreduce(cond2, lower_bound)[0])
  1614. place(output, cond3, argsreduce(cond3, upper_bound)[0])
  1615. if np.any(cond): # call only if at least 1 entry
  1616. goodargs = argsreduce(cond, *((q,)+args+(scale, loc)))
  1617. scale, loc, goodargs = goodargs[-2], goodargs[-1], goodargs[:-2]
  1618. place(output, cond, self._ppf(*goodargs) * scale + loc)
  1619. if output.ndim == 0:
  1620. return output[()]
  1621. return output
  1622. def isf(self, q, *args, **kwds):
  1623. """
  1624. Inverse survival function (inverse of `sf`) at q of the given RV.
  1625. Parameters
  1626. ----------
  1627. q : array_like
  1628. upper tail probability
  1629. arg1, arg2, arg3,... : array_like
  1630. The shape parameter(s) for the distribution (see docstring of the
  1631. instance object for more information)
  1632. loc : array_like, optional
  1633. location parameter (default=0)
  1634. scale : array_like, optional
  1635. scale parameter (default=1)
  1636. Returns
  1637. -------
  1638. x : ndarray or scalar
  1639. Quantile corresponding to the upper tail probability q.
  1640. """
  1641. args, loc, scale = self._parse_args(*args, **kwds)
  1642. q, loc, scale = map(asarray, (q, loc, scale))
  1643. args = tuple(map(asarray, args))
  1644. cond0 = self._argcheck(*args) & (scale > 0) & (loc == loc)
  1645. cond1 = (0 < q) & (q < 1)
  1646. cond2 = cond0 & (q == 1)
  1647. cond3 = cond0 & (q == 0)
  1648. cond = cond0 & cond1
  1649. output = valarray(shape(cond), value=self.badvalue)
  1650. lower_bound = self.a * scale + loc
  1651. upper_bound = self.b * scale + loc
  1652. place(output, cond2, argsreduce(cond2, lower_bound)[0])
  1653. place(output, cond3, argsreduce(cond3, upper_bound)[0])
  1654. if np.any(cond):
  1655. goodargs = argsreduce(cond, *((q,)+args+(scale, loc)))
  1656. scale, loc, goodargs = goodargs[-2], goodargs[-1], goodargs[:-2]
  1657. place(output, cond, self._isf(*goodargs) * scale + loc)
  1658. if output.ndim == 0:
  1659. return output[()]
  1660. return output
  1661. def _nnlf(self, x, *args):
  1662. return -np.sum(self._logpdf(x, *args), axis=0)
  1663. def _unpack_loc_scale(self, theta):
  1664. try:
  1665. loc = theta[-2]
  1666. scale = theta[-1]
  1667. args = tuple(theta[:-2])
  1668. except IndexError:
  1669. raise ValueError("Not enough input arguments.")
  1670. return loc, scale, args
  1671. def nnlf(self, theta, x):
  1672. '''Return negative loglikelihood function.
  1673. Notes
  1674. -----
  1675. This is ``-sum(log pdf(x, theta), axis=0)`` where `theta` are the
  1676. parameters (including loc and scale).
  1677. '''
  1678. loc, scale, args = self._unpack_loc_scale(theta)
  1679. if not self._argcheck(*args) or scale <= 0:
  1680. return inf
  1681. x = asarray((x-loc) / scale)
  1682. n_log_scale = len(x) * log(scale)
  1683. if np.any(~self._support_mask(x)):
  1684. return inf
  1685. return self._nnlf(x, *args) + n_log_scale
  1686. def _nnlf_and_penalty(self, x, args):
  1687. cond0 = ~self._support_mask(x)
  1688. n_bad = np.count_nonzero(cond0, axis=0)
  1689. if n_bad > 0:
  1690. x = argsreduce(~cond0, x)[0]
  1691. logpdf = self._logpdf(x, *args)
  1692. finite_logpdf = np.isfinite(logpdf)
  1693. n_bad += np.sum(~finite_logpdf, axis=0)
  1694. if n_bad > 0:
  1695. penalty = n_bad * log(_XMAX) * 100
  1696. return -np.sum(logpdf[finite_logpdf], axis=0) + penalty
  1697. return -np.sum(logpdf, axis=0)
  1698. def _penalized_nnlf(self, theta, x):
  1699. ''' Return penalized negative loglikelihood function,
  1700. i.e., - sum (log pdf(x, theta), axis=0) + penalty
  1701. where theta are the parameters (including loc and scale)
  1702. '''
  1703. loc, scale, args = self._unpack_loc_scale(theta)
  1704. if not self._argcheck(*args) or scale <= 0:
  1705. return inf
  1706. x = asarray((x-loc) / scale)
  1707. n_log_scale = len(x) * log(scale)
  1708. return self._nnlf_and_penalty(x, args) + n_log_scale
  1709. # return starting point for fit (shape arguments + loc + scale)
  1710. def _fitstart(self, data, args=None):
  1711. if args is None:
  1712. args = (1.0,)*self.numargs
  1713. loc, scale = self._fit_loc_scale_support(data, *args)
  1714. return args + (loc, scale)
  1715. # Return the (possibly reduced) function to optimize in order to find MLE
  1716. # estimates for the .fit method
  1717. def _reduce_func(self, args, kwds):
  1718. # First of all, convert fshapes params to fnum: eg for stats.beta,
  1719. # shapes='a, b'. To fix `a`, can specify either `f1` or `fa`.
  1720. # Convert the latter into the former.
  1721. if self.shapes:
  1722. shapes = self.shapes.replace(',', ' ').split()
  1723. for j, s in enumerate(shapes):
  1724. val = kwds.pop('f' + s, None) or kwds.pop('fix_' + s, None)
  1725. if val is not None:
  1726. key = 'f%d' % j
  1727. if key in kwds:
  1728. raise ValueError("Duplicate entry for %s." % key)
  1729. else:
  1730. kwds[key] = val
  1731. args = list(args)
  1732. Nargs = len(args)
  1733. fixedn = []
  1734. names = ['f%d' % n for n in range(Nargs - 2)] + ['floc', 'fscale']
  1735. x0 = []
  1736. for n, key in enumerate(names):
  1737. if key in kwds:
  1738. fixedn.append(n)
  1739. args[n] = kwds.pop(key)
  1740. else:
  1741. x0.append(args[n])
  1742. if len(fixedn) == 0:
  1743. func = self._penalized_nnlf
  1744. restore = None
  1745. else:
  1746. if len(fixedn) == Nargs:
  1747. raise ValueError(
  1748. "All parameters fixed. There is nothing to optimize.")
  1749. def restore(args, theta):
  1750. # Replace with theta for all numbers not in fixedn
  1751. # This allows the non-fixed values to vary, but
  1752. # we still call self.nnlf with all parameters.
  1753. i = 0
  1754. for n in range(Nargs):
  1755. if n not in fixedn:
  1756. args[n] = theta[i]
  1757. i += 1
  1758. return args
  1759. def func(theta, x):
  1760. newtheta = restore(args[:], theta)
  1761. return self._penalized_nnlf(newtheta, x)
  1762. return x0, func, restore, args
  1763. def fit(self, data, *args, **kwds):
  1764. """
  1765. Return MLEs for shape (if applicable), location, and scale
  1766. parameters from data.
  1767. MLE stands for Maximum Likelihood Estimate. Starting estimates for
  1768. the fit are given by input arguments; for any arguments not provided
  1769. with starting estimates, ``self._fitstart(data)`` is called to generate
  1770. such.
  1771. One can hold some parameters fixed to specific values by passing in
  1772. keyword arguments ``f0``, ``f1``, ..., ``fn`` (for shape parameters)
  1773. and ``floc`` and ``fscale`` (for location and scale parameters,
  1774. respectively).
  1775. Parameters
  1776. ----------
  1777. data : array_like
  1778. Data to use in calculating the MLEs.
  1779. args : floats, optional
  1780. Starting value(s) for any shape-characterizing arguments (those not
  1781. provided will be determined by a call to ``_fitstart(data)``).
  1782. No default value.
  1783. kwds : floats, optional
  1784. Starting values for the location and scale parameters; no default.
  1785. Special keyword arguments are recognized as holding certain
  1786. parameters fixed:
  1787. - f0...fn : hold respective shape parameters fixed.
  1788. Alternatively, shape parameters to fix can be specified by name.
  1789. For example, if ``self.shapes == "a, b"``, ``fa``and ``fix_a``
  1790. are equivalent to ``f0``, and ``fb`` and ``fix_b`` are
  1791. equivalent to ``f1``.
  1792. - floc : hold location parameter fixed to specified value.
  1793. - fscale : hold scale parameter fixed to specified value.
  1794. - optimizer : The optimizer to use. The optimizer must take ``func``,
  1795. and starting position as the first two arguments,
  1796. plus ``args`` (for extra arguments to pass to the
  1797. function to be optimized) and ``disp=0`` to suppress
  1798. output as keyword arguments.
  1799. Returns
  1800. -------
  1801. mle_tuple : tuple of floats
  1802. MLEs for any shape parameters (if applicable), followed by those
  1803. for location and scale. For most random variables, shape statistics
  1804. will be returned, but there are exceptions (e.g. ``norm``).
  1805. Notes
  1806. -----
  1807. This fit is computed by maximizing a log-likelihood function, with
  1808. penalty applied for samples outside of range of the distribution. The
  1809. returned answer is not guaranteed to be the globally optimal MLE, it
  1810. may only be locally optimal, or the optimization may fail altogether.
  1811. Examples
  1812. --------
  1813. Generate some data to fit: draw random variates from the `beta`
  1814. distribution
  1815. >>> from scipy.stats import beta
  1816. >>> a, b = 1., 2.
  1817. >>> x = beta.rvs(a, b, size=1000)
  1818. Now we can fit all four parameters (``a``, ``b``, ``loc`` and ``scale``):
  1819. >>> a1, b1, loc1, scale1 = beta.fit(x)
  1820. We can also use some prior knowledge about the dataset: let's keep
  1821. ``loc`` and ``scale`` fixed:
  1822. >>> a1, b1, loc1, scale1 = beta.fit(x, floc=0, fscale=1)
  1823. >>> loc1, scale1
  1824. (0, 1)
  1825. We can also keep shape parameters fixed by using ``f``-keywords. To
  1826. keep the zero-th shape parameter ``a`` equal 1, use ``f0=1`` or,
  1827. equivalently, ``fa=1``:
  1828. >>> a1, b1, loc1, scale1 = beta.fit(x, fa=1, floc=0, fscale=1)
  1829. >>> a1
  1830. 1
  1831. Not all distributions return estimates for the shape parameters.
  1832. ``norm`` for example just returns estimates for location and scale:
  1833. >>> from scipy.stats import norm
  1834. >>> x = norm.rvs(a, b, size=1000, random_state=123)
  1835. >>> loc1, scale1 = norm.fit(x)
  1836. >>> loc1, scale1
  1837. (0.92087172783841631, 2.0015750750324668)
  1838. """
  1839. Narg = len(args)
  1840. if Narg > self.numargs:
  1841. raise TypeError("Too many input arguments.")
  1842. start = [None]*2
  1843. if (Narg < self.numargs) or not ('loc' in kwds and
  1844. 'scale' in kwds):
  1845. # get distribution specific starting locations
  1846. start = self._fitstart(data)
  1847. args += start[Narg:-2]
  1848. loc = kwds.pop('loc', start[-2])
  1849. scale = kwds.pop('scale', start[-1])
  1850. args += (loc, scale)
  1851. x0, func, restore, args = self._reduce_func(args, kwds)
  1852. optimizer = kwds.pop('optimizer', optimize.fmin)
  1853. # convert string to function in scipy.optimize
  1854. if not callable(optimizer) and isinstance(optimizer, string_types):
  1855. if not optimizer.startswith('fmin_'):
  1856. optimizer = "fmin_"+optimizer
  1857. if optimizer == 'fmin_':
  1858. optimizer = 'fmin'
  1859. try:
  1860. optimizer = getattr(optimize, optimizer)
  1861. except AttributeError:
  1862. raise ValueError("%s is not a valid optimizer" % optimizer)
  1863. # by now kwds must be empty, since everybody took what they needed
  1864. if kwds:
  1865. raise TypeError("Unknown arguments: %s." % kwds)
  1866. vals = optimizer(func, x0, args=(ravel(data),), disp=0)
  1867. if restore is not None:
  1868. vals = restore(args, vals)
  1869. vals = tuple(vals)
  1870. return vals
  1871. def _fit_loc_scale_support(self, data, *args):
  1872. """
  1873. Estimate loc and scale parameters from data accounting for support.
  1874. Parameters
  1875. ----------
  1876. data : array_like
  1877. Data to fit.
  1878. arg1, arg2, arg3,... : array_like
  1879. The shape parameter(s) for the distribution (see docstring of the
  1880. instance object for more information).
  1881. Returns
  1882. -------
  1883. Lhat : float
  1884. Estimated location parameter for the data.
  1885. Shat : float
  1886. Estimated scale parameter for the data.
  1887. """
  1888. data = np.asarray(data)
  1889. # Estimate location and scale according to the method of moments.
  1890. loc_hat, scale_hat = self.fit_loc_scale(data, *args)
  1891. # Compute the support according to the shape parameters.
  1892. self._argcheck(*args)
  1893. a, b = self.a, self.b
  1894. support_width = b - a
  1895. # If the support is empty then return the moment-based estimates.
  1896. if support_width <= 0:
  1897. return loc_hat, scale_hat
  1898. # Compute the proposed support according to the loc and scale
  1899. # estimates.
  1900. a_hat = loc_hat + a * scale_hat
  1901. b_hat = loc_hat + b * scale_hat
  1902. # Use the moment-based estimates if they are compatible with the data.
  1903. data_a = np.min(data)
  1904. data_b = np.max(data)
  1905. if a_hat < data_a and data_b < b_hat:
  1906. return loc_hat, scale_hat
  1907. # Otherwise find other estimates that are compatible with the data.
  1908. data_width = data_b - data_a
  1909. rel_margin = 0.1
  1910. margin = data_width * rel_margin
  1911. # For a finite interval, both the location and scale
  1912. # should have interesting values.
  1913. if support_width < np.inf:
  1914. loc_hat = (data_a - a) - margin
  1915. scale_hat = (data_width + 2 * margin) / support_width
  1916. return loc_hat, scale_hat
  1917. # For a one-sided interval, use only an interesting location parameter.
  1918. if a > -np.inf:
  1919. return (data_a - a) - margin, 1
  1920. elif b < np.inf:
  1921. return (data_b - b) + margin, 1
  1922. else:
  1923. raise RuntimeError
  1924. def fit_loc_scale(self, data, *args):
  1925. """
  1926. Estimate loc and scale parameters from data using 1st and 2nd moments.
  1927. Parameters
  1928. ----------
  1929. data : array_like
  1930. Data to fit.
  1931. arg1, arg2, arg3,... : array_like
  1932. The shape parameter(s) for the distribution (see docstring of the
  1933. instance object for more information).
  1934. Returns
  1935. -------
  1936. Lhat : float
  1937. Estimated location parameter for the data.
  1938. Shat : float
  1939. Estimated scale parameter for the data.
  1940. """
  1941. mu, mu2 = self.stats(*args, **{'moments': 'mv'})
  1942. tmp = asarray(data)
  1943. muhat = tmp.mean()
  1944. mu2hat = tmp.var()
  1945. Shat = sqrt(mu2hat / mu2)
  1946. Lhat = muhat - Shat*mu
  1947. if not np.isfinite(Lhat):
  1948. Lhat = 0
  1949. if not (np.isfinite(Shat) and (0 < Shat)):
  1950. Shat = 1
  1951. return Lhat, Shat
  1952. def _entropy(self, *args):
  1953. def integ(x):
  1954. val = self._pdf(x, *args)
  1955. return entr(val)
  1956. # upper limit is often inf, so suppress warnings when integrating
  1957. olderr = np.seterr(over='ignore')
  1958. h = integrate.quad(integ, self.a, self.b)[0]
  1959. np.seterr(**olderr)
  1960. if not np.isnan(h):
  1961. return h
  1962. else:
  1963. # try with different limits if integration problems
  1964. low, upp = self.ppf([1e-10, 1. - 1e-10], *args)
  1965. if np.isinf(self.b):
  1966. upper = upp
  1967. else:
  1968. upper = self.b
  1969. if np.isinf(self.a):
  1970. lower = low
  1971. else:
  1972. lower = self.a
  1973. return integrate.quad(integ, lower, upper)[0]
  1974. def expect(self, func=None, args=(), loc=0, scale=1, lb=None, ub=None,
  1975. conditional=False, **kwds):
  1976. """Calculate expected value of a function with respect to the
  1977. distribution by numerical integration.
  1978. The expected value of a function ``f(x)`` with respect to a
  1979. distribution ``dist`` is defined as::
  1980. ub
  1981. E[f(x)] = Integral(f(x) * dist.pdf(x)),
  1982. lb
  1983. where ``ub`` and ``lb`` are arguments and ``x`` has the ``dist.pdf(x)``
  1984. distribution. If the bounds ``lb`` and ``ub`` correspond to the
  1985. support of the distribution, e.g. ``[-inf, inf]`` in the default
  1986. case, then the integral is the unrestricted expectation of ``f(x)``.
  1987. Also, the function ``f(x)`` may be defined such that ``f(x)`` is ``0``
  1988. outside a finite interval in which case the expectation is
  1989. calculated within the finite range ``[lb, ub]``.
  1990. Parameters
  1991. ----------
  1992. func : callable, optional
  1993. Function for which integral is calculated. Takes only one argument.
  1994. The default is the identity mapping f(x) = x.
  1995. args : tuple, optional
  1996. Shape parameters of the distribution.
  1997. loc : float, optional
  1998. Location parameter (default=0).
  1999. scale : float, optional
  2000. Scale parameter (default=1).
  2001. lb, ub : scalar, optional
  2002. Lower and upper bound for integration. Default is set to the
  2003. support of the distribution.
  2004. conditional : bool, optional
  2005. If True, the integral is corrected by the conditional probability
  2006. of the integration interval. The return value is the expectation
  2007. of the function, conditional on being in the given interval.
  2008. Default is False.
  2009. Additional keyword arguments are passed to the integration routine.
  2010. Returns
  2011. -------
  2012. expect : float
  2013. The calculated expected value.
  2014. Notes
  2015. -----
  2016. The integration behavior of this function is inherited from
  2017. `scipy.integrate.quad`. Neither this function nor
  2018. `scipy.integrate.quad` can verify whether the integral exists or is
  2019. finite. For example ``cauchy(0).mean()`` returns ``np.nan`` and
  2020. ``cauchy(0).expect()`` returns ``0.0``.
  2021. Examples
  2022. --------
  2023. To understand the effect of the bounds of integration consider
  2024. >>> from scipy.stats import expon
  2025. >>> expon(1).expect(lambda x: 1, lb=0.0, ub=2.0)
  2026. 0.6321205588285578
  2027. This is close to
  2028. >>> expon(1).cdf(2.0) - expon(1).cdf(0.0)
  2029. 0.6321205588285577
  2030. If ``conditional=True``
  2031. >>> expon(1).expect(lambda x: 1, lb=0.0, ub=2.0, conditional=True)
  2032. 1.0000000000000002
  2033. The slight deviation from 1 is due to numerical integration.
  2034. """
  2035. lockwds = {'loc': loc,
  2036. 'scale': scale}
  2037. self._argcheck(*args)
  2038. if func is None:
  2039. def fun(x, *args):
  2040. return x * self.pdf(x, *args, **lockwds)
  2041. else:
  2042. def fun(x, *args):
  2043. return func(x) * self.pdf(x, *args, **lockwds)
  2044. if lb is None:
  2045. lb = loc + self.a * scale
  2046. if ub is None:
  2047. ub = loc + self.b * scale
  2048. if conditional:
  2049. invfac = (self.sf(lb, *args, **lockwds)
  2050. - self.sf(ub, *args, **lockwds))
  2051. else:
  2052. invfac = 1.0
  2053. kwds['args'] = args
  2054. # Silence floating point warnings from integration.
  2055. olderr = np.seterr(all='ignore')
  2056. vals = integrate.quad(fun, lb, ub, **kwds)[0] / invfac
  2057. np.seterr(**olderr)
  2058. return vals
  2059. # Helpers for the discrete distributions
  2060. def _drv2_moment(self, n, *args):
  2061. """Non-central moment of discrete distribution."""
  2062. def fun(x):
  2063. return np.power(x, n) * self._pmf(x, *args)
  2064. return _expect(fun, self.a, self.b, self.ppf(0.5, *args), self.inc)
  2065. def _drv2_ppfsingle(self, q, *args): # Use basic bisection algorithm
  2066. b = self.b
  2067. a = self.a
  2068. if isinf(b): # Be sure ending point is > q
  2069. b = int(max(100*q, 10))
  2070. while 1:
  2071. if b >= self.b:
  2072. qb = 1.0
  2073. break
  2074. qb = self._cdf(b, *args)
  2075. if (qb < q):
  2076. b += 10
  2077. else:
  2078. break
  2079. else:
  2080. qb = 1.0
  2081. if isinf(a): # be sure starting point < q
  2082. a = int(min(-100*q, -10))
  2083. while 1:
  2084. if a <= self.a:
  2085. qb = 0.0
  2086. break
  2087. qa = self._cdf(a, *args)
  2088. if (qa > q):
  2089. a -= 10
  2090. else:
  2091. break
  2092. else:
  2093. qa = self._cdf(a, *args)
  2094. while 1:
  2095. if (qa == q):
  2096. return a
  2097. if (qb == q):
  2098. return b
  2099. if b <= a+1:
  2100. if qa > q:
  2101. return a
  2102. else:
  2103. return b
  2104. c = int((a+b)/2.0)
  2105. qc = self._cdf(c, *args)
  2106. if (qc < q):
  2107. if a != c:
  2108. a = c
  2109. else:
  2110. raise RuntimeError('updating stopped, endless loop')
  2111. qa = qc
  2112. elif (qc > q):
  2113. if b != c:
  2114. b = c
  2115. else:
  2116. raise RuntimeError('updating stopped, endless loop')
  2117. qb = qc
  2118. else:
  2119. return c
  2120. def entropy(pk, qk=None, base=None):
  2121. """Calculate the entropy of a distribution for given probability values.
  2122. If only probabilities `pk` are given, the entropy is calculated as
  2123. ``S = -sum(pk * log(pk), axis=0)``.
  2124. If `qk` is not None, then compute the Kullback-Leibler divergence
  2125. ``S = sum(pk * log(pk / qk), axis=0)``.
  2126. This routine will normalize `pk` and `qk` if they don't sum to 1.
  2127. Parameters
  2128. ----------
  2129. pk : sequence
  2130. Defines the (discrete) distribution. ``pk[i]`` is the (possibly
  2131. unnormalized) probability of event ``i``.
  2132. qk : sequence, optional
  2133. Sequence against which the relative entropy is computed. Should be in
  2134. the same format as `pk`.
  2135. base : float, optional
  2136. The logarithmic base to use, defaults to ``e`` (natural logarithm).
  2137. Returns
  2138. -------
  2139. S : float
  2140. The calculated entropy.
  2141. """
  2142. pk = asarray(pk)
  2143. pk = 1.0*pk / np.sum(pk, axis=0)
  2144. if qk is None:
  2145. vec = entr(pk)
  2146. else:
  2147. qk = asarray(qk)
  2148. if len(qk) != len(pk):
  2149. raise ValueError("qk and pk must have same length.")
  2150. qk = 1.0*qk / np.sum(qk, axis=0)
  2151. vec = rel_entr(pk, qk)
  2152. S = np.sum(vec, axis=0)
  2153. if base is not None:
  2154. S /= log(base)
  2155. return S
  2156. # Must over-ride one of _pmf or _cdf or pass in
  2157. # x_k, p(x_k) lists in initialization
  2158. class rv_discrete(rv_generic):
  2159. """
  2160. A generic discrete random variable class meant for subclassing.
  2161. `rv_discrete` is a base class to construct specific distribution classes
  2162. and instances for discrete random variables. It can also be used
  2163. to construct an arbitrary distribution defined by a list of support
  2164. points and corresponding probabilities.
  2165. Parameters
  2166. ----------
  2167. a : float, optional
  2168. Lower bound of the support of the distribution, default: 0
  2169. b : float, optional
  2170. Upper bound of the support of the distribution, default: plus infinity
  2171. moment_tol : float, optional
  2172. The tolerance for the generic calculation of moments.
  2173. values : tuple of two array_like, optional
  2174. ``(xk, pk)`` where ``xk`` are integers with non-zero
  2175. probabilities ``pk`` with ``sum(pk) = 1``.
  2176. inc : integer, optional
  2177. Increment for the support of the distribution.
  2178. Default is 1. (other values have not been tested)
  2179. badvalue : float, optional
  2180. The value in a result arrays that indicates a value that for which
  2181. some argument restriction is violated, default is np.nan.
  2182. name : str, optional
  2183. The name of the instance. This string is used to construct the default
  2184. example for distributions.
  2185. longname : str, optional
  2186. This string is used as part of the first line of the docstring returned
  2187. when a subclass has no docstring of its own. Note: `longname` exists
  2188. for backwards compatibility, do not use for new subclasses.
  2189. shapes : str, optional
  2190. The shape of the distribution. For example "m, n" for a distribution
  2191. that takes two integers as the two shape arguments for all its methods
  2192. If not provided, shape parameters will be inferred from
  2193. the signatures of the private methods, ``_pmf`` and ``_cdf`` of
  2194. the instance.
  2195. extradoc : str, optional
  2196. This string is used as the last part of the docstring returned when a
  2197. subclass has no docstring of its own. Note: `extradoc` exists for
  2198. backwards compatibility, do not use for new subclasses.
  2199. seed : None or int or ``numpy.random.RandomState`` instance, optional
  2200. This parameter defines the RandomState object to use for drawing
  2201. random variates.
  2202. If None, the global np.random state is used.
  2203. If integer, it is used to seed the local RandomState instance.
  2204. Default is None.
  2205. Methods
  2206. -------
  2207. rvs
  2208. pmf
  2209. logpmf
  2210. cdf
  2211. logcdf
  2212. sf
  2213. logsf
  2214. ppf
  2215. isf
  2216. moment
  2217. stats
  2218. entropy
  2219. expect
  2220. median
  2221. mean
  2222. std
  2223. var
  2224. interval
  2225. __call__
  2226. Notes
  2227. -----
  2228. This class is similar to `rv_continuous`. Whether a shape parameter is
  2229. valid is decided by an ``_argcheck`` method (which defaults to checking
  2230. that its arguments are strictly positive.)
  2231. The main differences are:
  2232. - the support of the distribution is a set of integers
  2233. - instead of the probability density function, ``pdf`` (and the
  2234. corresponding private ``_pdf``), this class defines the
  2235. *probability mass function*, `pmf` (and the corresponding
  2236. private ``_pmf``.)
  2237. - scale parameter is not defined.
  2238. To create a new discrete distribution, we would do the following:
  2239. >>> from scipy.stats import rv_discrete
  2240. >>> class poisson_gen(rv_discrete):
  2241. ... "Poisson distribution"
  2242. ... def _pmf(self, k, mu):
  2243. ... return exp(-mu) * mu**k / factorial(k)
  2244. and create an instance::
  2245. >>> poisson = poisson_gen(name="poisson")
  2246. Note that above we defined the Poisson distribution in the standard form.
  2247. Shifting the distribution can be done by providing the ``loc`` parameter
  2248. to the methods of the instance. For example, ``poisson.pmf(x, mu, loc)``
  2249. delegates the work to ``poisson._pmf(x-loc, mu)``.
  2250. **Discrete distributions from a list of probabilities**
  2251. Alternatively, you can construct an arbitrary discrete rv defined
  2252. on a finite set of values ``xk`` with ``Prob{X=xk} = pk`` by using the
  2253. ``values`` keyword argument to the `rv_discrete` constructor.
  2254. Examples
  2255. --------
  2256. Custom made discrete distribution:
  2257. >>> from scipy import stats
  2258. >>> xk = np.arange(7)
  2259. >>> pk = (0.1, 0.2, 0.3, 0.1, 0.1, 0.0, 0.2)
  2260. >>> custm = stats.rv_discrete(name='custm', values=(xk, pk))
  2261. >>>
  2262. >>> import matplotlib.pyplot as plt
  2263. >>> fig, ax = plt.subplots(1, 1)
  2264. >>> ax.plot(xk, custm.pmf(xk), 'ro', ms=12, mec='r')
  2265. >>> ax.vlines(xk, 0, custm.pmf(xk), colors='r', lw=4)
  2266. >>> plt.show()
  2267. Random number generation:
  2268. >>> R = custm.rvs(size=100)
  2269. """
  2270. def __new__(cls, a=0, b=inf, name=None, badvalue=None,
  2271. moment_tol=1e-8, values=None, inc=1, longname=None,
  2272. shapes=None, extradoc=None, seed=None):
  2273. if values is not None:
  2274. # dispatch to a subclass
  2275. return super(rv_discrete, cls).__new__(rv_sample)
  2276. else:
  2277. # business as usual
  2278. return super(rv_discrete, cls).__new__(cls)
  2279. def __init__(self, a=0, b=inf, name=None, badvalue=None,
  2280. moment_tol=1e-8, values=None, inc=1, longname=None,
  2281. shapes=None, extradoc=None, seed=None):
  2282. super(rv_discrete, self).__init__(seed)
  2283. # cf generic freeze
  2284. self._ctor_param = dict(
  2285. a=a, b=b, name=name, badvalue=badvalue,
  2286. moment_tol=moment_tol, values=values, inc=inc,
  2287. longname=longname, shapes=shapes, extradoc=extradoc, seed=seed)
  2288. if badvalue is None:
  2289. badvalue = nan
  2290. self.badvalue = badvalue
  2291. self.a = a
  2292. self.b = b
  2293. self.moment_tol = moment_tol
  2294. self.inc = inc
  2295. self._cdfvec = vectorize(self._cdf_single, otypes='d')
  2296. self.vecentropy = vectorize(self._entropy)
  2297. self.shapes = shapes
  2298. if values is not None:
  2299. raise ValueError("rv_discrete.__init__(..., values != None, ...)")
  2300. self._construct_argparser(meths_to_inspect=[self._pmf, self._cdf],
  2301. locscale_in='loc=0',
  2302. # scale=1 for discrete RVs
  2303. locscale_out='loc, 1')
  2304. # nin correction needs to be after we know numargs
  2305. # correct nin for generic moment vectorization
  2306. _vec_generic_moment = vectorize(_drv2_moment, otypes='d')
  2307. _vec_generic_moment.nin = self.numargs + 2
  2308. self.generic_moment = instancemethod(_vec_generic_moment,
  2309. self, rv_discrete)
  2310. # correct nin for ppf vectorization
  2311. _vppf = vectorize(_drv2_ppfsingle, otypes='d')
  2312. _vppf.nin = self.numargs + 2
  2313. self._ppfvec = instancemethod(_vppf,
  2314. self, rv_discrete)
  2315. # now that self.numargs is defined, we can adjust nin
  2316. self._cdfvec.nin = self.numargs + 1
  2317. self._construct_docstrings(name, longname, extradoc)
  2318. def _construct_docstrings(self, name, longname, extradoc):
  2319. if name is None:
  2320. name = 'Distribution'
  2321. self.name = name
  2322. self.extradoc = extradoc
  2323. # generate docstring for subclass instances
  2324. if longname is None:
  2325. if name[0] in ['aeiouAEIOU']:
  2326. hstr = "An "
  2327. else:
  2328. hstr = "A "
  2329. longname = hstr + name
  2330. if sys.flags.optimize < 2:
  2331. # Skip adding docstrings if interpreter is run with -OO
  2332. if self.__doc__ is None:
  2333. self._construct_default_doc(longname=longname,
  2334. extradoc=extradoc,
  2335. docdict=docdict_discrete,
  2336. discrete='discrete')
  2337. else:
  2338. dct = dict(distdiscrete)
  2339. self._construct_doc(docdict_discrete, dct.get(self.name))
  2340. # discrete RV do not have the scale parameter, remove it
  2341. self.__doc__ = self.__doc__.replace(
  2342. '\n scale : array_like, '
  2343. 'optional\n scale parameter (default=1)', '')
  2344. def _updated_ctor_param(self):
  2345. """ Return the current version of _ctor_param, possibly updated by user.
  2346. Used by freezing and pickling.
  2347. Keep this in sync with the signature of __init__.
  2348. """
  2349. dct = self._ctor_param.copy()
  2350. dct['a'] = self.a
  2351. dct['b'] = self.b
  2352. dct['badvalue'] = self.badvalue
  2353. dct['moment_tol'] = self.moment_tol
  2354. dct['inc'] = self.inc
  2355. dct['name'] = self.name
  2356. dct['shapes'] = self.shapes
  2357. dct['extradoc'] = self.extradoc
  2358. return dct
  2359. def _nonzero(self, k, *args):
  2360. return floor(k) == k
  2361. def _pmf(self, k, *args):
  2362. return self._cdf(k, *args) - self._cdf(k-1, *args)
  2363. def _logpmf(self, k, *args):
  2364. return log(self._pmf(k, *args))
  2365. def _cdf_single(self, k, *args):
  2366. m = arange(int(self.a), k+1)
  2367. return np.sum(self._pmf(m, *args), axis=0)
  2368. def _cdf(self, x, *args):
  2369. k = floor(x)
  2370. return self._cdfvec(k, *args)
  2371. # generic _logcdf, _sf, _logsf, _ppf, _isf, _rvs defined in rv_generic
  2372. def rvs(self, *args, **kwargs):
  2373. """
  2374. Random variates of given type.
  2375. Parameters
  2376. ----------
  2377. arg1, arg2, arg3,... : array_like
  2378. The shape parameter(s) for the distribution (see docstring of the
  2379. instance object for more information).
  2380. loc : array_like, optional
  2381. Location parameter (default=0).
  2382. size : int or tuple of ints, optional
  2383. Defining number of random variates (Default is 1). Note that `size`
  2384. has to be given as keyword, not as positional argument.
  2385. random_state : None or int or ``np.random.RandomState`` instance, optional
  2386. If int or RandomState, use it for drawing the random variates.
  2387. If None, rely on ``self.random_state``.
  2388. Default is None.
  2389. Returns
  2390. -------
  2391. rvs : ndarray or scalar
  2392. Random variates of given `size`.
  2393. """
  2394. kwargs['discrete'] = True
  2395. return super(rv_discrete, self).rvs(*args, **kwargs)
  2396. def pmf(self, k, *args, **kwds):
  2397. """
  2398. Probability mass function at k of the given RV.
  2399. Parameters
  2400. ----------
  2401. k : array_like
  2402. Quantiles.
  2403. arg1, arg2, arg3,... : array_like
  2404. The shape parameter(s) for the distribution (see docstring of the
  2405. instance object for more information)
  2406. loc : array_like, optional
  2407. Location parameter (default=0).
  2408. Returns
  2409. -------
  2410. pmf : array_like
  2411. Probability mass function evaluated at k
  2412. """
  2413. args, loc, _ = self._parse_args(*args, **kwds)
  2414. k, loc = map(asarray, (k, loc))
  2415. args = tuple(map(asarray, args))
  2416. k = asarray((k-loc))
  2417. cond0 = self._argcheck(*args)
  2418. cond1 = (k >= self.a) & (k <= self.b) & self._nonzero(k, *args)
  2419. cond = cond0 & cond1
  2420. output = zeros(shape(cond), 'd')
  2421. place(output, (1-cond0) + np.isnan(k), self.badvalue)
  2422. if np.any(cond):
  2423. goodargs = argsreduce(cond, *((k,)+args))
  2424. place(output, cond, np.clip(self._pmf(*goodargs), 0, 1))
  2425. if output.ndim == 0:
  2426. return output[()]
  2427. return output
  2428. def logpmf(self, k, *args, **kwds):
  2429. """
  2430. Log of the probability mass function at k of the given RV.
  2431. Parameters
  2432. ----------
  2433. k : array_like
  2434. Quantiles.
  2435. arg1, arg2, arg3,... : array_like
  2436. The shape parameter(s) for the distribution (see docstring of the
  2437. instance object for more information).
  2438. loc : array_like, optional
  2439. Location parameter. Default is 0.
  2440. Returns
  2441. -------
  2442. logpmf : array_like
  2443. Log of the probability mass function evaluated at k.
  2444. """
  2445. args, loc, _ = self._parse_args(*args, **kwds)
  2446. k, loc = map(asarray, (k, loc))
  2447. args = tuple(map(asarray, args))
  2448. k = asarray((k-loc))
  2449. cond0 = self._argcheck(*args)
  2450. cond1 = (k >= self.a) & (k <= self.b) & self._nonzero(k, *args)
  2451. cond = cond0 & cond1
  2452. output = empty(shape(cond), 'd')
  2453. output.fill(NINF)
  2454. place(output, (1-cond0) + np.isnan(k), self.badvalue)
  2455. if np.any(cond):
  2456. goodargs = argsreduce(cond, *((k,)+args))
  2457. place(output, cond, self._logpmf(*goodargs))
  2458. if output.ndim == 0:
  2459. return output[()]
  2460. return output
  2461. def cdf(self, k, *args, **kwds):
  2462. """
  2463. Cumulative distribution function of the given RV.
  2464. Parameters
  2465. ----------
  2466. k : array_like, int
  2467. Quantiles.
  2468. arg1, arg2, arg3,... : array_like
  2469. The shape parameter(s) for the distribution (see docstring of the
  2470. instance object for more information).
  2471. loc : array_like, optional
  2472. Location parameter (default=0).
  2473. Returns
  2474. -------
  2475. cdf : ndarray
  2476. Cumulative distribution function evaluated at `k`.
  2477. """
  2478. args, loc, _ = self._parse_args(*args, **kwds)
  2479. k, loc = map(asarray, (k, loc))
  2480. args = tuple(map(asarray, args))
  2481. k = asarray((k-loc))
  2482. cond0 = self._argcheck(*args)
  2483. cond1 = (k >= self.a) & (k < self.b)
  2484. cond2 = (k >= self.b)
  2485. cond = cond0 & cond1
  2486. output = zeros(shape(cond), 'd')
  2487. place(output, (1-cond0) + np.isnan(k), self.badvalue)
  2488. place(output, cond2*(cond0 == cond0), 1.0)
  2489. if np.any(cond):
  2490. goodargs = argsreduce(cond, *((k,)+args))
  2491. place(output, cond, np.clip(self._cdf(*goodargs), 0, 1))
  2492. if output.ndim == 0:
  2493. return output[()]
  2494. return output
  2495. def logcdf(self, k, *args, **kwds):
  2496. """
  2497. Log of the cumulative distribution function at k of the given RV.
  2498. Parameters
  2499. ----------
  2500. k : array_like, int
  2501. Quantiles.
  2502. arg1, arg2, arg3,... : array_like
  2503. The shape parameter(s) for the distribution (see docstring of the
  2504. instance object for more information).
  2505. loc : array_like, optional
  2506. Location parameter (default=0).
  2507. Returns
  2508. -------
  2509. logcdf : array_like
  2510. Log of the cumulative distribution function evaluated at k.
  2511. """
  2512. args, loc, _ = self._parse_args(*args, **kwds)
  2513. k, loc = map(asarray, (k, loc))
  2514. args = tuple(map(asarray, args))
  2515. k = asarray((k-loc))
  2516. cond0 = self._argcheck(*args)
  2517. cond1 = (k >= self.a) & (k < self.b)
  2518. cond2 = (k >= self.b)
  2519. cond = cond0 & cond1
  2520. output = empty(shape(cond), 'd')
  2521. output.fill(NINF)
  2522. place(output, (1-cond0) + np.isnan(k), self.badvalue)
  2523. place(output, cond2*(cond0 == cond0), 0.0)
  2524. if np.any(cond):
  2525. goodargs = argsreduce(cond, *((k,)+args))
  2526. place(output, cond, self._logcdf(*goodargs))
  2527. if output.ndim == 0:
  2528. return output[()]
  2529. return output
  2530. def sf(self, k, *args, **kwds):
  2531. """
  2532. Survival function (1 - `cdf`) at k of the given RV.
  2533. Parameters
  2534. ----------
  2535. k : array_like
  2536. Quantiles.
  2537. arg1, arg2, arg3,... : array_like
  2538. The shape parameter(s) for the distribution (see docstring of the
  2539. instance object for more information).
  2540. loc : array_like, optional
  2541. Location parameter (default=0).
  2542. Returns
  2543. -------
  2544. sf : array_like
  2545. Survival function evaluated at k.
  2546. """
  2547. args, loc, _ = self._parse_args(*args, **kwds)
  2548. k, loc = map(asarray, (k, loc))
  2549. args = tuple(map(asarray, args))
  2550. k = asarray(k-loc)
  2551. cond0 = self._argcheck(*args)
  2552. cond1 = (k >= self.a) & (k < self.b)
  2553. cond2 = (k < self.a) & cond0
  2554. cond = cond0 & cond1
  2555. output = zeros(shape(cond), 'd')
  2556. place(output, (1-cond0) + np.isnan(k), self.badvalue)
  2557. place(output, cond2, 1.0)
  2558. if np.any(cond):
  2559. goodargs = argsreduce(cond, *((k,)+args))
  2560. place(output, cond, np.clip(self._sf(*goodargs), 0, 1))
  2561. if output.ndim == 0:
  2562. return output[()]
  2563. return output
  2564. def logsf(self, k, *args, **kwds):
  2565. """
  2566. Log of the survival function of the given RV.
  2567. Returns the log of the "survival function," defined as 1 - `cdf`,
  2568. evaluated at `k`.
  2569. Parameters
  2570. ----------
  2571. k : array_like
  2572. Quantiles.
  2573. arg1, arg2, arg3,... : array_like
  2574. The shape parameter(s) for the distribution (see docstring of the
  2575. instance object for more information).
  2576. loc : array_like, optional
  2577. Location parameter (default=0).
  2578. Returns
  2579. -------
  2580. logsf : ndarray
  2581. Log of the survival function evaluated at `k`.
  2582. """
  2583. args, loc, _ = self._parse_args(*args, **kwds)
  2584. k, loc = map(asarray, (k, loc))
  2585. args = tuple(map(asarray, args))
  2586. k = asarray(k-loc)
  2587. cond0 = self._argcheck(*args)
  2588. cond1 = (k >= self.a) & (k < self.b)
  2589. cond2 = (k < self.a) & cond0
  2590. cond = cond0 & cond1
  2591. output = empty(shape(cond), 'd')
  2592. output.fill(NINF)
  2593. place(output, (1-cond0) + np.isnan(k), self.badvalue)
  2594. place(output, cond2, 0.0)
  2595. if np.any(cond):
  2596. goodargs = argsreduce(cond, *((k,)+args))
  2597. place(output, cond, self._logsf(*goodargs))
  2598. if output.ndim == 0:
  2599. return output[()]
  2600. return output
  2601. def ppf(self, q, *args, **kwds):
  2602. """
  2603. Percent point function (inverse of `cdf`) at q of the given RV.
  2604. Parameters
  2605. ----------
  2606. q : array_like
  2607. Lower tail probability.
  2608. arg1, arg2, arg3,... : array_like
  2609. The shape parameter(s) for the distribution (see docstring of the
  2610. instance object for more information).
  2611. loc : array_like, optional
  2612. Location parameter (default=0).
  2613. Returns
  2614. -------
  2615. k : array_like
  2616. Quantile corresponding to the lower tail probability, q.
  2617. """
  2618. args, loc, _ = self._parse_args(*args, **kwds)
  2619. q, loc = map(asarray, (q, loc))
  2620. args = tuple(map(asarray, args))
  2621. cond0 = self._argcheck(*args) & (loc == loc)
  2622. cond1 = (q > 0) & (q < 1)
  2623. cond2 = (q == 1) & cond0
  2624. cond = cond0 & cond1
  2625. output = valarray(shape(cond), value=self.badvalue, typecode='d')
  2626. # output type 'd' to handle nin and inf
  2627. place(output, (q == 0)*(cond == cond), self.a-1)
  2628. place(output, cond2, self.b)
  2629. if np.any(cond):
  2630. goodargs = argsreduce(cond, *((q,)+args+(loc,)))
  2631. loc, goodargs = goodargs[-1], goodargs[:-1]
  2632. place(output, cond, self._ppf(*goodargs) + loc)
  2633. if output.ndim == 0:
  2634. return output[()]
  2635. return output
  2636. def isf(self, q, *args, **kwds):
  2637. """
  2638. Inverse survival function (inverse of `sf`) at q of the given RV.
  2639. Parameters
  2640. ----------
  2641. q : array_like
  2642. Upper tail probability.
  2643. arg1, arg2, arg3,... : array_like
  2644. The shape parameter(s) for the distribution (see docstring of the
  2645. instance object for more information).
  2646. loc : array_like, optional
  2647. Location parameter (default=0).
  2648. Returns
  2649. -------
  2650. k : ndarray or scalar
  2651. Quantile corresponding to the upper tail probability, q.
  2652. """
  2653. args, loc, _ = self._parse_args(*args, **kwds)
  2654. q, loc = map(asarray, (q, loc))
  2655. args = tuple(map(asarray, args))
  2656. cond0 = self._argcheck(*args) & (loc == loc)
  2657. cond1 = (q > 0) & (q < 1)
  2658. cond2 = (q == 1) & cond0
  2659. cond = cond0 & cond1
  2660. # same problem as with ppf; copied from ppf and changed
  2661. output = valarray(shape(cond), value=self.badvalue, typecode='d')
  2662. # output type 'd' to handle nin and inf
  2663. place(output, (q == 0)*(cond == cond), self.b)
  2664. place(output, cond2, self.a-1)
  2665. # call place only if at least 1 valid argument
  2666. if np.any(cond):
  2667. goodargs = argsreduce(cond, *((q,)+args+(loc,)))
  2668. loc, goodargs = goodargs[-1], goodargs[:-1]
  2669. # PB same as ticket 766
  2670. place(output, cond, self._isf(*goodargs) + loc)
  2671. if output.ndim == 0:
  2672. return output[()]
  2673. return output
  2674. def _entropy(self, *args):
  2675. if hasattr(self, 'pk'):
  2676. return entropy(self.pk)
  2677. else:
  2678. return _expect(lambda x: entr(self.pmf(x, *args)),
  2679. self.a, self.b, self.ppf(0.5, *args), self.inc)
  2680. def expect(self, func=None, args=(), loc=0, lb=None, ub=None,
  2681. conditional=False, maxcount=1000, tolerance=1e-10, chunksize=32):
  2682. """
  2683. Calculate expected value of a function with respect to the distribution
  2684. for discrete distribution by numerical summation.
  2685. Parameters
  2686. ----------
  2687. func : callable, optional
  2688. Function for which the expectation value is calculated.
  2689. Takes only one argument.
  2690. The default is the identity mapping f(k) = k.
  2691. args : tuple, optional
  2692. Shape parameters of the distribution.
  2693. loc : float, optional
  2694. Location parameter.
  2695. Default is 0.
  2696. lb, ub : int, optional
  2697. Lower and upper bound for the summation, default is set to the
  2698. support of the distribution, inclusive (``ul <= k <= ub``).
  2699. conditional : bool, optional
  2700. If true then the expectation is corrected by the conditional
  2701. probability of the summation interval. The return value is the
  2702. expectation of the function, `func`, conditional on being in
  2703. the given interval (k such that ``ul <= k <= ub``).
  2704. Default is False.
  2705. maxcount : int, optional
  2706. Maximal number of terms to evaluate (to avoid an endless loop for
  2707. an infinite sum). Default is 1000.
  2708. tolerance : float, optional
  2709. Absolute tolerance for the summation. Default is 1e-10.
  2710. chunksize : int, optional
  2711. Iterate over the support of a distributions in chunks of this size.
  2712. Default is 32.
  2713. Returns
  2714. -------
  2715. expect : float
  2716. Expected value.
  2717. Notes
  2718. -----
  2719. For heavy-tailed distributions, the expected value may or may not exist,
  2720. depending on the function, `func`. If it does exist, but the sum converges
  2721. slowly, the accuracy of the result may be rather low. For instance, for
  2722. ``zipf(4)``, accuracy for mean, variance in example is only 1e-5.
  2723. increasing `maxcount` and/or `chunksize` may improve the result, but may
  2724. also make zipf very slow.
  2725. The function is not vectorized.
  2726. """
  2727. if func is None:
  2728. def fun(x):
  2729. # loc and args from outer scope
  2730. return (x+loc)*self._pmf(x, *args)
  2731. else:
  2732. def fun(x):
  2733. # loc and args from outer scope
  2734. return func(x+loc)*self._pmf(x, *args)
  2735. # used pmf because _pmf does not check support in randint and there
  2736. # might be problems(?) with correct self.a, self.b at this stage maybe
  2737. # not anymore, seems to work now with _pmf
  2738. self._argcheck(*args) # (re)generate scalar self.a and self.b
  2739. if lb is None:
  2740. lb = self.a
  2741. else:
  2742. lb = lb - loc # convert bound for standardized distribution
  2743. if ub is None:
  2744. ub = self.b
  2745. else:
  2746. ub = ub - loc # convert bound for standardized distribution
  2747. if conditional:
  2748. invfac = self.sf(lb-1, *args) - self.sf(ub, *args)
  2749. else:
  2750. invfac = 1.0
  2751. # iterate over the support, starting from the median
  2752. x0 = self.ppf(0.5, *args)
  2753. res = _expect(fun, lb, ub, x0, self.inc, maxcount, tolerance, chunksize)
  2754. return res / invfac
  2755. def _expect(fun, lb, ub, x0, inc, maxcount=1000, tolerance=1e-10,
  2756. chunksize=32):
  2757. """Helper for computing the expectation value of `fun`."""
  2758. # short-circuit if the support size is small enough
  2759. if (ub - lb) <= chunksize:
  2760. supp = np.arange(lb, ub+1, inc)
  2761. vals = fun(supp)
  2762. return np.sum(vals)
  2763. # otherwise, iterate starting from x0
  2764. if x0 < lb:
  2765. x0 = lb
  2766. if x0 > ub:
  2767. x0 = ub
  2768. count, tot = 0, 0.
  2769. # iterate over [x0, ub] inclusive
  2770. for x in _iter_chunked(x0, ub+1, chunksize=chunksize, inc=inc):
  2771. count += x.size
  2772. delta = np.sum(fun(x))
  2773. tot += delta
  2774. if abs(delta) < tolerance * x.size:
  2775. break
  2776. if count > maxcount:
  2777. warnings.warn('expect(): sum did not converge', RuntimeWarning)
  2778. return tot
  2779. # iterate over [lb, x0)
  2780. for x in _iter_chunked(x0-1, lb-1, chunksize=chunksize, inc=-inc):
  2781. count += x.size
  2782. delta = np.sum(fun(x))
  2783. tot += delta
  2784. if abs(delta) < tolerance * x.size:
  2785. break
  2786. if count > maxcount:
  2787. warnings.warn('expect(): sum did not converge', RuntimeWarning)
  2788. break
  2789. return tot
  2790. def _iter_chunked(x0, x1, chunksize=4, inc=1):
  2791. """Iterate from x0 to x1 in chunks of chunksize and steps inc.
  2792. x0 must be finite, x1 need not be. In the latter case, the iterator is
  2793. infinite.
  2794. Handles both x0 < x1 and x0 > x1. In the latter case, iterates downwards
  2795. (make sure to set inc < 0.)
  2796. >>> [x for x in _iter_chunked(2, 5, inc=2)]
  2797. [array([2, 4])]
  2798. >>> [x for x in _iter_chunked(2, 11, inc=2)]
  2799. [array([2, 4, 6, 8]), array([10])]
  2800. >>> [x for x in _iter_chunked(2, -5, inc=-2)]
  2801. [array([ 2, 0, -2, -4])]
  2802. >>> [x for x in _iter_chunked(2, -9, inc=-2)]
  2803. [array([ 2, 0, -2, -4]), array([-6, -8])]
  2804. """
  2805. if inc == 0:
  2806. raise ValueError('Cannot increment by zero.')
  2807. if chunksize <= 0:
  2808. raise ValueError('Chunk size must be positive; got %s.' % chunksize)
  2809. s = 1 if inc > 0 else -1
  2810. stepsize = abs(chunksize * inc)
  2811. x = x0
  2812. while (x - x1) * inc < 0:
  2813. delta = min(stepsize, abs(x - x1))
  2814. step = delta * s
  2815. supp = np.arange(x, x + step, inc)
  2816. x += step
  2817. yield supp
  2818. class rv_sample(rv_discrete):
  2819. """A 'sample' discrete distribution defined by the support and values.
  2820. The ctor ignores most of the arguments, only needs the `values` argument.
  2821. """
  2822. def __init__(self, a=0, b=inf, name=None, badvalue=None,
  2823. moment_tol=1e-8, values=None, inc=1, longname=None,
  2824. shapes=None, extradoc=None, seed=None):
  2825. super(rv_discrete, self).__init__(seed)
  2826. if values is None:
  2827. raise ValueError("rv_sample.__init__(..., values=None,...)")
  2828. # cf generic freeze
  2829. self._ctor_param = dict(
  2830. a=a, b=b, name=name, badvalue=badvalue,
  2831. moment_tol=moment_tol, values=values, inc=inc,
  2832. longname=longname, shapes=shapes, extradoc=extradoc, seed=seed)
  2833. if badvalue is None:
  2834. badvalue = nan
  2835. self.badvalue = badvalue
  2836. self.moment_tol = moment_tol
  2837. self.inc = inc
  2838. self.shapes = shapes
  2839. self.vecentropy = self._entropy
  2840. xk, pk = values
  2841. if len(xk) != len(pk):
  2842. raise ValueError("xk and pk need to have the same length.")
  2843. if not np.allclose(np.sum(pk), 1):
  2844. raise ValueError("The sum of provided pk is not 1.")
  2845. indx = np.argsort(np.ravel(xk))
  2846. self.xk = np.take(np.ravel(xk), indx, 0)
  2847. self.pk = np.take(np.ravel(pk), indx, 0)
  2848. self.a = self.xk[0]
  2849. self.b = self.xk[-1]
  2850. self.qvals = np.cumsum(self.pk, axis=0)
  2851. self.shapes = ' ' # bypass inspection
  2852. self._construct_argparser(meths_to_inspect=[self._pmf],
  2853. locscale_in='loc=0',
  2854. # scale=1 for discrete RVs
  2855. locscale_out='loc, 1')
  2856. self._construct_docstrings(name, longname, extradoc)
  2857. def _pmf(self, x):
  2858. return np.select([x == k for k in self.xk],
  2859. [np.broadcast_arrays(p, x)[0] for p in self.pk], 0)
  2860. def _cdf(self, x):
  2861. xx, xxk = np.broadcast_arrays(x[:, None], self.xk)
  2862. indx = np.argmax(xxk > xx, axis=-1) - 1
  2863. return self.qvals[indx]
  2864. def _ppf(self, q):
  2865. qq, sqq = np.broadcast_arrays(q[..., None], self.qvals)
  2866. indx = argmax(sqq >= qq, axis=-1)
  2867. return self.xk[indx]
  2868. def _rvs(self):
  2869. # Need to define it explicitly, otherwise .rvs() with size=None
  2870. # fails due to explicit broadcasting in _ppf
  2871. U = self._random_state.random_sample(self._size)
  2872. if self._size is None:
  2873. U = np.array(U, ndmin=1)
  2874. Y = self._ppf(U)[0]
  2875. else:
  2876. Y = self._ppf(U)
  2877. return Y
  2878. def _entropy(self):
  2879. return entropy(self.pk)
  2880. def generic_moment(self, n):
  2881. n = asarray(n)
  2882. return np.sum(self.xk**n[np.newaxis, ...] * self.pk, axis=0)
  2883. def get_distribution_names(namespace_pairs, rv_base_class):
  2884. """
  2885. Collect names of statistical distributions and their generators.
  2886. Parameters
  2887. ----------
  2888. namespace_pairs : sequence
  2889. A snapshot of (name, value) pairs in the namespace of a module.
  2890. rv_base_class : class
  2891. The base class of random variable generator classes in a module.
  2892. Returns
  2893. -------
  2894. distn_names : list of strings
  2895. Names of the statistical distributions.
  2896. distn_gen_names : list of strings
  2897. Names of the generators of the statistical distributions.
  2898. Note that these are not simply the names of the statistical
  2899. distributions, with a _gen suffix added.
  2900. """
  2901. distn_names = []
  2902. distn_gen_names = []
  2903. for name, value in namespace_pairs:
  2904. if name.startswith('_'):
  2905. continue
  2906. if name.endswith('_gen') and issubclass(value, rv_base_class):
  2907. distn_gen_names.append(name)
  2908. if isinstance(value, rv_base_class):
  2909. distn_names.append(name)
  2910. return distn_names, distn_gen_names