_continuous_distns.py 207 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278
  1. # -*- coding: utf-8 -*-
  2. #
  3. # Author: Travis Oliphant 2002-2011 with contributions from
  4. # SciPy Developers 2004-2011
  5. #
  6. from __future__ import division, print_function, absolute_import
  7. import warnings
  8. import numpy as np
  9. from scipy.misc.doccer import (extend_notes_in_docstring,
  10. replace_notes_in_docstring)
  11. from scipy import optimize
  12. from scipy import integrate
  13. from scipy import interpolate
  14. import scipy.special as sc
  15. import scipy.special._ufuncs as scu
  16. from scipy._lib._numpy_compat import broadcast_to
  17. from scipy._lib._util import _lazyselect, _lazywhere
  18. from . import _stats
  19. from ._tukeylambda_stats import (tukeylambda_variance as _tlvar,
  20. tukeylambda_kurtosis as _tlkurt)
  21. from ._distn_infrastructure import (get_distribution_names, _kurtosis,
  22. _ncx2_cdf, _ncx2_log_pdf, _ncx2_pdf,
  23. rv_continuous, _skew, valarray)
  24. from ._constants import _XMIN, _EULER, _ZETA3, _XMAX, _LOGXMAX
  25. # In numpy 1.12 and above, np.power refuses to raise integers to negative
  26. # powers, and `np.float_power` is a new replacement.
  27. try:
  28. float_power = np.float_power
  29. except AttributeError:
  30. float_power = np.power
  31. ## Kolmogorov-Smirnov one-sided and two-sided test statistics
  32. class ksone_gen(rv_continuous):
  33. r"""General Kolmogorov-Smirnov one-sided test.
  34. This is the distribution of the one-sided Kolmogorov-Smirnov (KS)
  35. statistics :math:`\sqrt{n} D_n^+` and :math:`\sqrt{n} D_n^-`
  36. for a finite sample size ``n`` (the shape parameter).
  37. %(before_notes)s
  38. Notes
  39. -----
  40. :math:`\sqrt{n} D_n^+` and :math:`\sqrt{n} D_n^-` are given by
  41. .. math::
  42. D_n^+ &= \text{sup}_x (F_n(x) - F(x)),\\
  43. D_n^- &= \text{sup}_x (F(x) - F_n(x)),\\
  44. where :math:`F` is a CDF and :math:`F_n` is an empirical CDF. `ksone`
  45. describes the distribution under the null hypothesis of the KS test
  46. that the empirical CDF corresponds to :math:`n` i.i.d. random variates
  47. with CDF :math:`F`.
  48. %(after_notes)s
  49. See Also
  50. --------
  51. kstwobign, kstest
  52. References
  53. ----------
  54. .. [1] Birnbaum, Z. W. and Tingey, F.H. "One-sided confidence contours
  55. for probability distribution functions", The Annals of Mathematical
  56. Statistics, 22(4), pp 592-596 (1951).
  57. %(example)s
  58. """
  59. def _pdf(self, x, n):
  60. return -scu._smirnovp(n, x)
  61. def _cdf(self, x, n):
  62. return scu._smirnovc(n, x)
  63. def _sf(self, x, n):
  64. return sc.smirnov(n, x)
  65. def _ppf(self, q, n):
  66. return scu._smirnovci(n, q)
  67. def _isf(self, q, n):
  68. return sc.smirnovi(n, q)
  69. ksone = ksone_gen(a=0.0, name='ksone')
  70. class kstwobign_gen(rv_continuous):
  71. r"""Kolmogorov-Smirnov two-sided test for large N.
  72. This is the asymptotic distribution of the two-sided Kolmogorov-Smirnov
  73. statistic :math:`\sqrt{n} D_n` that measures the maximum absolute
  74. distance of the theoretical CDF from the empirical CDF (see `kstest`).
  75. %(before_notes)s
  76. Notes
  77. -----
  78. :math:`\sqrt{n} D_n` is given by
  79. .. math::
  80. D_n = \text{sup}_x |F_n(x) - F(x)|
  81. where :math:`F` is a CDF and :math:`F_n` is an empirical CDF. `kstwobign`
  82. describes the asymptotic distribution (i.e. the limit of
  83. :math:`\sqrt{n} D_n`) under the null hypothesis of the KS test that the
  84. empirical CDF corresponds to i.i.d. random variates with CDF :math:`F`.
  85. %(after_notes)s
  86. See Also
  87. --------
  88. ksone, kstest
  89. References
  90. ----------
  91. .. [1] Marsaglia, G. et al. "Evaluating Kolmogorov's distribution",
  92. Journal of Statistical Software, 8(18), 2003.
  93. %(example)s
  94. """
  95. def _pdf(self, x):
  96. return -scu._kolmogp(x)
  97. def _cdf(self, x):
  98. return scu._kolmogc(x)
  99. def _sf(self, x):
  100. return sc.kolmogorov(x)
  101. def _ppf(self, q):
  102. return scu._kolmogci(q)
  103. def _isf(self, q):
  104. return sc.kolmogi(q)
  105. kstwobign = kstwobign_gen(a=0.0, name='kstwobign')
  106. ## Normal distribution
  107. # loc = mu, scale = std
  108. # Keep these implementations out of the class definition so they can be reused
  109. # by other distributions.
  110. _norm_pdf_C = np.sqrt(2*np.pi)
  111. _norm_pdf_logC = np.log(_norm_pdf_C)
  112. def _norm_pdf(x):
  113. return np.exp(-x**2/2.0) / _norm_pdf_C
  114. def _norm_logpdf(x):
  115. return -x**2 / 2.0 - _norm_pdf_logC
  116. def _norm_cdf(x):
  117. return sc.ndtr(x)
  118. def _norm_logcdf(x):
  119. return sc.log_ndtr(x)
  120. def _norm_ppf(q):
  121. return sc.ndtri(q)
  122. def _norm_sf(x):
  123. return _norm_cdf(-x)
  124. def _norm_logsf(x):
  125. return _norm_logcdf(-x)
  126. def _norm_isf(q):
  127. return -_norm_ppf(q)
  128. class norm_gen(rv_continuous):
  129. r"""A normal continuous random variable.
  130. The location (``loc``) keyword specifies the mean.
  131. The scale (``scale``) keyword specifies the standard deviation.
  132. %(before_notes)s
  133. Notes
  134. -----
  135. The probability density function for `norm` is:
  136. .. math::
  137. f(x) = \frac{\exp(-x^2/2)}{\sqrt{2\pi}}
  138. for a real number :math:`x`.
  139. %(after_notes)s
  140. %(example)s
  141. """
  142. def _rvs(self):
  143. return self._random_state.standard_normal(self._size)
  144. def _pdf(self, x):
  145. # norm.pdf(x) = exp(-x**2/2)/sqrt(2*pi)
  146. return _norm_pdf(x)
  147. def _logpdf(self, x):
  148. return _norm_logpdf(x)
  149. def _cdf(self, x):
  150. return _norm_cdf(x)
  151. def _logcdf(self, x):
  152. return _norm_logcdf(x)
  153. def _sf(self, x):
  154. return _norm_sf(x)
  155. def _logsf(self, x):
  156. return _norm_logsf(x)
  157. def _ppf(self, q):
  158. return _norm_ppf(q)
  159. def _isf(self, q):
  160. return _norm_isf(q)
  161. def _stats(self):
  162. return 0.0, 1.0, 0.0, 0.0
  163. def _entropy(self):
  164. return 0.5*(np.log(2*np.pi)+1)
  165. @replace_notes_in_docstring(rv_continuous, notes="""\
  166. This function uses explicit formulas for the maximum likelihood
  167. estimation of the normal distribution parameters, so the
  168. `optimizer` argument is ignored.\n\n""")
  169. def fit(self, data, **kwds):
  170. floc = kwds.get('floc', None)
  171. fscale = kwds.get('fscale', None)
  172. if floc is not None and fscale is not None:
  173. # This check is for consistency with `rv_continuous.fit`.
  174. # Without this check, this function would just return the
  175. # parameters that were given.
  176. raise ValueError("All parameters fixed. There is nothing to "
  177. "optimize.")
  178. data = np.asarray(data)
  179. if floc is None:
  180. loc = data.mean()
  181. else:
  182. loc = floc
  183. if fscale is None:
  184. scale = np.sqrt(((data - loc)**2).mean())
  185. else:
  186. scale = fscale
  187. return loc, scale
  188. norm = norm_gen(name='norm')
  189. class alpha_gen(rv_continuous):
  190. r"""An alpha continuous random variable.
  191. %(before_notes)s
  192. Notes
  193. -----
  194. The probability density function for `alpha` is:
  195. .. math::
  196. f(x, a) = \frac{1}{x^2 \Phi(a) \sqrt{2\pi}} *
  197. \exp(-\frac{1}{2} (a-1/x)^2)
  198. where :math:`\Phi` is the normal CDF, :math:`x > 0`, and :math:`a > 0`.
  199. `alpha` takes ``a`` as a shape parameter.
  200. %(after_notes)s
  201. %(example)s
  202. """
  203. _support_mask = rv_continuous._open_support_mask
  204. def _pdf(self, x, a):
  205. # alpha.pdf(x, a) = 1/(x**2*Phi(a)*sqrt(2*pi)) * exp(-1/2 * (a-1/x)**2)
  206. return 1.0/(x**2)/_norm_cdf(a)*_norm_pdf(a-1.0/x)
  207. def _logpdf(self, x, a):
  208. return -2*np.log(x) + _norm_logpdf(a-1.0/x) - np.log(_norm_cdf(a))
  209. def _cdf(self, x, a):
  210. return _norm_cdf(a-1.0/x) / _norm_cdf(a)
  211. def _ppf(self, q, a):
  212. return 1.0/np.asarray(a-sc.ndtri(q*_norm_cdf(a)))
  213. def _stats(self, a):
  214. return [np.inf]*2 + [np.nan]*2
  215. alpha = alpha_gen(a=0.0, name='alpha')
  216. class anglit_gen(rv_continuous):
  217. r"""An anglit continuous random variable.
  218. %(before_notes)s
  219. Notes
  220. -----
  221. The probability density function for `anglit` is:
  222. .. math::
  223. f(x) = \sin(2x + \pi/2) = \cos(2x)
  224. for :math:`-\pi/4 \le x \le \pi/4`.
  225. %(after_notes)s
  226. %(example)s
  227. """
  228. def _pdf(self, x):
  229. # anglit.pdf(x) = sin(2*x + \pi/2) = cos(2*x)
  230. return np.cos(2*x)
  231. def _cdf(self, x):
  232. return np.sin(x+np.pi/4)**2.0
  233. def _ppf(self, q):
  234. return np.arcsin(np.sqrt(q))-np.pi/4
  235. def _stats(self):
  236. return 0.0, np.pi*np.pi/16-0.5, 0.0, -2*(np.pi**4 - 96)/(np.pi*np.pi-8)**2
  237. def _entropy(self):
  238. return 1-np.log(2)
  239. anglit = anglit_gen(a=-np.pi/4, b=np.pi/4, name='anglit')
  240. class arcsine_gen(rv_continuous):
  241. r"""An arcsine continuous random variable.
  242. %(before_notes)s
  243. Notes
  244. -----
  245. The probability density function for `arcsine` is:
  246. .. math::
  247. f(x) = \frac{1}{\pi \sqrt{x (1-x)}}
  248. for :math:`0 < x < 1`.
  249. %(after_notes)s
  250. %(example)s
  251. """
  252. def _pdf(self, x):
  253. # arcsine.pdf(x) = 1/(pi*sqrt(x*(1-x)))
  254. return 1.0/np.pi/np.sqrt(x*(1-x))
  255. def _cdf(self, x):
  256. return 2.0/np.pi*np.arcsin(np.sqrt(x))
  257. def _ppf(self, q):
  258. return np.sin(np.pi/2.0*q)**2.0
  259. def _stats(self):
  260. mu = 0.5
  261. mu2 = 1.0/8
  262. g1 = 0
  263. g2 = -3.0/2.0
  264. return mu, mu2, g1, g2
  265. def _entropy(self):
  266. return -0.24156447527049044468
  267. arcsine = arcsine_gen(a=0.0, b=1.0, name='arcsine')
  268. class FitDataError(ValueError):
  269. # This exception is raised by, for example, beta_gen.fit when both floc
  270. # and fscale are fixed and there are values in the data not in the open
  271. # interval (floc, floc+fscale).
  272. def __init__(self, distr, lower, upper):
  273. self.args = (
  274. "Invalid values in `data`. Maximum likelihood "
  275. "estimation with {distr!r} requires that {lower!r} < x "
  276. "< {upper!r} for each x in `data`.".format(
  277. distr=distr, lower=lower, upper=upper),
  278. )
  279. class FitSolverError(RuntimeError):
  280. # This exception is raised by, for example, beta_gen.fit when
  281. # optimize.fsolve returns with ier != 1.
  282. def __init__(self, mesg):
  283. emsg = "Solver for the MLE equations failed to converge: "
  284. emsg += mesg.replace('\n', '')
  285. self.args = (emsg,)
  286. def _beta_mle_a(a, b, n, s1):
  287. # The zeros of this function give the MLE for `a`, with
  288. # `b`, `n` and `s1` given. `s1` is the sum of the logs of
  289. # the data. `n` is the number of data points.
  290. psiab = sc.psi(a + b)
  291. func = s1 - n * (-psiab + sc.psi(a))
  292. return func
  293. def _beta_mle_ab(theta, n, s1, s2):
  294. # Zeros of this function are critical points of
  295. # the maximum likelihood function. Solving this system
  296. # for theta (which contains a and b) gives the MLE for a and b
  297. # given `n`, `s1` and `s2`. `s1` is the sum of the logs of the data,
  298. # and `s2` is the sum of the logs of 1 - data. `n` is the number
  299. # of data points.
  300. a, b = theta
  301. psiab = sc.psi(a + b)
  302. func = [s1 - n * (-psiab + sc.psi(a)),
  303. s2 - n * (-psiab + sc.psi(b))]
  304. return func
  305. class beta_gen(rv_continuous):
  306. r"""A beta continuous random variable.
  307. %(before_notes)s
  308. Notes
  309. -----
  310. The probability density function for `beta` is:
  311. .. math::
  312. f(x, a, b) = \frac{\Gamma(a+b) x^{a-1} (1-x)^{b-1}}
  313. {\Gamma(a) \Gamma(b)}
  314. for :math:`0 < x < 1`, :math:`a > 0`, :math:`b > 0`, where
  315. :math:`\Gamma` is the gamma function (`scipy.special.gamma`).
  316. `beta` takes :math:`a` and :math:`b` as shape parameters.
  317. %(after_notes)s
  318. %(example)s
  319. """
  320. def _rvs(self, a, b):
  321. return self._random_state.beta(a, b, self._size)
  322. def _pdf(self, x, a, b):
  323. # gamma(a+b) * x**(a-1) * (1-x)**(b-1)
  324. # beta.pdf(x, a, b) = ------------------------------------
  325. # gamma(a)*gamma(b)
  326. return np.exp(self._logpdf(x, a, b))
  327. def _logpdf(self, x, a, b):
  328. lPx = sc.xlog1py(b - 1.0, -x) + sc.xlogy(a - 1.0, x)
  329. lPx -= sc.betaln(a, b)
  330. return lPx
  331. def _cdf(self, x, a, b):
  332. return sc.btdtr(a, b, x)
  333. def _ppf(self, q, a, b):
  334. return sc.btdtri(a, b, q)
  335. def _stats(self, a, b):
  336. mn = a*1.0 / (a + b)
  337. var = (a*b*1.0)/(a+b+1.0)/(a+b)**2.0
  338. g1 = 2.0*(b-a)*np.sqrt((1.0+a+b)/(a*b)) / (2+a+b)
  339. g2 = 6.0*(a**3 + a**2*(1-2*b) + b**2*(1+b) - 2*a*b*(2+b))
  340. g2 /= a*b*(a+b+2)*(a+b+3)
  341. return mn, var, g1, g2
  342. def _fitstart(self, data):
  343. g1 = _skew(data)
  344. g2 = _kurtosis(data)
  345. def func(x):
  346. a, b = x
  347. sk = 2*(b-a)*np.sqrt(a + b + 1) / (a + b + 2) / np.sqrt(a*b)
  348. ku = a**3 - a**2*(2*b-1) + b**2*(b+1) - 2*a*b*(b+2)
  349. ku /= a*b*(a+b+2)*(a+b+3)
  350. ku *= 6
  351. return [sk-g1, ku-g2]
  352. a, b = optimize.fsolve(func, (1.0, 1.0))
  353. return super(beta_gen, self)._fitstart(data, args=(a, b))
  354. @extend_notes_in_docstring(rv_continuous, notes="""\
  355. In the special case where both `floc` and `fscale` are given, a
  356. `ValueError` is raised if any value `x` in `data` does not satisfy
  357. `floc < x < floc + fscale`.\n\n""")
  358. def fit(self, data, *args, **kwds):
  359. # Override rv_continuous.fit, so we can more efficiently handle the
  360. # case where floc and fscale are given.
  361. f0 = (kwds.get('f0', None) or kwds.get('fa', None) or
  362. kwds.get('fix_a', None))
  363. f1 = (kwds.get('f1', None) or kwds.get('fb', None) or
  364. kwds.get('fix_b', None))
  365. floc = kwds.get('floc', None)
  366. fscale = kwds.get('fscale', None)
  367. if floc is None or fscale is None:
  368. # do general fit
  369. return super(beta_gen, self).fit(data, *args, **kwds)
  370. if f0 is not None and f1 is not None:
  371. # This check is for consistency with `rv_continuous.fit`.
  372. raise ValueError("All parameters fixed. There is nothing to "
  373. "optimize.")
  374. # Special case: loc and scale are constrained, so we are fitting
  375. # just the shape parameters. This can be done much more efficiently
  376. # than the method used in `rv_continuous.fit`. (See the subsection
  377. # "Two unknown parameters" in the section "Maximum likelihood" of
  378. # the Wikipedia article on the Beta distribution for the formulas.)
  379. # Normalize the data to the interval [0, 1].
  380. data = (np.ravel(data) - floc) / fscale
  381. if np.any(data <= 0) or np.any(data >= 1):
  382. raise FitDataError("beta", lower=floc, upper=floc + fscale)
  383. xbar = data.mean()
  384. if f0 is not None or f1 is not None:
  385. # One of the shape parameters is fixed.
  386. if f0 is not None:
  387. # The shape parameter a is fixed, so swap the parameters
  388. # and flip the data. We always solve for `a`. The result
  389. # will be swapped back before returning.
  390. b = f0
  391. data = 1 - data
  392. xbar = 1 - xbar
  393. else:
  394. b = f1
  395. # Initial guess for a. Use the formula for the mean of the beta
  396. # distribution, E[x] = a / (a + b), to generate a reasonable
  397. # starting point based on the mean of the data and the given
  398. # value of b.
  399. a = b * xbar / (1 - xbar)
  400. # Compute the MLE for `a` by solving _beta_mle_a.
  401. theta, info, ier, mesg = optimize.fsolve(
  402. _beta_mle_a, a,
  403. args=(b, len(data), np.log(data).sum()),
  404. full_output=True
  405. )
  406. if ier != 1:
  407. raise FitSolverError(mesg=mesg)
  408. a = theta[0]
  409. if f0 is not None:
  410. # The shape parameter a was fixed, so swap back the
  411. # parameters.
  412. a, b = b, a
  413. else:
  414. # Neither of the shape parameters is fixed.
  415. # s1 and s2 are used in the extra arguments passed to _beta_mle_ab
  416. # by optimize.fsolve.
  417. s1 = np.log(data).sum()
  418. s2 = sc.log1p(-data).sum()
  419. # Use the "method of moments" to estimate the initial
  420. # guess for a and b.
  421. fac = xbar * (1 - xbar) / data.var(ddof=0) - 1
  422. a = xbar * fac
  423. b = (1 - xbar) * fac
  424. # Compute the MLE for a and b by solving _beta_mle_ab.
  425. theta, info, ier, mesg = optimize.fsolve(
  426. _beta_mle_ab, [a, b],
  427. args=(len(data), s1, s2),
  428. full_output=True
  429. )
  430. if ier != 1:
  431. raise FitSolverError(mesg=mesg)
  432. a, b = theta
  433. return a, b, floc, fscale
  434. beta = beta_gen(a=0.0, b=1.0, name='beta')
  435. class betaprime_gen(rv_continuous):
  436. r"""A beta prime continuous random variable.
  437. %(before_notes)s
  438. Notes
  439. -----
  440. The probability density function for `betaprime` is:
  441. .. math::
  442. f(x, a, b) = \frac{x^{a-1} (1+x)^{-a-b}}{\beta(a, b)}
  443. for :math:`x > 0`, :math:`a > 0`, :math:`b > 0`, where
  444. :math:`\beta(a, b)` is the beta function (see `scipy.special.beta`).
  445. `betaprime` takes ``a`` and ``b`` as shape parameters.
  446. %(after_notes)s
  447. %(example)s
  448. """
  449. _support_mask = rv_continuous._open_support_mask
  450. def _rvs(self, a, b):
  451. sz, rndm = self._size, self._random_state
  452. u1 = gamma.rvs(a, size=sz, random_state=rndm)
  453. u2 = gamma.rvs(b, size=sz, random_state=rndm)
  454. return u1 / u2
  455. def _pdf(self, x, a, b):
  456. # betaprime.pdf(x, a, b) = x**(a-1) * (1+x)**(-a-b) / beta(a, b)
  457. return np.exp(self._logpdf(x, a, b))
  458. def _logpdf(self, x, a, b):
  459. return sc.xlogy(a - 1.0, x) - sc.xlog1py(a + b, x) - sc.betaln(a, b)
  460. def _cdf(self, x, a, b):
  461. return sc.betainc(a, b, x/(1.+x))
  462. def _munp(self, n, a, b):
  463. if n == 1.0:
  464. return np.where(b > 1,
  465. a/(b-1.0),
  466. np.inf)
  467. elif n == 2.0:
  468. return np.where(b > 2,
  469. a*(a+1.0)/((b-2.0)*(b-1.0)),
  470. np.inf)
  471. elif n == 3.0:
  472. return np.where(b > 3,
  473. a*(a+1.0)*(a+2.0)/((b-3.0)*(b-2.0)*(b-1.0)),
  474. np.inf)
  475. elif n == 4.0:
  476. return np.where(b > 4,
  477. (a*(a + 1.0)*(a + 2.0)*(a + 3.0) /
  478. ((b - 4.0)*(b - 3.0)*(b - 2.0)*(b - 1.0))),
  479. np.inf)
  480. else:
  481. raise NotImplementedError
  482. betaprime = betaprime_gen(a=0.0, name='betaprime')
  483. class bradford_gen(rv_continuous):
  484. r"""A Bradford continuous random variable.
  485. %(before_notes)s
  486. Notes
  487. -----
  488. The probability density function for `bradford` is:
  489. .. math::
  490. f(x, c) = \frac{c}{\log(1+c) (1+cx)}
  491. for :math:`0 < x < 1` and :math:`c > 0`.
  492. `bradford` takes ``c`` as a shape parameter for :math:`c`.
  493. %(after_notes)s
  494. %(example)s
  495. """
  496. def _pdf(self, x, c):
  497. # bradford.pdf(x, c) = c / (k * (1+c*x))
  498. return c / (c*x + 1.0) / sc.log1p(c)
  499. def _cdf(self, x, c):
  500. return sc.log1p(c*x) / sc.log1p(c)
  501. def _ppf(self, q, c):
  502. return sc.expm1(q * sc.log1p(c)) / c
  503. def _stats(self, c, moments='mv'):
  504. k = np.log(1.0+c)
  505. mu = (c-k)/(c*k)
  506. mu2 = ((c+2.0)*k-2.0*c)/(2*c*k*k)
  507. g1 = None
  508. g2 = None
  509. if 's' in moments:
  510. g1 = np.sqrt(2)*(12*c*c-9*c*k*(c+2)+2*k*k*(c*(c+3)+3))
  511. g1 /= np.sqrt(c*(c*(k-2)+2*k))*(3*c*(k-2)+6*k)
  512. if 'k' in moments:
  513. g2 = (c**3*(k-3)*(k*(3*k-16)+24)+12*k*c*c*(k-4)*(k-3) +
  514. 6*c*k*k*(3*k-14) + 12*k**3)
  515. g2 /= 3*c*(c*(k-2)+2*k)**2
  516. return mu, mu2, g1, g2
  517. def _entropy(self, c):
  518. k = np.log(1+c)
  519. return k/2.0 - np.log(c/k)
  520. bradford = bradford_gen(a=0.0, b=1.0, name='bradford')
  521. class burr_gen(rv_continuous):
  522. r"""A Burr (Type III) continuous random variable.
  523. %(before_notes)s
  524. See Also
  525. --------
  526. fisk : a special case of either `burr` or `burr12` with ``d=1``
  527. burr12 : Burr Type XII distribution
  528. Notes
  529. -----
  530. The probability density function for `burr` is:
  531. .. math::
  532. f(x, c, d) = c d x^{-c-1} (1+x^{-c})^{-d-1}
  533. for :math:`x > 0` and :math:`c, d > 0`.
  534. `burr` takes :math:`c` and :math:`d` as shape parameters.
  535. This is the PDF corresponding to the third CDF given in Burr's list;
  536. specifically, it is equation (11) in Burr's paper [1]_.
  537. %(after_notes)s
  538. References
  539. ----------
  540. .. [1] Burr, I. W. "Cumulative frequency functions", Annals of
  541. Mathematical Statistics, 13(2), pp 215-232 (1942).
  542. %(example)s
  543. """
  544. _support_mask = rv_continuous._open_support_mask
  545. def _pdf(self, x, c, d):
  546. # burr.pdf(x, c, d) = c * d * x**(-c-1) * (1+x**(-c))**(-d-1)
  547. return c * d * (x**(-c - 1.0)) * ((1 + x**(-c))**(-d - 1.0))
  548. def _cdf(self, x, c, d):
  549. return (1 + x**(-c))**(-d)
  550. def _ppf(self, q, c, d):
  551. return (q**(-1.0/d) - 1)**(-1.0/c)
  552. def _munp(self, n, c, d):
  553. nc = 1. * n / c
  554. return d * sc.beta(1.0 - nc, d + nc)
  555. burr = burr_gen(a=0.0, name='burr')
  556. class burr12_gen(rv_continuous):
  557. r"""A Burr (Type XII) continuous random variable.
  558. %(before_notes)s
  559. See Also
  560. --------
  561. fisk : a special case of either `burr` or `burr12` with ``d=1``
  562. burr : Burr Type III distribution
  563. Notes
  564. -----
  565. The probability density function for `burr` is:
  566. .. math::
  567. f(x, c, d) = c d x^{c-1} (1+x^c)^{-d-1}
  568. for :math:`x > 0` and :math:`c, d > 0`.
  569. `burr12` takes ``c`` and ``d`` as shape parameters for :math:`c`
  570. and :math:`d`.
  571. This is the PDF corresponding to the twelfth CDF given in Burr's list;
  572. specifically, it is equation (20) in Burr's paper [1]_.
  573. %(after_notes)s
  574. The Burr type 12 distribution is also sometimes referred to as
  575. the Singh-Maddala distribution from NIST [2]_.
  576. References
  577. ----------
  578. .. [1] Burr, I. W. "Cumulative frequency functions", Annals of
  579. Mathematical Statistics, 13(2), pp 215-232 (1942).
  580. .. [2] https://www.itl.nist.gov/div898/software/dataplot/refman2/auxillar/b12pdf.htm
  581. %(example)s
  582. """
  583. _support_mask = rv_continuous._open_support_mask
  584. def _pdf(self, x, c, d):
  585. # burr12.pdf(x, c, d) = c * d * x**(c-1) * (1+x**(c))**(-d-1)
  586. return np.exp(self._logpdf(x, c, d))
  587. def _logpdf(self, x, c, d):
  588. return np.log(c) + np.log(d) + sc.xlogy(c - 1, x) + sc.xlog1py(-d-1, x**c)
  589. def _cdf(self, x, c, d):
  590. return -sc.expm1(self._logsf(x, c, d))
  591. def _logcdf(self, x, c, d):
  592. return sc.log1p(-(1 + x**c)**(-d))
  593. def _sf(self, x, c, d):
  594. return np.exp(self._logsf(x, c, d))
  595. def _logsf(self, x, c, d):
  596. return sc.xlog1py(-d, x**c)
  597. def _ppf(self, q, c, d):
  598. # The following is an implementation of
  599. # ((1 - q)**(-1.0/d) - 1)**(1.0/c)
  600. # that does a better job handling small values of q.
  601. return sc.expm1(-1/d * sc.log1p(-q))**(1/c)
  602. def _munp(self, n, c, d):
  603. nc = 1. * n / c
  604. return d * sc.beta(1.0 + nc, d - nc)
  605. burr12 = burr12_gen(a=0.0, name='burr12')
  606. class fisk_gen(burr_gen):
  607. r"""A Fisk continuous random variable.
  608. The Fisk distribution is also known as the log-logistic distribution.
  609. %(before_notes)s
  610. Notes
  611. -----
  612. The probability density function for `fisk` is:
  613. .. math::
  614. f(x, c) = c x^{-c-1} (1 + x^{-c})^{-2}
  615. for :math:`x > 0` and :math:`c > 0`.
  616. `fisk` takes ``c`` as a shape parameter for :math:`c`.
  617. `fisk` is a special case of `burr` or `burr12` with ``d=1``.
  618. %(after_notes)s
  619. See Also
  620. --------
  621. burr
  622. %(example)s
  623. """
  624. def _pdf(self, x, c):
  625. # fisk.pdf(x, c) = c * x**(-c-1) * (1 + x**(-c))**(-2)
  626. return burr_gen._pdf(self, x, c, 1.0)
  627. def _cdf(self, x, c):
  628. return burr_gen._cdf(self, x, c, 1.0)
  629. def _ppf(self, x, c):
  630. return burr_gen._ppf(self, x, c, 1.0)
  631. def _munp(self, n, c):
  632. return burr_gen._munp(self, n, c, 1.0)
  633. def _entropy(self, c):
  634. return 2 - np.log(c)
  635. fisk = fisk_gen(a=0.0, name='fisk')
  636. # median = loc
  637. class cauchy_gen(rv_continuous):
  638. r"""A Cauchy continuous random variable.
  639. %(before_notes)s
  640. Notes
  641. -----
  642. The probability density function for `cauchy` is
  643. .. math::
  644. f(x) = \frac{1}{\pi (1 + x^2)}
  645. for a real number :math:`x`.
  646. %(after_notes)s
  647. %(example)s
  648. """
  649. def _pdf(self, x):
  650. # cauchy.pdf(x) = 1 / (pi * (1 + x**2))
  651. return 1.0/np.pi/(1.0+x*x)
  652. def _cdf(self, x):
  653. return 0.5 + 1.0/np.pi*np.arctan(x)
  654. def _ppf(self, q):
  655. return np.tan(np.pi*q-np.pi/2.0)
  656. def _sf(self, x):
  657. return 0.5 - 1.0/np.pi*np.arctan(x)
  658. def _isf(self, q):
  659. return np.tan(np.pi/2.0-np.pi*q)
  660. def _stats(self):
  661. return np.nan, np.nan, np.nan, np.nan
  662. def _entropy(self):
  663. return np.log(4*np.pi)
  664. def _fitstart(self, data, args=None):
  665. # Initialize ML guesses using quartiles instead of moments.
  666. p25, p50, p75 = np.percentile(data, [25, 50, 75])
  667. return p50, (p75 - p25)/2
  668. cauchy = cauchy_gen(name='cauchy')
  669. class chi_gen(rv_continuous):
  670. r"""A chi continuous random variable.
  671. %(before_notes)s
  672. Notes
  673. -----
  674. The probability density function for `chi` is:
  675. .. math::
  676. f(x, k) = \frac{1}{2^{k/2-1} \Gamma \left( k/2 \right)}
  677. x^{k-1} \exp \left( -x^2/2 \right)
  678. for :math:`x > 0` and :math:`k > 0` (degrees of freedom, denoted ``df``
  679. in the implementation). :math:`\Gamma` is the gamma function
  680. (`scipy.special.gamma`).
  681. Special cases of `chi` are:
  682. - ``chi(1, loc, scale)`` is equivalent to `halfnorm`
  683. - ``chi(2, 0, scale)`` is equivalent to `rayleigh`
  684. - ``chi(3, 0, scale)`` is equivalent to `maxwell`
  685. `chi` takes ``df`` as a shape parameter.
  686. %(after_notes)s
  687. %(example)s
  688. """
  689. def _rvs(self, df):
  690. sz, rndm = self._size, self._random_state
  691. return np.sqrt(chi2.rvs(df, size=sz, random_state=rndm))
  692. def _pdf(self, x, df):
  693. # x**(df-1) * exp(-x**2/2)
  694. # chi.pdf(x, df) = -------------------------
  695. # 2**(df/2-1) * gamma(df/2)
  696. return np.exp(self._logpdf(x, df))
  697. def _logpdf(self, x, df):
  698. l = np.log(2) - .5*np.log(2)*df - sc.gammaln(.5*df)
  699. return l + sc.xlogy(df - 1., x) - .5*x**2
  700. def _cdf(self, x, df):
  701. return sc.gammainc(.5*df, .5*x**2)
  702. def _ppf(self, q, df):
  703. return np.sqrt(2*sc.gammaincinv(.5*df, q))
  704. def _stats(self, df):
  705. mu = np.sqrt(2)*sc.gamma(df/2.0+0.5)/sc.gamma(df/2.0)
  706. mu2 = df - mu*mu
  707. g1 = (2*mu**3.0 + mu*(1-2*df))/np.asarray(np.power(mu2, 1.5))
  708. g2 = 2*df*(1.0-df)-6*mu**4 + 4*mu**2 * (2*df-1)
  709. g2 /= np.asarray(mu2**2.0)
  710. return mu, mu2, g1, g2
  711. chi = chi_gen(a=0.0, name='chi')
  712. ## Chi-squared (gamma-distributed with loc=0 and scale=2 and shape=df/2)
  713. class chi2_gen(rv_continuous):
  714. r"""A chi-squared continuous random variable.
  715. %(before_notes)s
  716. Notes
  717. -----
  718. The probability density function for `chi2` is:
  719. .. math::
  720. f(x, k) = \frac{1}{2^{k/2} \Gamma \left( k/2 \right)}
  721. x^{k/2-1} \exp \left( -x/2 \right)
  722. for :math:`x > 0` and :math:`k > 0` (degrees of freedom, denoted ``df``
  723. in the implementation).
  724. `chi2` takes ``df`` as a shape parameter.
  725. %(after_notes)s
  726. %(example)s
  727. """
  728. def _rvs(self, df):
  729. return self._random_state.chisquare(df, self._size)
  730. def _pdf(self, x, df):
  731. # chi2.pdf(x, df) = 1 / (2*gamma(df/2)) * (x/2)**(df/2-1) * exp(-x/2)
  732. return np.exp(self._logpdf(x, df))
  733. def _logpdf(self, x, df):
  734. return sc.xlogy(df/2.-1, x) - x/2. - sc.gammaln(df/2.) - (np.log(2)*df)/2.
  735. def _cdf(self, x, df):
  736. return sc.chdtr(df, x)
  737. def _sf(self, x, df):
  738. return sc.chdtrc(df, x)
  739. def _isf(self, p, df):
  740. return sc.chdtri(df, p)
  741. def _ppf(self, p, df):
  742. return self._isf(1.0-p, df)
  743. def _stats(self, df):
  744. mu = df
  745. mu2 = 2*df
  746. g1 = 2*np.sqrt(2.0/df)
  747. g2 = 12.0/df
  748. return mu, mu2, g1, g2
  749. chi2 = chi2_gen(a=0.0, name='chi2')
  750. class cosine_gen(rv_continuous):
  751. r"""A cosine continuous random variable.
  752. %(before_notes)s
  753. Notes
  754. -----
  755. The cosine distribution is an approximation to the normal distribution.
  756. The probability density function for `cosine` is:
  757. .. math::
  758. f(x) = \frac{1}{2\pi} (1+\cos(x))
  759. for :math:`-\pi \le x \le \pi`.
  760. %(after_notes)s
  761. %(example)s
  762. """
  763. def _pdf(self, x):
  764. # cosine.pdf(x) = 1/(2*pi) * (1+cos(x))
  765. return 1.0/2/np.pi*(1+np.cos(x))
  766. def _cdf(self, x):
  767. return 1.0/2/np.pi*(np.pi + x + np.sin(x))
  768. def _stats(self):
  769. return 0.0, np.pi*np.pi/3.0-2.0, 0.0, -6.0*(np.pi**4-90)/(5.0*(np.pi*np.pi-6)**2)
  770. def _entropy(self):
  771. return np.log(4*np.pi)-1.0
  772. cosine = cosine_gen(a=-np.pi, b=np.pi, name='cosine')
  773. class dgamma_gen(rv_continuous):
  774. r"""A double gamma continuous random variable.
  775. %(before_notes)s
  776. Notes
  777. -----
  778. The probability density function for `dgamma` is:
  779. .. math::
  780. f(x, a) = \frac{1}{2\Gamma(a)} |x|^{a-1} \exp(-|x|)
  781. for a real number :math:`x` and :math:`a > 0`. :math:`\Gamma` is the
  782. gamma function (`scipy.special.gamma`).
  783. `dgamma` takes ``a`` as a shape parameter for :math:`a`.
  784. %(after_notes)s
  785. %(example)s
  786. """
  787. def _rvs(self, a):
  788. sz, rndm = self._size, self._random_state
  789. u = rndm.random_sample(size=sz)
  790. gm = gamma.rvs(a, size=sz, random_state=rndm)
  791. return gm * np.where(u >= 0.5, 1, -1)
  792. def _pdf(self, x, a):
  793. # dgamma.pdf(x, a) = 1 / (2*gamma(a)) * abs(x)**(a-1) * exp(-abs(x))
  794. ax = abs(x)
  795. return 1.0/(2*sc.gamma(a))*ax**(a-1.0) * np.exp(-ax)
  796. def _logpdf(self, x, a):
  797. ax = abs(x)
  798. return sc.xlogy(a - 1.0, ax) - ax - np.log(2) - sc.gammaln(a)
  799. def _cdf(self, x, a):
  800. fac = 0.5*sc.gammainc(a, abs(x))
  801. return np.where(x > 0, 0.5 + fac, 0.5 - fac)
  802. def _sf(self, x, a):
  803. fac = 0.5*sc.gammainc(a, abs(x))
  804. return np.where(x > 0, 0.5-fac, 0.5+fac)
  805. def _ppf(self, q, a):
  806. fac = sc.gammainccinv(a, 1-abs(2*q-1))
  807. return np.where(q > 0.5, fac, -fac)
  808. def _stats(self, a):
  809. mu2 = a*(a+1.0)
  810. return 0.0, mu2, 0.0, (a+2.0)*(a+3.0)/mu2-3.0
  811. dgamma = dgamma_gen(name='dgamma')
  812. class dweibull_gen(rv_continuous):
  813. r"""A double Weibull continuous random variable.
  814. %(before_notes)s
  815. Notes
  816. -----
  817. The probability density function for `dweibull` is given by
  818. .. math::
  819. f(x, c) = c / 2 |x|^{c-1} \exp(-|x|^c)
  820. for a real number :math:`x` and :math:`c > 0`.
  821. `dweibull` takes ``c`` as a shape parameter for :math:`c`.
  822. %(after_notes)s
  823. %(example)s
  824. """
  825. def _rvs(self, c):
  826. sz, rndm = self._size, self._random_state
  827. u = rndm.random_sample(size=sz)
  828. w = weibull_min.rvs(c, size=sz, random_state=rndm)
  829. return w * (np.where(u >= 0.5, 1, -1))
  830. def _pdf(self, x, c):
  831. # dweibull.pdf(x, c) = c / 2 * abs(x)**(c-1) * exp(-abs(x)**c)
  832. ax = abs(x)
  833. Px = c / 2.0 * ax**(c-1.0) * np.exp(-ax**c)
  834. return Px
  835. def _logpdf(self, x, c):
  836. ax = abs(x)
  837. return np.log(c) - np.log(2.0) + sc.xlogy(c - 1.0, ax) - ax**c
  838. def _cdf(self, x, c):
  839. Cx1 = 0.5 * np.exp(-abs(x)**c)
  840. return np.where(x > 0, 1 - Cx1, Cx1)
  841. def _ppf(self, q, c):
  842. fac = 2. * np.where(q <= 0.5, q, 1. - q)
  843. fac = np.power(-np.log(fac), 1.0 / c)
  844. return np.where(q > 0.5, fac, -fac)
  845. def _munp(self, n, c):
  846. return (1 - (n % 2)) * sc.gamma(1.0 + 1.0 * n / c)
  847. # since we know that all odd moments are zeros, return them at once.
  848. # returning Nones from _stats makes the public stats call _munp
  849. # so overall we're saving one or two gamma function evaluations here.
  850. def _stats(self, c):
  851. return 0, None, 0, None
  852. dweibull = dweibull_gen(name='dweibull')
  853. ## Exponential (gamma distributed with a=1.0, loc=loc and scale=scale)
  854. class expon_gen(rv_continuous):
  855. r"""An exponential continuous random variable.
  856. %(before_notes)s
  857. Notes
  858. -----
  859. The probability density function for `expon` is:
  860. .. math::
  861. f(x) = \exp(-x)
  862. for :math:`x \ge 0`.
  863. %(after_notes)s
  864. A common parameterization for `expon` is in terms of the rate parameter
  865. ``lambda``, such that ``pdf = lambda * exp(-lambda * x)``. This
  866. parameterization corresponds to using ``scale = 1 / lambda``.
  867. %(example)s
  868. """
  869. def _rvs(self):
  870. return self._random_state.standard_exponential(self._size)
  871. def _pdf(self, x):
  872. # expon.pdf(x) = exp(-x)
  873. return np.exp(-x)
  874. def _logpdf(self, x):
  875. return -x
  876. def _cdf(self, x):
  877. return -sc.expm1(-x)
  878. def _ppf(self, q):
  879. return -sc.log1p(-q)
  880. def _sf(self, x):
  881. return np.exp(-x)
  882. def _logsf(self, x):
  883. return -x
  884. def _isf(self, q):
  885. return -np.log(q)
  886. def _stats(self):
  887. return 1.0, 1.0, 2.0, 6.0
  888. def _entropy(self):
  889. return 1.0
  890. @replace_notes_in_docstring(rv_continuous, notes="""\
  891. This function uses explicit formulas for the maximum likelihood
  892. estimation of the exponential distribution parameters, so the
  893. `optimizer`, `loc` and `scale` keyword arguments are ignored.\n\n""")
  894. def fit(self, data, *args, **kwds):
  895. if len(args) > 0:
  896. raise TypeError("Too many arguments.")
  897. floc = kwds.pop('floc', None)
  898. fscale = kwds.pop('fscale', None)
  899. # Ignore the optimizer-related keyword arguments, if given.
  900. kwds.pop('loc', None)
  901. kwds.pop('scale', None)
  902. kwds.pop('optimizer', None)
  903. if kwds:
  904. raise TypeError("Unknown arguments: %s." % kwds)
  905. if floc is not None and fscale is not None:
  906. # This check is for consistency with `rv_continuous.fit`.
  907. raise ValueError("All parameters fixed. There is nothing to "
  908. "optimize.")
  909. data = np.asarray(data)
  910. data_min = data.min()
  911. if floc is None:
  912. # ML estimate of the location is the minimum of the data.
  913. loc = data_min
  914. else:
  915. loc = floc
  916. if data_min < loc:
  917. # There are values that are less than the specified loc.
  918. raise FitDataError("expon", lower=floc, upper=np.inf)
  919. if fscale is None:
  920. # ML estimate of the scale is the shifted mean.
  921. scale = data.mean() - loc
  922. else:
  923. scale = fscale
  924. # We expect the return values to be floating point, so ensure it
  925. # by explicitly converting to float.
  926. return float(loc), float(scale)
  927. expon = expon_gen(a=0.0, name='expon')
  928. ## Exponentially Modified Normal (exponential distribution
  929. ## convolved with a Normal).
  930. ## This is called an exponentially modified gaussian on wikipedia
  931. class exponnorm_gen(rv_continuous):
  932. r"""An exponentially modified Normal continuous random variable.
  933. %(before_notes)s
  934. Notes
  935. -----
  936. The probability density function for `exponnorm` is:
  937. .. math::
  938. f(x, K) = \frac{1}{2K} \exp\left(\frac{1}{2 K^2} - x / K \right)
  939. \text{erfc}\left(-\frac{x - 1/K}{\sqrt{2}}\right)
  940. where :math:`x` is a real number and :math:`K > 0`.
  941. It can be thought of as the sum of a standard normal random variable
  942. and an independent exponentially distributed random variable with rate
  943. ``1/K``.
  944. %(after_notes)s
  945. An alternative parameterization of this distribution (for example, in
  946. `Wikipedia <https://en.wikipedia.org/wiki/Exponentially_modified_Gaussian_distribution>`_)
  947. involves three parameters, :math:`\mu`, :math:`\lambda` and
  948. :math:`\sigma`.
  949. In the present parameterization this corresponds to having ``loc`` and
  950. ``scale`` equal to :math:`\mu` and :math:`\sigma`, respectively, and
  951. shape parameter :math:`K = 1/(\sigma\lambda)`.
  952. .. versionadded:: 0.16.0
  953. %(example)s
  954. """
  955. def _rvs(self, K):
  956. expval = self._random_state.standard_exponential(self._size) * K
  957. gval = self._random_state.standard_normal(self._size)
  958. return expval + gval
  959. def _pdf(self, x, K):
  960. # exponnorm.pdf(x, K) =
  961. # 1/(2*K) exp(1/(2 * K**2)) exp(-x / K) * erfc-(x - 1/K) / sqrt(2))
  962. invK = 1.0 / K
  963. exparg = 0.5 * invK**2 - invK * x
  964. # Avoid overflows; setting np.exp(exparg) to the max float works
  965. # all right here
  966. expval = _lazywhere(exparg < _LOGXMAX, (exparg,), np.exp, _XMAX)
  967. return 0.5 * invK * expval * sc.erfc(-(x - invK) / np.sqrt(2))
  968. def _logpdf(self, x, K):
  969. invK = 1.0 / K
  970. exparg = 0.5 * invK**2 - invK * x
  971. return exparg + np.log(0.5 * invK * sc.erfc(-(x - invK) / np.sqrt(2)))
  972. def _cdf(self, x, K):
  973. invK = 1.0 / K
  974. expval = invK * (0.5 * invK - x)
  975. return _norm_cdf(x) - np.exp(expval) * _norm_cdf(x - invK)
  976. def _sf(self, x, K):
  977. invK = 1.0 / K
  978. expval = invK * (0.5 * invK - x)
  979. return _norm_cdf(-x) + np.exp(expval) * _norm_cdf(x - invK)
  980. def _stats(self, K):
  981. K2 = K * K
  982. opK2 = 1.0 + K2
  983. skw = 2 * K**3 * opK2**(-1.5)
  984. krt = 6.0 * K2 * K2 * opK2**(-2)
  985. return K, opK2, skw, krt
  986. exponnorm = exponnorm_gen(name='exponnorm')
  987. class exponweib_gen(rv_continuous):
  988. r"""An exponentiated Weibull continuous random variable.
  989. %(before_notes)s
  990. Notes
  991. -----
  992. The probability density function for `exponweib` is:
  993. .. math::
  994. f(x, a, c) = a c (1-\exp(-x^c))^{a-1} \exp(-x^c) x^{c-1}
  995. for :math:`x > 0`, :math:`a > 0`, :math:`c > 0`.
  996. `exponweib` takes :math:`a` and :math:`c` as shape parameters.
  997. %(after_notes)s
  998. %(example)s
  999. """
  1000. def _pdf(self, x, a, c):
  1001. # exponweib.pdf(x, a, c) =
  1002. # a * c * (1-exp(-x**c))**(a-1) * exp(-x**c)*x**(c-1)
  1003. return np.exp(self._logpdf(x, a, c))
  1004. def _logpdf(self, x, a, c):
  1005. negxc = -x**c
  1006. exm1c = -sc.expm1(negxc)
  1007. logp = (np.log(a) + np.log(c) + sc.xlogy(a - 1.0, exm1c) +
  1008. negxc + sc.xlogy(c - 1.0, x))
  1009. return logp
  1010. def _cdf(self, x, a, c):
  1011. exm1c = -sc.expm1(-x**c)
  1012. return exm1c**a
  1013. def _ppf(self, q, a, c):
  1014. return (-sc.log1p(-q**(1.0/a)))**np.asarray(1.0/c)
  1015. exponweib = exponweib_gen(a=0.0, name='exponweib')
  1016. class exponpow_gen(rv_continuous):
  1017. r"""An exponential power continuous random variable.
  1018. %(before_notes)s
  1019. Notes
  1020. -----
  1021. The probability density function for `exponpow` is:
  1022. .. math::
  1023. f(x, b) = b x^{b-1} \exp(1 + x^b - \exp(x^b))
  1024. for :math:`x \ge 0`, :math:`b > 0`. Note that this is a different
  1025. distribution from the exponential power distribution that is also known
  1026. under the names "generalized normal" or "generalized Gaussian".
  1027. `exponpow` takes ``b`` as a shape parameter for :math:`b`.
  1028. %(after_notes)s
  1029. References
  1030. ----------
  1031. http://www.math.wm.edu/~leemis/chart/UDR/PDFs/Exponentialpower.pdf
  1032. %(example)s
  1033. """
  1034. def _pdf(self, x, b):
  1035. # exponpow.pdf(x, b) = b * x**(b-1) * exp(1 + x**b - exp(x**b))
  1036. return np.exp(self._logpdf(x, b))
  1037. def _logpdf(self, x, b):
  1038. xb = x**b
  1039. f = 1 + np.log(b) + sc.xlogy(b - 1.0, x) + xb - np.exp(xb)
  1040. return f
  1041. def _cdf(self, x, b):
  1042. return -sc.expm1(-sc.expm1(x**b))
  1043. def _sf(self, x, b):
  1044. return np.exp(-sc.expm1(x**b))
  1045. def _isf(self, x, b):
  1046. return (sc.log1p(-np.log(x)))**(1./b)
  1047. def _ppf(self, q, b):
  1048. return pow(sc.log1p(-sc.log1p(-q)), 1.0/b)
  1049. exponpow = exponpow_gen(a=0.0, name='exponpow')
  1050. class fatiguelife_gen(rv_continuous):
  1051. r"""A fatigue-life (Birnbaum-Saunders) continuous random variable.
  1052. %(before_notes)s
  1053. Notes
  1054. -----
  1055. The probability density function for `fatiguelife` is:
  1056. .. math::
  1057. f(x, c) = \frac{x+1}{2c\sqrt{2\pi x^3}} \exp(-\frac{(x-1)^2}{2x c^2})
  1058. for :math:`x > 0` and :math:`c > 0`.
  1059. `fatiguelife` takes ``c`` as a shape parameter for :math:`c`.
  1060. %(after_notes)s
  1061. References
  1062. ----------
  1063. .. [1] "Birnbaum-Saunders distribution",
  1064. https://en.wikipedia.org/wiki/Birnbaum-Saunders_distribution
  1065. %(example)s
  1066. """
  1067. _support_mask = rv_continuous._open_support_mask
  1068. def _rvs(self, c):
  1069. z = self._random_state.standard_normal(self._size)
  1070. x = 0.5*c*z
  1071. x2 = x*x
  1072. t = 1.0 + 2*x2 + 2*x*np.sqrt(1 + x2)
  1073. return t
  1074. def _pdf(self, x, c):
  1075. # fatiguelife.pdf(x, c) =
  1076. # (x+1) / (2*c*sqrt(2*pi*x**3)) * exp(-(x-1)**2/(2*x*c**2))
  1077. return np.exp(self._logpdf(x, c))
  1078. def _logpdf(self, x, c):
  1079. return (np.log(x+1) - (x-1)**2 / (2.0*x*c**2) - np.log(2*c) -
  1080. 0.5*(np.log(2*np.pi) + 3*np.log(x)))
  1081. def _cdf(self, x, c):
  1082. return _norm_cdf(1.0 / c * (np.sqrt(x) - 1.0/np.sqrt(x)))
  1083. def _ppf(self, q, c):
  1084. tmp = c*sc.ndtri(q)
  1085. return 0.25 * (tmp + np.sqrt(tmp**2 + 4))**2
  1086. def _stats(self, c):
  1087. # NB: the formula for kurtosis in wikipedia seems to have an error:
  1088. # it's 40, not 41. At least it disagrees with the one from Wolfram
  1089. # Alpha. And the latter one, below, passes the tests, while the wiki
  1090. # one doesn't So far I didn't have the guts to actually check the
  1091. # coefficients from the expressions for the raw moments.
  1092. c2 = c*c
  1093. mu = c2 / 2.0 + 1.0
  1094. den = 5.0 * c2 + 4.0
  1095. mu2 = c2*den / 4.0
  1096. g1 = 4 * c * (11*c2 + 6.0) / np.power(den, 1.5)
  1097. g2 = 6 * c2 * (93*c2 + 40.0) / den**2.0
  1098. return mu, mu2, g1, g2
  1099. fatiguelife = fatiguelife_gen(a=0.0, name='fatiguelife')
  1100. class foldcauchy_gen(rv_continuous):
  1101. r"""A folded Cauchy continuous random variable.
  1102. %(before_notes)s
  1103. Notes
  1104. -----
  1105. The probability density function for `foldcauchy` is:
  1106. .. math::
  1107. f(x, c) = \frac{1}{\pi (1+(x-c)^2)} + \frac{1}{\pi (1+(x+c)^2)}
  1108. for :math:`x \ge 0`.
  1109. `foldcauchy` takes ``c`` as a shape parameter for :math:`c`.
  1110. %(example)s
  1111. """
  1112. def _rvs(self, c):
  1113. return abs(cauchy.rvs(loc=c, size=self._size,
  1114. random_state=self._random_state))
  1115. def _pdf(self, x, c):
  1116. # foldcauchy.pdf(x, c) = 1/(pi*(1+(x-c)**2)) + 1/(pi*(1+(x+c)**2))
  1117. return 1.0/np.pi*(1.0/(1+(x-c)**2) + 1.0/(1+(x+c)**2))
  1118. def _cdf(self, x, c):
  1119. return 1.0/np.pi*(np.arctan(x-c) + np.arctan(x+c))
  1120. def _stats(self, c):
  1121. return np.inf, np.inf, np.nan, np.nan
  1122. foldcauchy = foldcauchy_gen(a=0.0, name='foldcauchy')
  1123. class f_gen(rv_continuous):
  1124. r"""An F continuous random variable.
  1125. %(before_notes)s
  1126. Notes
  1127. -----
  1128. The probability density function for `f` is:
  1129. .. math::
  1130. f(x, df_1, df_2) = \frac{df_2^{df_2/2} df_1^{df_1/2} x^{df_1 / 2-1}}
  1131. {(df_2+df_1 x)^{(df_1+df_2)/2}
  1132. B(df_1/2, df_2/2)}
  1133. for :math:`x > 0`.
  1134. `f` takes ``dfn`` and ``dfd`` as shape parameters.
  1135. %(after_notes)s
  1136. %(example)s
  1137. """
  1138. def _rvs(self, dfn, dfd):
  1139. return self._random_state.f(dfn, dfd, self._size)
  1140. def _pdf(self, x, dfn, dfd):
  1141. # df2**(df2/2) * df1**(df1/2) * x**(df1/2-1)
  1142. # F.pdf(x, df1, df2) = --------------------------------------------
  1143. # (df2+df1*x)**((df1+df2)/2) * B(df1/2, df2/2)
  1144. return np.exp(self._logpdf(x, dfn, dfd))
  1145. def _logpdf(self, x, dfn, dfd):
  1146. n = 1.0 * dfn
  1147. m = 1.0 * dfd
  1148. lPx = m/2 * np.log(m) + n/2 * np.log(n) + (n/2 - 1) * np.log(x)
  1149. lPx -= ((n+m)/2) * np.log(m + n*x) + sc.betaln(n/2, m/2)
  1150. return lPx
  1151. def _cdf(self, x, dfn, dfd):
  1152. return sc.fdtr(dfn, dfd, x)
  1153. def _sf(self, x, dfn, dfd):
  1154. return sc.fdtrc(dfn, dfd, x)
  1155. def _ppf(self, q, dfn, dfd):
  1156. return sc.fdtri(dfn, dfd, q)
  1157. def _stats(self, dfn, dfd):
  1158. v1, v2 = 1. * dfn, 1. * dfd
  1159. v2_2, v2_4, v2_6, v2_8 = v2 - 2., v2 - 4., v2 - 6., v2 - 8.
  1160. mu = _lazywhere(
  1161. v2 > 2, (v2, v2_2),
  1162. lambda v2, v2_2: v2 / v2_2,
  1163. np.inf)
  1164. mu2 = _lazywhere(
  1165. v2 > 4, (v1, v2, v2_2, v2_4),
  1166. lambda v1, v2, v2_2, v2_4:
  1167. 2 * v2 * v2 * (v1 + v2_2) / (v1 * v2_2**2 * v2_4),
  1168. np.inf)
  1169. g1 = _lazywhere(
  1170. v2 > 6, (v1, v2_2, v2_4, v2_6),
  1171. lambda v1, v2_2, v2_4, v2_6:
  1172. (2 * v1 + v2_2) / v2_6 * np.sqrt(v2_4 / (v1 * (v1 + v2_2))),
  1173. np.nan)
  1174. g1 *= np.sqrt(8.)
  1175. g2 = _lazywhere(
  1176. v2 > 8, (g1, v2_6, v2_8),
  1177. lambda g1, v2_6, v2_8: (8 + g1 * g1 * v2_6) / v2_8,
  1178. np.nan)
  1179. g2 *= 3. / 2.
  1180. return mu, mu2, g1, g2
  1181. f = f_gen(a=0.0, name='f')
  1182. ## Folded Normal
  1183. ## abs(Z) where (Z is normal with mu=L and std=S so that c=abs(L)/S)
  1184. ##
  1185. ## note: regress docs have scale parameter correct, but first parameter
  1186. ## he gives is a shape parameter A = c * scale
  1187. ## Half-normal is folded normal with shape-parameter c=0.
  1188. class foldnorm_gen(rv_continuous):
  1189. r"""A folded normal continuous random variable.
  1190. %(before_notes)s
  1191. Notes
  1192. -----
  1193. The probability density function for `foldnorm` is:
  1194. .. math::
  1195. f(x, c) = \sqrt{2/\pi} cosh(c x) \exp(-\frac{x^2+c^2}{2})
  1196. for :math:`c \ge 0`.
  1197. `foldnorm` takes ``c`` as a shape parameter for :math:`c`.
  1198. %(after_notes)s
  1199. %(example)s
  1200. """
  1201. def _argcheck(self, c):
  1202. return c >= 0
  1203. def _rvs(self, c):
  1204. return abs(self._random_state.standard_normal(self._size) + c)
  1205. def _pdf(self, x, c):
  1206. # foldnormal.pdf(x, c) = sqrt(2/pi) * cosh(c*x) * exp(-(x**2+c**2)/2)
  1207. return _norm_pdf(x + c) + _norm_pdf(x-c)
  1208. def _cdf(self, x, c):
  1209. return _norm_cdf(x-c) + _norm_cdf(x+c) - 1.0
  1210. def _stats(self, c):
  1211. # Regina C. Elandt, Technometrics 3, 551 (1961)
  1212. # https://www.jstor.org/stable/1266561
  1213. #
  1214. c2 = c*c
  1215. expfac = np.exp(-0.5*c2) / np.sqrt(2.*np.pi)
  1216. mu = 2.*expfac + c * sc.erf(c/np.sqrt(2))
  1217. mu2 = c2 + 1 - mu*mu
  1218. g1 = 2. * (mu*mu*mu - c2*mu - expfac)
  1219. g1 /= np.power(mu2, 1.5)
  1220. g2 = c2 * (c2 + 6.) + 3 + 8.*expfac*mu
  1221. g2 += (2. * (c2 - 3.) - 3. * mu**2) * mu**2
  1222. g2 = g2 / mu2**2.0 - 3.
  1223. return mu, mu2, g1, g2
  1224. foldnorm = foldnorm_gen(a=0.0, name='foldnorm')
  1225. class weibull_min_gen(rv_continuous):
  1226. r"""Weibull minimum continuous random variable.
  1227. %(before_notes)s
  1228. See Also
  1229. --------
  1230. weibull_max
  1231. Notes
  1232. -----
  1233. The probability density function for `weibull_min` is:
  1234. .. math::
  1235. f(x, c) = c x^{c-1} \exp(-x^c)
  1236. for :math:`x > 0`, :math:`c > 0`.
  1237. `weibull_min` takes ``c`` as a shape parameter for :math:`c`.
  1238. %(after_notes)s
  1239. %(example)s
  1240. """
  1241. def _pdf(self, x, c):
  1242. # frechet_r.pdf(x, c) = c * x**(c-1) * exp(-x**c)
  1243. return c*pow(x, c-1)*np.exp(-pow(x, c))
  1244. def _logpdf(self, x, c):
  1245. return np.log(c) + sc.xlogy(c - 1, x) - pow(x, c)
  1246. def _cdf(self, x, c):
  1247. return -sc.expm1(-pow(x, c))
  1248. def _sf(self, x, c):
  1249. return np.exp(-pow(x, c))
  1250. def _logsf(self, x, c):
  1251. return -pow(x, c)
  1252. def _ppf(self, q, c):
  1253. return pow(-sc.log1p(-q), 1.0/c)
  1254. def _munp(self, n, c):
  1255. return sc.gamma(1.0+n*1.0/c)
  1256. def _entropy(self, c):
  1257. return -_EULER / c - np.log(c) + _EULER + 1
  1258. weibull_min = weibull_min_gen(a=0.0, name='weibull_min')
  1259. class weibull_max_gen(rv_continuous):
  1260. r"""Weibull maximum continuous random variable.
  1261. %(before_notes)s
  1262. See Also
  1263. --------
  1264. weibull_min
  1265. Notes
  1266. -----
  1267. The probability density function for `weibull_max` is:
  1268. .. math::
  1269. f(x, c) = c (-x)^{c-1} \exp(-(-x)^c)
  1270. for :math:`x < 0`, :math:`c > 0`.
  1271. `weibull_max` takes ``c`` as a shape parameter for :math:`c`.
  1272. %(after_notes)s
  1273. %(example)s
  1274. """
  1275. def _pdf(self, x, c):
  1276. # frechet_l.pdf(x, c) = c * (-x)**(c-1) * exp(-(-x)**c)
  1277. return c*pow(-x, c-1)*np.exp(-pow(-x, c))
  1278. def _logpdf(self, x, c):
  1279. return np.log(c) + sc.xlogy(c-1, -x) - pow(-x, c)
  1280. def _cdf(self, x, c):
  1281. return np.exp(-pow(-x, c))
  1282. def _logcdf(self, x, c):
  1283. return -pow(-x, c)
  1284. def _sf(self, x, c):
  1285. return -sc.expm1(-pow(-x, c))
  1286. def _ppf(self, q, c):
  1287. return -pow(-np.log(q), 1.0/c)
  1288. def _munp(self, n, c):
  1289. val = sc.gamma(1.0+n*1.0/c)
  1290. if int(n) % 2:
  1291. sgn = -1
  1292. else:
  1293. sgn = 1
  1294. return sgn * val
  1295. def _entropy(self, c):
  1296. return -_EULER / c - np.log(c) + _EULER + 1
  1297. weibull_max = weibull_max_gen(b=0.0, name='weibull_max')
  1298. # Public methods to be deprecated in frechet_r and frechet_l:
  1299. # ['__call__', 'cdf', 'entropy', 'expect', 'fit', 'fit_loc_scale', 'freeze',
  1300. # 'interval', 'isf', 'logcdf', 'logpdf', 'logsf', 'mean', 'median', 'moment',
  1301. # 'nnlf', 'pdf', 'ppf', 'rvs', 'sf', 'stats', 'std', 'var']
  1302. _frechet_r_deprec_msg = """\
  1303. The distribution `frechet_r` is a synonym for `weibull_min`; this historical
  1304. usage is deprecated because of possible confusion with the (quite different)
  1305. Frechet distribution. To preserve the existing behavior of the program, use
  1306. `scipy.stats.weibull_min`. For the Frechet distribution (i.e. the Type II
  1307. extreme value distribution), use `scipy.stats.invweibull`."""
  1308. class frechet_r_gen(weibull_min_gen):
  1309. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1310. def __call__(self, *args, **kwargs):
  1311. return weibull_min_gen.__call__(self, *args, **kwargs)
  1312. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1313. def cdf(self, *args, **kwargs):
  1314. return weibull_min_gen.cdf(self, *args, **kwargs)
  1315. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1316. def entropy(self, *args, **kwargs):
  1317. return weibull_min_gen.entropy(self, *args, **kwargs)
  1318. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1319. def expect(self, *args, **kwargs):
  1320. return weibull_min_gen.expect(self, *args, **kwargs)
  1321. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1322. def fit(self, *args, **kwargs):
  1323. return weibull_min_gen.fit(self, *args, **kwargs)
  1324. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1325. def fit_loc_scale(self, *args, **kwargs):
  1326. return weibull_min_gen.fit_loc_scale(self, *args, **kwargs)
  1327. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1328. def freeze(self, *args, **kwargs):
  1329. return weibull_min_gen.freeze(self, *args, **kwargs)
  1330. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1331. def interval(self, *args, **kwargs):
  1332. return weibull_min_gen.interval(self, *args, **kwargs)
  1333. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1334. def isf(self, *args, **kwargs):
  1335. return weibull_min_gen.isf(self, *args, **kwargs)
  1336. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1337. def logcdf(self, *args, **kwargs):
  1338. return weibull_min_gen.logcdf(self, *args, **kwargs)
  1339. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1340. def logpdf(self, *args, **kwargs):
  1341. return weibull_min_gen.logpdf(self, *args, **kwargs)
  1342. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1343. def logsf(self, *args, **kwargs):
  1344. return weibull_min_gen.logsf(self, *args, **kwargs)
  1345. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1346. def mean(self, *args, **kwargs):
  1347. return weibull_min_gen.mean(self, *args, **kwargs)
  1348. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1349. def median(self, *args, **kwargs):
  1350. return weibull_min_gen.median(self, *args, **kwargs)
  1351. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1352. def moment(self, *args, **kwargs):
  1353. return weibull_min_gen.moment(self, *args, **kwargs)
  1354. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1355. def nnlf(self, *args, **kwargs):
  1356. return weibull_min_gen.nnlf(self, *args, **kwargs)
  1357. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1358. def pdf(self, *args, **kwargs):
  1359. return weibull_min_gen.pdf(self, *args, **kwargs)
  1360. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1361. def ppf(self, *args, **kwargs):
  1362. return weibull_min_gen.ppf(self, *args, **kwargs)
  1363. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1364. def rvs(self, *args, **kwargs):
  1365. return weibull_min_gen.rvs(self, *args, **kwargs)
  1366. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1367. def sf(self, *args, **kwargs):
  1368. return weibull_min_gen.sf(self, *args, **kwargs)
  1369. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1370. def stats(self, *args, **kwargs):
  1371. return weibull_min_gen.stats(self, *args, **kwargs)
  1372. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1373. def std(self, *args, **kwargs):
  1374. return weibull_min_gen.std(self, *args, **kwargs)
  1375. @np.deprecate(old_name='frechet_r', message=_frechet_r_deprec_msg)
  1376. def var(self, *args, **kwargs):
  1377. return weibull_min_gen.var(self, *args, **kwargs)
  1378. frechet_r = frechet_r_gen(a=0.0, name='frechet_r')
  1379. _frechet_l_deprec_msg = """\
  1380. The distribution `frechet_l` is a synonym for `weibull_max`; this historical
  1381. usage is deprecated because of possible confusion with the (quite different)
  1382. Frechet distribution. To preserve the existing behavior of the program, use
  1383. `scipy.stats.weibull_max`. For the Frechet distribution (i.e. the Type II
  1384. extreme value distribution), use `scipy.stats.invweibull`."""
  1385. class frechet_l_gen(weibull_max_gen):
  1386. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1387. def __call__(self, *args, **kwargs):
  1388. return weibull_max_gen.__call__(self, *args, **kwargs)
  1389. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1390. def cdf(self, *args, **kwargs):
  1391. return weibull_max_gen.cdf(self, *args, **kwargs)
  1392. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1393. def entropy(self, *args, **kwargs):
  1394. return weibull_max_gen.entropy(self, *args, **kwargs)
  1395. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1396. def expect(self, *args, **kwargs):
  1397. return weibull_max_gen.expect(self, *args, **kwargs)
  1398. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1399. def fit(self, *args, **kwargs):
  1400. return weibull_max_gen.fit(self, *args, **kwargs)
  1401. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1402. def fit_loc_scale(self, *args, **kwargs):
  1403. return weibull_max_gen.fit_loc_scale(self, *args, **kwargs)
  1404. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1405. def freeze(self, *args, **kwargs):
  1406. return weibull_max_gen.freeze(self, *args, **kwargs)
  1407. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1408. def interval(self, *args, **kwargs):
  1409. return weibull_max_gen.interval(self, *args, **kwargs)
  1410. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1411. def isf(self, *args, **kwargs):
  1412. return weibull_max_gen.isf(self, *args, **kwargs)
  1413. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1414. def logcdf(self, *args, **kwargs):
  1415. return weibull_max_gen.logcdf(self, *args, **kwargs)
  1416. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1417. def logpdf(self, *args, **kwargs):
  1418. return weibull_max_gen.logpdf(self, *args, **kwargs)
  1419. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1420. def logsf(self, *args, **kwargs):
  1421. return weibull_max_gen.logsf(self, *args, **kwargs)
  1422. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1423. def mean(self, *args, **kwargs):
  1424. return weibull_max_gen.mean(self, *args, **kwargs)
  1425. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1426. def median(self, *args, **kwargs):
  1427. return weibull_max_gen.median(self, *args, **kwargs)
  1428. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1429. def moment(self, *args, **kwargs):
  1430. return weibull_max_gen.moment(self, *args, **kwargs)
  1431. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1432. def nnlf(self, *args, **kwargs):
  1433. return weibull_max_gen.nnlf(self, *args, **kwargs)
  1434. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1435. def pdf(self, *args, **kwargs):
  1436. return weibull_max_gen.pdf(self, *args, **kwargs)
  1437. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1438. def ppf(self, *args, **kwargs):
  1439. return weibull_max_gen.ppf(self, *args, **kwargs)
  1440. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1441. def rvs(self, *args, **kwargs):
  1442. return weibull_max_gen.rvs(self, *args, **kwargs)
  1443. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1444. def sf(self, *args, **kwargs):
  1445. return weibull_max_gen.sf(self, *args, **kwargs)
  1446. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1447. def stats(self, *args, **kwargs):
  1448. return weibull_max_gen.stats(self, *args, **kwargs)
  1449. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1450. def std(self, *args, **kwargs):
  1451. return weibull_max_gen.std(self, *args, **kwargs)
  1452. @np.deprecate(old_name='frechet_l', message=_frechet_l_deprec_msg)
  1453. def var(self, *args, **kwargs):
  1454. return weibull_max_gen.var(self, *args, **kwargs)
  1455. frechet_l = frechet_l_gen(b=0.0, name='frechet_l')
  1456. class genlogistic_gen(rv_continuous):
  1457. r"""A generalized logistic continuous random variable.
  1458. %(before_notes)s
  1459. Notes
  1460. -----
  1461. The probability density function for `genlogistic` is:
  1462. .. math::
  1463. f(x, c) = c \frac{\exp(-x)}
  1464. {(1 + \exp(-x))^{c+1}}
  1465. for :math:`x > 0`, :math:`c > 0`.
  1466. `genlogistic` takes ``c`` as a shape parameter for :math:`c`.
  1467. %(after_notes)s
  1468. %(example)s
  1469. """
  1470. def _pdf(self, x, c):
  1471. # genlogistic.pdf(x, c) = c * exp(-x) / (1 + exp(-x))**(c+1)
  1472. return np.exp(self._logpdf(x, c))
  1473. def _logpdf(self, x, c):
  1474. return np.log(c) - x - (c+1.0)*sc.log1p(np.exp(-x))
  1475. def _cdf(self, x, c):
  1476. Cx = (1+np.exp(-x))**(-c)
  1477. return Cx
  1478. def _ppf(self, q, c):
  1479. vals = -np.log(pow(q, -1.0/c)-1)
  1480. return vals
  1481. def _stats(self, c):
  1482. mu = _EULER + sc.psi(c)
  1483. mu2 = np.pi*np.pi/6.0 + sc.zeta(2, c)
  1484. g1 = -2*sc.zeta(3, c) + 2*_ZETA3
  1485. g1 /= np.power(mu2, 1.5)
  1486. g2 = np.pi**4/15.0 + 6*sc.zeta(4, c)
  1487. g2 /= mu2**2.0
  1488. return mu, mu2, g1, g2
  1489. genlogistic = genlogistic_gen(name='genlogistic')
  1490. class genpareto_gen(rv_continuous):
  1491. r"""A generalized Pareto continuous random variable.
  1492. %(before_notes)s
  1493. Notes
  1494. -----
  1495. The probability density function for `genpareto` is:
  1496. .. math::
  1497. f(x, c) = (1 + c x)^{-1 - 1/c}
  1498. defined for :math:`x \ge 0` if :math:`c \ge 0`, and for
  1499. :math:`0 \le x \le -1/c` if :math:`c < 0`.
  1500. `genpareto` takes ``c`` as a shape parameter for :math:`c`.
  1501. For :math:`c=0`, `genpareto` reduces to the exponential
  1502. distribution, `expon`:
  1503. .. math::
  1504. f(x, 0) = \exp(-x)
  1505. For :math:`c=-1`, `genpareto` is uniform on ``[0, 1]``:
  1506. .. math::
  1507. f(x, -1) = 1
  1508. %(after_notes)s
  1509. %(example)s
  1510. """
  1511. def _argcheck(self, c):
  1512. c = np.asarray(c)
  1513. self.b = _lazywhere(c < 0, (c,),
  1514. lambda c: -1. / c,
  1515. np.inf)
  1516. return True
  1517. def _pdf(self, x, c):
  1518. # genpareto.pdf(x, c) = (1 + c * x)**(-1 - 1/c)
  1519. return np.exp(self._logpdf(x, c))
  1520. def _logpdf(self, x, c):
  1521. return _lazywhere((x == x) & (c != 0), (x, c),
  1522. lambda x, c: -sc.xlog1py(c + 1., c*x) / c,
  1523. -x)
  1524. def _cdf(self, x, c):
  1525. return -sc.inv_boxcox1p(-x, -c)
  1526. def _sf(self, x, c):
  1527. return sc.inv_boxcox(-x, -c)
  1528. def _logsf(self, x, c):
  1529. return _lazywhere((x == x) & (c != 0), (x, c),
  1530. lambda x, c: -sc.log1p(c*x) / c,
  1531. -x)
  1532. def _ppf(self, q, c):
  1533. return -sc.boxcox1p(-q, -c)
  1534. def _isf(self, q, c):
  1535. return -sc.boxcox(q, -c)
  1536. def _munp(self, n, c):
  1537. def __munp(n, c):
  1538. val = 0.0
  1539. k = np.arange(0, n + 1)
  1540. for ki, cnk in zip(k, sc.comb(n, k)):
  1541. val = val + cnk * (-1) ** ki / (1.0 - c * ki)
  1542. return np.where(c * n < 1, val * (-1.0 / c) ** n, np.inf)
  1543. return _lazywhere(c != 0, (c,),
  1544. lambda c: __munp(n, c),
  1545. sc.gamma(n + 1))
  1546. def _entropy(self, c):
  1547. return 1. + c
  1548. genpareto = genpareto_gen(a=0.0, name='genpareto')
  1549. class genexpon_gen(rv_continuous):
  1550. r"""A generalized exponential continuous random variable.
  1551. %(before_notes)s
  1552. Notes
  1553. -----
  1554. The probability density function for `genexpon` is:
  1555. .. math::
  1556. f(x, a, b, c) = (a + b (1 - \exp(-c x)))
  1557. \exp(-a x - b x + \frac{b}{c} (1-\exp(-c x)))
  1558. for :math:`x \ge 0`, :math:`a, b, c > 0`.
  1559. `genexpon` takes :math:`a`, :math:`b` and :math:`c` as shape parameters.
  1560. %(after_notes)s
  1561. References
  1562. ----------
  1563. H.K. Ryu, "An Extension of Marshall and Olkin's Bivariate Exponential
  1564. Distribution", Journal of the American Statistical Association, 1993.
  1565. N. Balakrishnan, "The Exponential Distribution: Theory, Methods and
  1566. Applications", Asit P. Basu.
  1567. %(example)s
  1568. """
  1569. def _pdf(self, x, a, b, c):
  1570. # genexpon.pdf(x, a, b, c) = (a + b * (1 - exp(-c*x))) * \
  1571. # exp(-a*x - b*x + b/c * (1-exp(-c*x)))
  1572. return (a + b*(-sc.expm1(-c*x)))*np.exp((-a-b)*x +
  1573. b*(-sc.expm1(-c*x))/c)
  1574. def _cdf(self, x, a, b, c):
  1575. return -sc.expm1((-a-b)*x + b*(-sc.expm1(-c*x))/c)
  1576. def _logpdf(self, x, a, b, c):
  1577. return np.log(a+b*(-sc.expm1(-c*x))) + (-a-b)*x+b*(-sc.expm1(-c*x))/c
  1578. genexpon = genexpon_gen(a=0.0, name='genexpon')
  1579. class genextreme_gen(rv_continuous):
  1580. r"""A generalized extreme value continuous random variable.
  1581. %(before_notes)s
  1582. See Also
  1583. --------
  1584. gumbel_r
  1585. Notes
  1586. -----
  1587. For :math:`c=0`, `genextreme` is equal to `gumbel_r`.
  1588. The probability density function for `genextreme` is:
  1589. .. math::
  1590. f(x, c) = \begin{cases}
  1591. \exp(-\exp(-x)) \exp(-x) &\text{for } c = 0\\
  1592. \exp(-(1-c x)^{1/c}) (1-c x)^{1/c-1} &\text{for }
  1593. x \le 1/c, c > 0
  1594. \end{cases}
  1595. Note that several sources and software packages use the opposite
  1596. convention for the sign of the shape parameter :math:`c`.
  1597. `genextreme` takes ``c`` as a shape parameter for :math:`c`.
  1598. %(after_notes)s
  1599. %(example)s
  1600. """
  1601. def _argcheck(self, c):
  1602. self.b = np.where(c > 0, 1.0 / np.maximum(c, _XMIN), np.inf)
  1603. self.a = np.where(c < 0, 1.0 / np.minimum(c, -_XMIN), -np.inf)
  1604. return np.where(abs(c) == np.inf, 0, 1)
  1605. def _loglogcdf(self, x, c):
  1606. return _lazywhere((x == x) & (c != 0), (x, c),
  1607. lambda x, c: sc.log1p(-c*x)/c, -x)
  1608. def _pdf(self, x, c):
  1609. # genextreme.pdf(x, c) =
  1610. # exp(-exp(-x))*exp(-x), for c==0
  1611. # exp(-(1-c*x)**(1/c))*(1-c*x)**(1/c-1), for x \le 1/c, c > 0
  1612. return np.exp(self._logpdf(x, c))
  1613. def _logpdf(self, x, c):
  1614. cx = _lazywhere((x == x) & (c != 0), (x, c), lambda x, c: c*x, 0.0)
  1615. logex2 = sc.log1p(-cx)
  1616. logpex2 = self._loglogcdf(x, c)
  1617. pex2 = np.exp(logpex2)
  1618. # Handle special cases
  1619. np.putmask(logpex2, (c == 0) & (x == -np.inf), 0.0)
  1620. logpdf = np.where((cx == 1) | (cx == -np.inf),
  1621. -np.inf,
  1622. -pex2+logpex2-logex2)
  1623. np.putmask(logpdf, (c == 1) & (x == 1), 0.0)
  1624. return logpdf
  1625. def _logcdf(self, x, c):
  1626. return -np.exp(self._loglogcdf(x, c))
  1627. def _cdf(self, x, c):
  1628. return np.exp(self._logcdf(x, c))
  1629. def _sf(self, x, c):
  1630. return -sc.expm1(self._logcdf(x, c))
  1631. def _ppf(self, q, c):
  1632. x = -np.log(-np.log(q))
  1633. return _lazywhere((x == x) & (c != 0), (x, c),
  1634. lambda x, c: -sc.expm1(-c * x) / c, x)
  1635. def _isf(self, q, c):
  1636. x = -np.log(-sc.log1p(-q))
  1637. return _lazywhere((x == x) & (c != 0), (x, c),
  1638. lambda x, c: -sc.expm1(-c * x) / c, x)
  1639. def _stats(self, c):
  1640. g = lambda n: sc.gamma(n*c + 1)
  1641. g1 = g(1)
  1642. g2 = g(2)
  1643. g3 = g(3)
  1644. g4 = g(4)
  1645. g2mg12 = np.where(abs(c) < 1e-7, (c*np.pi)**2.0/6.0, g2-g1**2.0)
  1646. gam2k = np.where(abs(c) < 1e-7, np.pi**2.0/6.0,
  1647. sc.expm1(sc.gammaln(2.0*c+1.0)-2*sc.gammaln(c + 1.0))/c**2.0)
  1648. eps = 1e-14
  1649. gamk = np.where(abs(c) < eps, -_EULER, sc.expm1(sc.gammaln(c + 1))/c)
  1650. m = np.where(c < -1.0, np.nan, -gamk)
  1651. v = np.where(c < -0.5, np.nan, g1**2.0*gam2k)
  1652. # skewness
  1653. sk1 = _lazywhere(c >= -1./3,
  1654. (c, g1, g2, g3, g2mg12),
  1655. lambda c, g1, g2, g3, g2gm12:
  1656. np.sign(c)*(-g3 + (g2 + 2*g2mg12)*g1)/g2mg12**1.5,
  1657. fillvalue=np.nan)
  1658. sk = np.where(abs(c) <= eps**0.29, 12*np.sqrt(6)*_ZETA3/np.pi**3, sk1)
  1659. # kurtosis
  1660. ku1 = _lazywhere(c >= -1./4,
  1661. (g1, g2, g3, g4, g2mg12),
  1662. lambda g1, g2, g3, g4, g2mg12:
  1663. (g4 + (-4*g3 + 3*(g2 + g2mg12)*g1)*g1)/g2mg12**2,
  1664. fillvalue=np.nan)
  1665. ku = np.where(abs(c) <= (eps)**0.23, 12.0/5.0, ku1-3.0)
  1666. return m, v, sk, ku
  1667. def _fitstart(self, data):
  1668. # This is better than the default shape of (1,).
  1669. g = _skew(data)
  1670. if g < 0:
  1671. a = 0.5
  1672. else:
  1673. a = -0.5
  1674. return super(genextreme_gen, self)._fitstart(data, args=(a,))
  1675. def _munp(self, n, c):
  1676. k = np.arange(0, n+1)
  1677. vals = 1.0/c**n * np.sum(
  1678. sc.comb(n, k) * (-1)**k * sc.gamma(c*k + 1),
  1679. axis=0)
  1680. return np.where(c*n > -1, vals, np.inf)
  1681. def _entropy(self, c):
  1682. return _EULER*(1 - c) + 1
  1683. genextreme = genextreme_gen(name='genextreme')
  1684. def _digammainv(y):
  1685. # Inverse of the digamma function (real positive arguments only).
  1686. # This function is used in the `fit` method of `gamma_gen`.
  1687. # The function uses either optimize.fsolve or optimize.newton
  1688. # to solve `sc.digamma(x) - y = 0`. There is probably room for
  1689. # improvement, but currently it works over a wide range of y:
  1690. # >>> y = 64*np.random.randn(1000000)
  1691. # >>> y.min(), y.max()
  1692. # (-311.43592651416662, 351.77388222276869)
  1693. # x = [_digammainv(t) for t in y]
  1694. # np.abs(sc.digamma(x) - y).max()
  1695. # 1.1368683772161603e-13
  1696. #
  1697. _em = 0.5772156649015328606065120
  1698. func = lambda x: sc.digamma(x) - y
  1699. if y > -0.125:
  1700. x0 = np.exp(y) + 0.5
  1701. if y < 10:
  1702. # Some experimentation shows that newton reliably converges
  1703. # must faster than fsolve in this y range. For larger y,
  1704. # newton sometimes fails to converge.
  1705. value = optimize.newton(func, x0, tol=1e-10)
  1706. return value
  1707. elif y > -3:
  1708. x0 = np.exp(y/2.332) + 0.08661
  1709. else:
  1710. x0 = 1.0 / (-y - _em)
  1711. value, info, ier, mesg = optimize.fsolve(func, x0, xtol=1e-11,
  1712. full_output=True)
  1713. if ier != 1:
  1714. raise RuntimeError("_digammainv: fsolve failed, y = %r" % y)
  1715. return value[0]
  1716. ## Gamma (Use MATLAB and MATHEMATICA (b=theta=scale, a=alpha=shape) definition)
  1717. ## gamma(a, loc, scale) with a an integer is the Erlang distribution
  1718. ## gamma(1, loc, scale) is the Exponential distribution
  1719. ## gamma(df/2, 0, 2) is the chi2 distribution with df degrees of freedom.
  1720. class gamma_gen(rv_continuous):
  1721. r"""A gamma continuous random variable.
  1722. %(before_notes)s
  1723. See Also
  1724. --------
  1725. erlang, expon
  1726. Notes
  1727. -----
  1728. The probability density function for `gamma` is:
  1729. .. math::
  1730. f(x, a) = \frac{x^{a-1} \exp(-x)}{\Gamma(a)}
  1731. for :math:`x \ge 0`, :math:`a > 0`. Here :math:`\Gamma(a)` refers to the
  1732. gamma function.
  1733. `gamma` takes ``a`` as a shape parameter for :math:`a`.
  1734. When :math:`a` is an integer, `gamma` reduces to the Erlang
  1735. distribution, and when :math:`a=1` to the exponential distribution.
  1736. %(after_notes)s
  1737. %(example)s
  1738. """
  1739. def _rvs(self, a):
  1740. return self._random_state.standard_gamma(a, self._size)
  1741. def _pdf(self, x, a):
  1742. # gamma.pdf(x, a) = x**(a-1) * exp(-x) / gamma(a)
  1743. return np.exp(self._logpdf(x, a))
  1744. def _logpdf(self, x, a):
  1745. return sc.xlogy(a-1.0, x) - x - sc.gammaln(a)
  1746. def _cdf(self, x, a):
  1747. return sc.gammainc(a, x)
  1748. def _sf(self, x, a):
  1749. return sc.gammaincc(a, x)
  1750. def _ppf(self, q, a):
  1751. return sc.gammaincinv(a, q)
  1752. def _stats(self, a):
  1753. return a, a, 2.0/np.sqrt(a), 6.0/a
  1754. def _entropy(self, a):
  1755. return sc.psi(a)*(1-a) + a + sc.gammaln(a)
  1756. def _fitstart(self, data):
  1757. # The skewness of the gamma distribution is `4 / np.sqrt(a)`.
  1758. # We invert that to estimate the shape `a` using the skewness
  1759. # of the data. The formula is regularized with 1e-8 in the
  1760. # denominator to allow for degenerate data where the skewness
  1761. # is close to 0.
  1762. a = 4 / (1e-8 + _skew(data)**2)
  1763. return super(gamma_gen, self)._fitstart(data, args=(a,))
  1764. @extend_notes_in_docstring(rv_continuous, notes="""\
  1765. When the location is fixed by using the argument `floc`, this
  1766. function uses explicit formulas or solves a simpler numerical
  1767. problem than the full ML optimization problem. So in that case,
  1768. the `optimizer`, `loc` and `scale` arguments are ignored.\n\n""")
  1769. def fit(self, data, *args, **kwds):
  1770. f0 = (kwds.get('f0', None) or kwds.get('fa', None) or
  1771. kwds.get('fix_a', None))
  1772. floc = kwds.get('floc', None)
  1773. fscale = kwds.get('fscale', None)
  1774. if floc is None:
  1775. # loc is not fixed. Use the default fit method.
  1776. return super(gamma_gen, self).fit(data, *args, **kwds)
  1777. # Special case: loc is fixed.
  1778. if f0 is not None and fscale is not None:
  1779. # This check is for consistency with `rv_continuous.fit`.
  1780. # Without this check, this function would just return the
  1781. # parameters that were given.
  1782. raise ValueError("All parameters fixed. There is nothing to "
  1783. "optimize.")
  1784. # Fixed location is handled by shifting the data.
  1785. data = np.asarray(data)
  1786. if np.any(data <= floc):
  1787. raise FitDataError("gamma", lower=floc, upper=np.inf)
  1788. if floc != 0:
  1789. # Don't do the subtraction in-place, because `data` might be a
  1790. # view of the input array.
  1791. data = data - floc
  1792. xbar = data.mean()
  1793. # Three cases to handle:
  1794. # * shape and scale both free
  1795. # * shape fixed, scale free
  1796. # * shape free, scale fixed
  1797. if fscale is None:
  1798. # scale is free
  1799. if f0 is not None:
  1800. # shape is fixed
  1801. a = f0
  1802. else:
  1803. # shape and scale are both free.
  1804. # The MLE for the shape parameter `a` is the solution to:
  1805. # np.log(a) - sc.digamma(a) - np.log(xbar) +
  1806. # np.log(data.mean) = 0
  1807. s = np.log(xbar) - np.log(data).mean()
  1808. func = lambda a: np.log(a) - sc.digamma(a) - s
  1809. aest = (3-s + np.sqrt((s-3)**2 + 24*s)) / (12*s)
  1810. xa = aest*(1-0.4)
  1811. xb = aest*(1+0.4)
  1812. a = optimize.brentq(func, xa, xb, disp=0)
  1813. # The MLE for the scale parameter is just the data mean
  1814. # divided by the shape parameter.
  1815. scale = xbar / a
  1816. else:
  1817. # scale is fixed, shape is free
  1818. # The MLE for the shape parameter `a` is the solution to:
  1819. # sc.digamma(a) - np.log(data).mean() + np.log(fscale) = 0
  1820. c = np.log(data).mean() - np.log(fscale)
  1821. a = _digammainv(c)
  1822. scale = fscale
  1823. return a, floc, scale
  1824. gamma = gamma_gen(a=0.0, name='gamma')
  1825. class erlang_gen(gamma_gen):
  1826. """An Erlang continuous random variable.
  1827. %(before_notes)s
  1828. See Also
  1829. --------
  1830. gamma
  1831. Notes
  1832. -----
  1833. The Erlang distribution is a special case of the Gamma distribution, with
  1834. the shape parameter `a` an integer. Note that this restriction is not
  1835. enforced by `erlang`. It will, however, generate a warning the first time
  1836. a non-integer value is used for the shape parameter.
  1837. Refer to `gamma` for examples.
  1838. """
  1839. def _argcheck(self, a):
  1840. allint = np.all(np.floor(a) == a)
  1841. allpos = np.all(a > 0)
  1842. if not allint:
  1843. # An Erlang distribution shouldn't really have a non-integer
  1844. # shape parameter, so warn the user.
  1845. warnings.warn(
  1846. 'The shape parameter of the erlang distribution '
  1847. 'has been given a non-integer value %r.' % (a,),
  1848. RuntimeWarning)
  1849. return allpos
  1850. def _fitstart(self, data):
  1851. # Override gamma_gen_fitstart so that an integer initial value is
  1852. # used. (Also regularize the division, to avoid issues when
  1853. # _skew(data) is 0 or close to 0.)
  1854. a = int(4.0 / (1e-8 + _skew(data)**2))
  1855. return super(gamma_gen, self)._fitstart(data, args=(a,))
  1856. # Trivial override of the fit method, so we can monkey-patch its
  1857. # docstring.
  1858. def fit(self, data, *args, **kwds):
  1859. return super(erlang_gen, self).fit(data, *args, **kwds)
  1860. if fit.__doc__ is not None:
  1861. fit.__doc__ = (rv_continuous.fit.__doc__ +
  1862. """
  1863. Notes
  1864. -----
  1865. The Erlang distribution is generally defined to have integer values
  1866. for the shape parameter. This is not enforced by the `erlang` class.
  1867. When fitting the distribution, it will generally return a non-integer
  1868. value for the shape parameter. By using the keyword argument
  1869. `f0=<integer>`, the fit method can be constrained to fit the data to
  1870. a specific integer shape parameter.
  1871. """)
  1872. erlang = erlang_gen(a=0.0, name='erlang')
  1873. class gengamma_gen(rv_continuous):
  1874. r"""A generalized gamma continuous random variable.
  1875. %(before_notes)s
  1876. Notes
  1877. -----
  1878. The probability density function for `gengamma` is:
  1879. .. math::
  1880. f(x, a, c) = \frac{|c| x^{c a-1} \exp(-x^c)}{\Gamma(a)}
  1881. for :math:`x \ge 0`, :math:`a > 0`, and :math:`c \ne 0`.
  1882. :math:`\Gamma` is the gamma function (`scipy.special.gamma`).
  1883. `gengamma` takes :math:`a` and :math:`c` as shape parameters.
  1884. %(after_notes)s
  1885. %(example)s
  1886. """
  1887. def _argcheck(self, a, c):
  1888. return (a > 0) & (c != 0)
  1889. def _pdf(self, x, a, c):
  1890. # gengamma.pdf(x, a, c) = abs(c) * x**(c*a-1) * exp(-x**c) / gamma(a)
  1891. return np.exp(self._logpdf(x, a, c))
  1892. def _logpdf(self, x, a, c):
  1893. return np.log(abs(c)) + sc.xlogy(c*a - 1, x) - x**c - sc.gammaln(a)
  1894. def _cdf(self, x, a, c):
  1895. xc = x**c
  1896. val1 = sc.gammainc(a, xc)
  1897. val2 = sc.gammaincc(a, xc)
  1898. return np.where(c > 0, val1, val2)
  1899. def _sf(self, x, a, c):
  1900. xc = x**c
  1901. val1 = sc.gammainc(a, xc)
  1902. val2 = sc.gammaincc(a, xc)
  1903. return np.where(c > 0, val2, val1)
  1904. def _ppf(self, q, a, c):
  1905. val1 = sc.gammaincinv(a, q)
  1906. val2 = sc.gammainccinv(a, q)
  1907. return np.where(c > 0, val1, val2)**(1.0/c)
  1908. def _isf(self, q, a, c):
  1909. val1 = sc.gammaincinv(a, q)
  1910. val2 = sc.gammainccinv(a, q)
  1911. return np.where(c > 0, val2, val1)**(1.0/c)
  1912. def _munp(self, n, a, c):
  1913. # Pochhammer symbol: sc.pocha,n) = gamma(a+n)/gamma(a)
  1914. return sc.poch(a, n*1.0/c)
  1915. def _entropy(self, a, c):
  1916. val = sc.psi(a)
  1917. return a*(1-val) + 1.0/c*val + sc.gammaln(a) - np.log(abs(c))
  1918. gengamma = gengamma_gen(a=0.0, name='gengamma')
  1919. class genhalflogistic_gen(rv_continuous):
  1920. r"""A generalized half-logistic continuous random variable.
  1921. %(before_notes)s
  1922. Notes
  1923. -----
  1924. The probability density function for `genhalflogistic` is:
  1925. .. math::
  1926. f(x, c) = \frac{2 (1 - c x)^{1/(c-1)}}{[1 + (1 - c x)^{1/c}]^2}
  1927. for :math:`0 \le x \le 1/c`, and :math:`c > 0`.
  1928. `genhalflogistic` takes ``c`` as a shape parameter for :math:`c`.
  1929. %(after_notes)s
  1930. %(example)s
  1931. """
  1932. def _argcheck(self, c):
  1933. self.b = 1.0 / c
  1934. return c > 0
  1935. def _pdf(self, x, c):
  1936. # genhalflogistic.pdf(x, c) =
  1937. # 2 * (1-c*x)**(1/c-1) / (1+(1-c*x)**(1/c))**2
  1938. limit = 1.0/c
  1939. tmp = np.asarray(1-c*x)
  1940. tmp0 = tmp**(limit-1)
  1941. tmp2 = tmp0*tmp
  1942. return 2*tmp0 / (1+tmp2)**2
  1943. def _cdf(self, x, c):
  1944. limit = 1.0/c
  1945. tmp = np.asarray(1-c*x)
  1946. tmp2 = tmp**(limit)
  1947. return (1.0-tmp2) / (1+tmp2)
  1948. def _ppf(self, q, c):
  1949. return 1.0/c*(1-((1.0-q)/(1.0+q))**c)
  1950. def _entropy(self, c):
  1951. return 2 - (2*c+1)*np.log(2)
  1952. genhalflogistic = genhalflogistic_gen(a=0.0, name='genhalflogistic')
  1953. class gompertz_gen(rv_continuous):
  1954. r"""A Gompertz (or truncated Gumbel) continuous random variable.
  1955. %(before_notes)s
  1956. Notes
  1957. -----
  1958. The probability density function for `gompertz` is:
  1959. .. math::
  1960. f(x, c) = c \exp(x) \exp(-c (e^x-1))
  1961. for :math:`x \ge 0`, :math:`c > 0`.
  1962. `gompertz` takes ``c`` as a shape parameter for :math:`c`.
  1963. %(after_notes)s
  1964. %(example)s
  1965. """
  1966. def _pdf(self, x, c):
  1967. # gompertz.pdf(x, c) = c * exp(x) * exp(-c*(exp(x)-1))
  1968. return np.exp(self._logpdf(x, c))
  1969. def _logpdf(self, x, c):
  1970. return np.log(c) + x - c * sc.expm1(x)
  1971. def _cdf(self, x, c):
  1972. return -sc.expm1(-c * sc.expm1(x))
  1973. def _ppf(self, q, c):
  1974. return sc.log1p(-1.0 / c * sc.log1p(-q))
  1975. def _entropy(self, c):
  1976. return 1.0 - np.log(c) - np.exp(c)*sc.expn(1, c)
  1977. gompertz = gompertz_gen(a=0.0, name='gompertz')
  1978. class gumbel_r_gen(rv_continuous):
  1979. r"""A right-skewed Gumbel continuous random variable.
  1980. %(before_notes)s
  1981. See Also
  1982. --------
  1983. gumbel_l, gompertz, genextreme
  1984. Notes
  1985. -----
  1986. The probability density function for `gumbel_r` is:
  1987. .. math::
  1988. f(x) = \exp(-(x + e^{-x}))
  1989. The Gumbel distribution is sometimes referred to as a type I Fisher-Tippett
  1990. distribution. It is also related to the extreme value distribution,
  1991. log-Weibull and Gompertz distributions.
  1992. %(after_notes)s
  1993. %(example)s
  1994. """
  1995. def _pdf(self, x):
  1996. # gumbel_r.pdf(x) = exp(-(x + exp(-x)))
  1997. return np.exp(self._logpdf(x))
  1998. def _logpdf(self, x):
  1999. return -x - np.exp(-x)
  2000. def _cdf(self, x):
  2001. return np.exp(-np.exp(-x))
  2002. def _logcdf(self, x):
  2003. return -np.exp(-x)
  2004. def _ppf(self, q):
  2005. return -np.log(-np.log(q))
  2006. def _stats(self):
  2007. return _EULER, np.pi*np.pi/6.0, 12*np.sqrt(6)/np.pi**3 * _ZETA3, 12.0/5
  2008. def _entropy(self):
  2009. # https://en.wikipedia.org/wiki/Gumbel_distribution
  2010. return _EULER + 1.
  2011. gumbel_r = gumbel_r_gen(name='gumbel_r')
  2012. class gumbel_l_gen(rv_continuous):
  2013. r"""A left-skewed Gumbel continuous random variable.
  2014. %(before_notes)s
  2015. See Also
  2016. --------
  2017. gumbel_r, gompertz, genextreme
  2018. Notes
  2019. -----
  2020. The probability density function for `gumbel_l` is:
  2021. .. math::
  2022. f(x) = \exp(x - e^x)
  2023. The Gumbel distribution is sometimes referred to as a type I Fisher-Tippett
  2024. distribution. It is also related to the extreme value distribution,
  2025. log-Weibull and Gompertz distributions.
  2026. %(after_notes)s
  2027. %(example)s
  2028. """
  2029. def _pdf(self, x):
  2030. # gumbel_l.pdf(x) = exp(x - exp(x))
  2031. return np.exp(self._logpdf(x))
  2032. def _logpdf(self, x):
  2033. return x - np.exp(x)
  2034. def _cdf(self, x):
  2035. return -sc.expm1(-np.exp(x))
  2036. def _ppf(self, q):
  2037. return np.log(-sc.log1p(-q))
  2038. def _logsf(self, x):
  2039. return -np.exp(x)
  2040. def _sf(self, x):
  2041. return np.exp(-np.exp(x))
  2042. def _isf(self, x):
  2043. return np.log(-np.log(x))
  2044. def _stats(self):
  2045. return -_EULER, np.pi*np.pi/6.0, \
  2046. -12*np.sqrt(6)/np.pi**3 * _ZETA3, 12.0/5
  2047. def _entropy(self):
  2048. return _EULER + 1.
  2049. gumbel_l = gumbel_l_gen(name='gumbel_l')
  2050. class halfcauchy_gen(rv_continuous):
  2051. r"""A Half-Cauchy continuous random variable.
  2052. %(before_notes)s
  2053. Notes
  2054. -----
  2055. The probability density function for `halfcauchy` is:
  2056. .. math::
  2057. f(x) = \frac{2}{\pi (1 + x^2)}
  2058. for :math:`x \ge 0`.
  2059. %(after_notes)s
  2060. %(example)s
  2061. """
  2062. def _pdf(self, x):
  2063. # halfcauchy.pdf(x) = 2 / (pi * (1 + x**2))
  2064. return 2.0/np.pi/(1.0+x*x)
  2065. def _logpdf(self, x):
  2066. return np.log(2.0/np.pi) - sc.log1p(x*x)
  2067. def _cdf(self, x):
  2068. return 2.0/np.pi*np.arctan(x)
  2069. def _ppf(self, q):
  2070. return np.tan(np.pi/2*q)
  2071. def _stats(self):
  2072. return np.inf, np.inf, np.nan, np.nan
  2073. def _entropy(self):
  2074. return np.log(2*np.pi)
  2075. halfcauchy = halfcauchy_gen(a=0.0, name='halfcauchy')
  2076. class halflogistic_gen(rv_continuous):
  2077. r"""A half-logistic continuous random variable.
  2078. %(before_notes)s
  2079. Notes
  2080. -----
  2081. The probability density function for `halflogistic` is:
  2082. .. math::
  2083. f(x) = \frac{ 2 e^{-x} }{ (1+e^{-x})^2 }
  2084. = \frac{1}{2} \text{sech}(x/2)^2
  2085. for :math:`x \ge 0`.
  2086. %(after_notes)s
  2087. %(example)s
  2088. """
  2089. def _pdf(self, x):
  2090. # halflogistic.pdf(x) = 2 * exp(-x) / (1+exp(-x))**2
  2091. # = 1/2 * sech(x/2)**2
  2092. return np.exp(self._logpdf(x))
  2093. def _logpdf(self, x):
  2094. return np.log(2) - x - 2. * sc.log1p(np.exp(-x))
  2095. def _cdf(self, x):
  2096. return np.tanh(x/2.0)
  2097. def _ppf(self, q):
  2098. return 2*np.arctanh(q)
  2099. def _munp(self, n):
  2100. if n == 1:
  2101. return 2*np.log(2)
  2102. if n == 2:
  2103. return np.pi*np.pi/3.0
  2104. if n == 3:
  2105. return 9*_ZETA3
  2106. if n == 4:
  2107. return 7*np.pi**4 / 15.0
  2108. return 2*(1-pow(2.0, 1-n))*sc.gamma(n+1)*sc.zeta(n, 1)
  2109. def _entropy(self):
  2110. return 2-np.log(2)
  2111. halflogistic = halflogistic_gen(a=0.0, name='halflogistic')
  2112. class halfnorm_gen(rv_continuous):
  2113. r"""A half-normal continuous random variable.
  2114. %(before_notes)s
  2115. Notes
  2116. -----
  2117. The probability density function for `halfnorm` is:
  2118. .. math::
  2119. f(x) = \sqrt{2/\pi} \exp(-x^2 / 2)
  2120. for :math:`x > 0`.
  2121. `halfnorm` is a special case of `chi` with ``df=1``.
  2122. %(after_notes)s
  2123. %(example)s
  2124. """
  2125. def _rvs(self):
  2126. return abs(self._random_state.standard_normal(size=self._size))
  2127. def _pdf(self, x):
  2128. # halfnorm.pdf(x) = sqrt(2/pi) * exp(-x**2/2)
  2129. return np.sqrt(2.0/np.pi)*np.exp(-x*x/2.0)
  2130. def _logpdf(self, x):
  2131. return 0.5 * np.log(2.0/np.pi) - x*x/2.0
  2132. def _cdf(self, x):
  2133. return _norm_cdf(x)*2-1.0
  2134. def _ppf(self, q):
  2135. return sc.ndtri((1+q)/2.0)
  2136. def _stats(self):
  2137. return (np.sqrt(2.0/np.pi),
  2138. 1-2.0/np.pi,
  2139. np.sqrt(2)*(4-np.pi)/(np.pi-2)**1.5,
  2140. 8*(np.pi-3)/(np.pi-2)**2)
  2141. def _entropy(self):
  2142. return 0.5*np.log(np.pi/2.0)+0.5
  2143. halfnorm = halfnorm_gen(a=0.0, name='halfnorm')
  2144. class hypsecant_gen(rv_continuous):
  2145. r"""A hyperbolic secant continuous random variable.
  2146. %(before_notes)s
  2147. Notes
  2148. -----
  2149. The probability density function for `hypsecant` is:
  2150. .. math::
  2151. f(x) = \frac{1}{\pi} \text{sech}(x)
  2152. for a real number :math:`x`.
  2153. %(after_notes)s
  2154. %(example)s
  2155. """
  2156. def _pdf(self, x):
  2157. # hypsecant.pdf(x) = 1/pi * sech(x)
  2158. return 1.0/(np.pi*np.cosh(x))
  2159. def _cdf(self, x):
  2160. return 2.0/np.pi*np.arctan(np.exp(x))
  2161. def _ppf(self, q):
  2162. return np.log(np.tan(np.pi*q/2.0))
  2163. def _stats(self):
  2164. return 0, np.pi*np.pi/4, 0, 2
  2165. def _entropy(self):
  2166. return np.log(2*np.pi)
  2167. hypsecant = hypsecant_gen(name='hypsecant')
  2168. class gausshyper_gen(rv_continuous):
  2169. r"""A Gauss hypergeometric continuous random variable.
  2170. %(before_notes)s
  2171. Notes
  2172. -----
  2173. The probability density function for `gausshyper` is:
  2174. .. math::
  2175. f(x, a, b, c, z) = C x^{a-1} (1-x)^{b-1} (1+zx)^{-c}
  2176. for :math:`0 \le x \le 1`, :math:`a > 0`, :math:`b > 0`, and
  2177. :math:`C = \frac{1}{B(a, b) F[2, 1](c, a; a+b; -z)}`.
  2178. :math:`F[2, 1]` is the Gauss hypergeometric function
  2179. `scipy.special.hyp2f1`.
  2180. `gausshyper` takes :math:`a`, :math:`b`, :math:`c` and :math:`z` as shape
  2181. parameters.
  2182. %(after_notes)s
  2183. %(example)s
  2184. """
  2185. def _argcheck(self, a, b, c, z):
  2186. return (a > 0) & (b > 0) & (c == c) & (z == z)
  2187. def _pdf(self, x, a, b, c, z):
  2188. # gausshyper.pdf(x, a, b, c, z) =
  2189. # C * x**(a-1) * (1-x)**(b-1) * (1+z*x)**(-c)
  2190. Cinv = sc.gamma(a)*sc.gamma(b)/sc.gamma(a+b)*sc.hyp2f1(c, a, a+b, -z)
  2191. return 1.0/Cinv * x**(a-1.0) * (1.0-x)**(b-1.0) / (1.0+z*x)**c
  2192. def _munp(self, n, a, b, c, z):
  2193. fac = sc.beta(n+a, b) / sc.beta(a, b)
  2194. num = sc.hyp2f1(c, a+n, a+b+n, -z)
  2195. den = sc.hyp2f1(c, a, a+b, -z)
  2196. return fac*num / den
  2197. gausshyper = gausshyper_gen(a=0.0, b=1.0, name='gausshyper')
  2198. class invgamma_gen(rv_continuous):
  2199. r"""An inverted gamma continuous random variable.
  2200. %(before_notes)s
  2201. Notes
  2202. -----
  2203. The probability density function for `invgamma` is:
  2204. .. math::
  2205. f(x, a) = \frac{x^{-a-1}}{\Gamma(a)} \exp(-\frac{1}{x})
  2206. for :math:`x > 0`, :math:`a > 0`. :math:`\Gamma` is the gamma function
  2207. (`scipy.special.gamma`).
  2208. `invgamma` takes ``a`` as a shape parameter for :math:`a`.
  2209. `invgamma` is a special case of `gengamma` with ``c=-1``.
  2210. %(after_notes)s
  2211. %(example)s
  2212. """
  2213. _support_mask = rv_continuous._open_support_mask
  2214. def _pdf(self, x, a):
  2215. # invgamma.pdf(x, a) = x**(-a-1) / gamma(a) * exp(-1/x)
  2216. return np.exp(self._logpdf(x, a))
  2217. def _logpdf(self, x, a):
  2218. return -(a+1) * np.log(x) - sc.gammaln(a) - 1.0/x
  2219. def _cdf(self, x, a):
  2220. return sc.gammaincc(a, 1.0 / x)
  2221. def _ppf(self, q, a):
  2222. return 1.0 / sc.gammainccinv(a, q)
  2223. def _sf(self, x, a):
  2224. return sc.gammainc(a, 1.0 / x)
  2225. def _isf(self, q, a):
  2226. return 1.0 / sc.gammaincinv(a, q)
  2227. def _stats(self, a, moments='mvsk'):
  2228. m1 = _lazywhere(a > 1, (a,), lambda x: 1. / (x - 1.), np.inf)
  2229. m2 = _lazywhere(a > 2, (a,), lambda x: 1. / (x - 1.)**2 / (x - 2.),
  2230. np.inf)
  2231. g1, g2 = None, None
  2232. if 's' in moments:
  2233. g1 = _lazywhere(
  2234. a > 3, (a,),
  2235. lambda x: 4. * np.sqrt(x - 2.) / (x - 3.), np.nan)
  2236. if 'k' in moments:
  2237. g2 = _lazywhere(
  2238. a > 4, (a,),
  2239. lambda x: 6. * (5. * x - 11.) / (x - 3.) / (x - 4.), np.nan)
  2240. return m1, m2, g1, g2
  2241. def _entropy(self, a):
  2242. return a - (a+1.0) * sc.psi(a) + sc.gammaln(a)
  2243. invgamma = invgamma_gen(a=0.0, name='invgamma')
  2244. # scale is gamma from DATAPLOT and B from Regress
  2245. class invgauss_gen(rv_continuous):
  2246. r"""An inverse Gaussian continuous random variable.
  2247. %(before_notes)s
  2248. Notes
  2249. -----
  2250. The probability density function for `invgauss` is:
  2251. .. math::
  2252. f(x, \mu) = \frac{1}{\sqrt{2 \pi x^3}}
  2253. \exp(-\frac{(x-\mu)^2}{2 x \mu^2})
  2254. for :math:`x > 0` and :math:`\mu > 0`.
  2255. `invgauss` takes ``mu`` as a shape parameter for :math:`\mu`.
  2256. %(after_notes)s
  2257. When :math:`\mu` is too small, evaluating the cumulative distribution
  2258. function will be inaccurate due to ``cdf(mu -> 0) = inf * 0``.
  2259. NaNs are returned for :math:`\mu \le 0.0028`.
  2260. %(example)s
  2261. """
  2262. _support_mask = rv_continuous._open_support_mask
  2263. def _rvs(self, mu):
  2264. return self._random_state.wald(mu, 1.0, size=self._size)
  2265. def _pdf(self, x, mu):
  2266. # invgauss.pdf(x, mu) =
  2267. # 1 / sqrt(2*pi*x**3) * exp(-(x-mu)**2/(2*x*mu**2))
  2268. return 1.0/np.sqrt(2*np.pi*x**3.0)*np.exp(-1.0/(2*x)*((x-mu)/mu)**2)
  2269. def _logpdf(self, x, mu):
  2270. return -0.5*np.log(2*np.pi) - 1.5*np.log(x) - ((x-mu)/mu)**2/(2*x)
  2271. def _cdf(self, x, mu):
  2272. fac = np.sqrt(1.0/x)
  2273. # Numerical accuracy for small `mu` is bad. See #869.
  2274. C1 = _norm_cdf(fac*(x-mu)/mu)
  2275. C1 += np.exp(1.0/mu) * _norm_cdf(-fac*(x+mu)/mu) * np.exp(1.0/mu)
  2276. return C1
  2277. def _stats(self, mu):
  2278. return mu, mu**3.0, 3*np.sqrt(mu), 15*mu
  2279. invgauss = invgauss_gen(a=0.0, name='invgauss')
  2280. class norminvgauss_gen(rv_continuous):
  2281. r"""A Normal Inverse Gaussian continuous random variable.
  2282. %(before_notes)s
  2283. Notes
  2284. -----
  2285. The probability density function for `norminvgauss` is:
  2286. .. math::
  2287. f(x, a, b) = (a \exp(\sqrt{a^2 - b^2} + b x)) /
  2288. (\pi \sqrt{1 + x^2} \, K_1(a \sqrt{1 + x^2}))
  2289. where `x` is a real number, the parameter `a` is the tail heaviness
  2290. and `b` is the asymmetry parameter satisfying `a > 0` and `abs(b) <= a`.
  2291. :math:`K_1` is the modified Bessel function of second kind
  2292. (`scipy.special.k1`).
  2293. %(after_notes)s
  2294. A normal inverse Gaussian random variable `Y` with parameters `a` and `b`
  2295. can be expressed as a normal mean-variance mixture:
  2296. `Y = b * V + sqrt(V) * X` where `X` is `norm(0,1)` and `V` is
  2297. `invgauss(mu=1/sqrt(a**2 - b**2))`. This representation is used
  2298. to generate random variates.
  2299. References
  2300. ----------
  2301. O. Barndorff-Nielsen, "Hyperbolic Distributions and Distributions on
  2302. Hyperbolae", Scandinavian Journal of Statistics, Vol. 5(3),
  2303. pp. 151-157, 1978.
  2304. O. Barndorff-Nielsen, "Normal Inverse Gaussian Distributions and Stochastic
  2305. Volatility Modelling", Scandinavian Journal of Statistics, Vol. 24,
  2306. pp. 1-13, 1997.
  2307. %(example)s
  2308. """
  2309. _support_mask = rv_continuous._open_support_mask
  2310. def _argcheck(self, a, b):
  2311. return (a > 0) & (np.absolute(b) < a)
  2312. def _pdf(self, x, a, b):
  2313. gamma = np.sqrt(a**2 - b**2)
  2314. fac1 = a / np.pi * np.exp(gamma)
  2315. sq = np.hypot(1, x) # reduce overflows
  2316. return fac1 * sc.k1e(a * sq) * np.exp(b*x - a*sq) / sq
  2317. def _rvs(self, a, b):
  2318. # note: X = b * V + sqrt(V) * X is norminvgaus(a,b) if X is standard
  2319. # normal and V is invgauss(mu=1/sqrt(a**2 - b**2))
  2320. gamma = np.sqrt(a**2 - b**2)
  2321. sz, rndm = self._size, self._random_state
  2322. ig = invgauss.rvs(mu=1/gamma, size=sz, random_state=rndm)
  2323. return b * ig + np.sqrt(ig) * norm.rvs(size=sz, random_state=rndm)
  2324. def _stats(self, a, b):
  2325. gamma = np.sqrt(a**2 - b**2)
  2326. mean = b / gamma
  2327. variance = a**2 / gamma**3
  2328. skewness = 3.0 * b / (a * np.sqrt(gamma))
  2329. kurtosis = 3.0 * (1 + 4 * b**2 / a**2) / gamma
  2330. return mean, variance, skewness, kurtosis
  2331. norminvgauss = norminvgauss_gen(name="norminvgauss")
  2332. class invweibull_gen(rv_continuous):
  2333. u"""An inverted Weibull continuous random variable.
  2334. This distribution is also known as the Fréchet distribution or the
  2335. type II extreme value distribution.
  2336. %(before_notes)s
  2337. Notes
  2338. -----
  2339. The probability density function for `invweibull` is:
  2340. .. math::
  2341. f(x, c) = c x^{-c-1} \\exp(-x^{-c})
  2342. for :math:`x > 0`, :math:`c > 0`.
  2343. `invweibull` takes ``c`` as a shape parameter for :math:`c`.
  2344. %(after_notes)s
  2345. References
  2346. ----------
  2347. F.R.S. de Gusmao, E.M.M Ortega and G.M. Cordeiro, "The generalized inverse
  2348. Weibull distribution", Stat. Papers, vol. 52, pp. 591-619, 2011.
  2349. %(example)s
  2350. """
  2351. _support_mask = rv_continuous._open_support_mask
  2352. def _pdf(self, x, c):
  2353. # invweibull.pdf(x, c) = c * x**(-c-1) * exp(-x**(-c))
  2354. xc1 = np.power(x, -c - 1.0)
  2355. xc2 = np.power(x, -c)
  2356. xc2 = np.exp(-xc2)
  2357. return c * xc1 * xc2
  2358. def _cdf(self, x, c):
  2359. xc1 = np.power(x, -c)
  2360. return np.exp(-xc1)
  2361. def _ppf(self, q, c):
  2362. return np.power(-np.log(q), -1.0/c)
  2363. def _munp(self, n, c):
  2364. return sc.gamma(1 - n / c)
  2365. def _entropy(self, c):
  2366. return 1+_EULER + _EULER / c - np.log(c)
  2367. invweibull = invweibull_gen(a=0, name='invweibull')
  2368. class johnsonsb_gen(rv_continuous):
  2369. r"""A Johnson SB continuous random variable.
  2370. %(before_notes)s
  2371. See Also
  2372. --------
  2373. johnsonsu
  2374. Notes
  2375. -----
  2376. The probability density function for `johnsonsb` is:
  2377. .. math::
  2378. f(x, a, b) = \frac{b}{x(1-x)} \phi(a + b \log \frac{x}{1-x} )
  2379. for :math:`0 < x < 1` and :math:`a, b > 0`, and :math:`\phi` is the normal
  2380. pdf.
  2381. `johnsonsb` takes :math:`a` and :math:`b` as shape parameters.
  2382. %(after_notes)s
  2383. %(example)s
  2384. """
  2385. _support_mask = rv_continuous._open_support_mask
  2386. def _argcheck(self, a, b):
  2387. return (b > 0) & (a == a)
  2388. def _pdf(self, x, a, b):
  2389. # johnsonsb.pdf(x, a, b) = b / (x*(1-x)) * phi(a + b * log(x/(1-x)))
  2390. trm = _norm_pdf(a + b*np.log(x/(1.0-x)))
  2391. return b*1.0/(x*(1-x))*trm
  2392. def _cdf(self, x, a, b):
  2393. return _norm_cdf(a + b*np.log(x/(1.0-x)))
  2394. def _ppf(self, q, a, b):
  2395. return 1.0 / (1 + np.exp(-1.0 / b * (_norm_ppf(q) - a)))
  2396. johnsonsb = johnsonsb_gen(a=0.0, b=1.0, name='johnsonsb')
  2397. class johnsonsu_gen(rv_continuous):
  2398. r"""A Johnson SU continuous random variable.
  2399. %(before_notes)s
  2400. See Also
  2401. --------
  2402. johnsonsb
  2403. Notes
  2404. -----
  2405. The probability density function for `johnsonsu` is:
  2406. .. math::
  2407. f(x, a, b) = \frac{b}{\sqrt{x^2 + 1}}
  2408. \phi(a + b \log(x + \sqrt{x^2 + 1}))
  2409. for all :math:`x, a, b > 0`, and :math:`\phi` is the normal pdf.
  2410. `johnsonsu` takes :math:`a` and :math:`b` as shape parameters.
  2411. %(after_notes)s
  2412. %(example)s
  2413. """
  2414. def _argcheck(self, a, b):
  2415. return (b > 0) & (a == a)
  2416. def _pdf(self, x, a, b):
  2417. # johnsonsu.pdf(x, a, b) = b / sqrt(x**2 + 1) *
  2418. # phi(a + b * log(x + sqrt(x**2 + 1)))
  2419. x2 = x*x
  2420. trm = _norm_pdf(a + b * np.log(x + np.sqrt(x2+1)))
  2421. return b*1.0/np.sqrt(x2+1.0)*trm
  2422. def _cdf(self, x, a, b):
  2423. return _norm_cdf(a + b * np.log(x + np.sqrt(x*x + 1)))
  2424. def _ppf(self, q, a, b):
  2425. return np.sinh((_norm_ppf(q) - a) / b)
  2426. johnsonsu = johnsonsu_gen(name='johnsonsu')
  2427. class laplace_gen(rv_continuous):
  2428. r"""A Laplace continuous random variable.
  2429. %(before_notes)s
  2430. Notes
  2431. -----
  2432. The probability density function for `laplace` is
  2433. .. math::
  2434. f(x) = \frac{1}{2} \exp(-|x|)
  2435. for a real number :math:`x`.
  2436. %(after_notes)s
  2437. %(example)s
  2438. """
  2439. def _rvs(self):
  2440. return self._random_state.laplace(0, 1, size=self._size)
  2441. def _pdf(self, x):
  2442. # laplace.pdf(x) = 1/2 * exp(-abs(x))
  2443. return 0.5*np.exp(-abs(x))
  2444. def _cdf(self, x):
  2445. return np.where(x > 0, 1.0-0.5*np.exp(-x), 0.5*np.exp(x))
  2446. def _ppf(self, q):
  2447. return np.where(q > 0.5, -np.log(2*(1-q)), np.log(2*q))
  2448. def _stats(self):
  2449. return 0, 2, 0, 3
  2450. def _entropy(self):
  2451. return np.log(2)+1
  2452. laplace = laplace_gen(name='laplace')
  2453. class levy_gen(rv_continuous):
  2454. r"""A Levy continuous random variable.
  2455. %(before_notes)s
  2456. See Also
  2457. --------
  2458. levy_stable, levy_l
  2459. Notes
  2460. -----
  2461. The probability density function for `levy` is:
  2462. .. math::
  2463. f(x) = \frac{1}{\sqrt{2\pi x^3}} \exp\left(-\frac{1}{2x}\right)
  2464. for :math:`x > 0`.
  2465. This is the same as the Levy-stable distribution with :math:`a=1/2` and
  2466. :math:`b=1`.
  2467. %(after_notes)s
  2468. %(example)s
  2469. """
  2470. _support_mask = rv_continuous._open_support_mask
  2471. def _pdf(self, x):
  2472. # levy.pdf(x) = 1 / (x * sqrt(2*pi*x)) * exp(-1/(2*x))
  2473. return 1 / np.sqrt(2*np.pi*x) / x * np.exp(-1/(2*x))
  2474. def _cdf(self, x):
  2475. # Equivalent to 2*norm.sf(np.sqrt(1/x))
  2476. return sc.erfc(np.sqrt(0.5 / x))
  2477. def _ppf(self, q):
  2478. # Equivalent to 1.0/(norm.isf(q/2)**2) or 0.5/(erfcinv(q)**2)
  2479. val = -sc.ndtri(q/2)
  2480. return 1.0 / (val * val)
  2481. def _stats(self):
  2482. return np.inf, np.inf, np.nan, np.nan
  2483. levy = levy_gen(a=0.0, name="levy")
  2484. class levy_l_gen(rv_continuous):
  2485. r"""A left-skewed Levy continuous random variable.
  2486. %(before_notes)s
  2487. See Also
  2488. --------
  2489. levy, levy_stable
  2490. Notes
  2491. -----
  2492. The probability density function for `levy_l` is:
  2493. .. math::
  2494. f(x) = \frac{1}{|x| \sqrt{2\pi |x|}} \exp{ \left(-\frac{1}{2|x|} \right)}
  2495. for :math:`x < 0`.
  2496. This is the same as the Levy-stable distribution with :math:`a=1/2` and
  2497. :math:`b=-1`.
  2498. %(after_notes)s
  2499. %(example)s
  2500. """
  2501. _support_mask = rv_continuous._open_support_mask
  2502. def _pdf(self, x):
  2503. # levy_l.pdf(x) = 1 / (abs(x) * sqrt(2*pi*abs(x))) * exp(-1/(2*abs(x)))
  2504. ax = abs(x)
  2505. return 1/np.sqrt(2*np.pi*ax)/ax*np.exp(-1/(2*ax))
  2506. def _cdf(self, x):
  2507. ax = abs(x)
  2508. return 2 * _norm_cdf(1 / np.sqrt(ax)) - 1
  2509. def _ppf(self, q):
  2510. val = _norm_ppf((q + 1.0) / 2)
  2511. return -1.0 / (val * val)
  2512. def _stats(self):
  2513. return np.inf, np.inf, np.nan, np.nan
  2514. levy_l = levy_l_gen(b=0.0, name="levy_l")
  2515. class levy_stable_gen(rv_continuous):
  2516. r"""A Levy-stable continuous random variable.
  2517. %(before_notes)s
  2518. See Also
  2519. --------
  2520. levy, levy_l
  2521. Notes
  2522. -----
  2523. The distribution for `levy_stable` has characteristic function:
  2524. .. math::
  2525. \varphi(t, \alpha, \beta, c, \mu) =
  2526. e^{it\mu -|ct|^{\alpha}(1-i\beta \operatorname{sign}(t)\Phi(\alpha, t))}
  2527. where:
  2528. .. math::
  2529. \Phi = \begin{cases}
  2530. \tan \left({\frac {\pi \alpha }{2}}\right)&\alpha \neq 1\\
  2531. -{\frac {2}{\pi }}\log |t|&\alpha =1
  2532. \end{cases}
  2533. The probability density function for `levy_stable` is:
  2534. .. math::
  2535. f(x) = \frac{1}{2\pi}\int_{-\infty}^\infty \varphi(t)e^{-ixt}\,dt
  2536. where :math:`-\infty < t < \infty`. This integral does not have a known closed form.
  2537. For evaluation of pdf we use either Zolotarev :math:`S_0` parameterization with integration,
  2538. direct integration of standard parameterization of characteristic function or FFT of
  2539. characteristic function. If set to other than None and if number of points is greater than
  2540. ``levy_stable.pdf_fft_min_points_threshold`` (defaults to None) we use FFT otherwise we use one
  2541. of the other methods.
  2542. The default method is 'best' which uses Zolotarev's method if alpha = 1 and integration of
  2543. characteristic function otherwise. The default method can be changed by setting
  2544. ``levy_stable.pdf_default_method`` to either 'zolotarev', 'quadrature' or 'best'.
  2545. To increase accuracy of FFT calculation one can specify ``levy_stable.pdf_fft_grid_spacing``
  2546. (defaults to 0.001) and ``pdf_fft_n_points_two_power`` (defaults to a value that covers the
  2547. input range * 4). Setting ``pdf_fft_n_points_two_power`` to 16 should be sufficiently accurate
  2548. in most cases at the expense of CPU time.
  2549. For evaluation of cdf we use Zolatarev :math:`S_0` parameterization with integration or integral of
  2550. the pdf FFT interpolated spline. The settings affecting FFT calculation are the same as
  2551. for pdf calculation. Setting the threshold to ``None`` (default) will disable FFT. For cdf
  2552. calculations the Zolatarev method is superior in accuracy, so FFT is disabled by default.
  2553. Fitting estimate uses quantile estimation method in [MC]. MLE estimation of parameters in
  2554. fit method uses this quantile estimate initially. Note that MLE doesn't always converge if
  2555. using FFT for pdf calculations; so it's best that ``pdf_fft_min_points_threshold`` is left unset.
  2556. .. warning::
  2557. For pdf calculations implementation of Zolatarev is unstable for values where alpha = 1 and
  2558. beta != 0. In this case the quadrature method is recommended. FFT calculation is also
  2559. considered experimental.
  2560. For cdf calculations FFT calculation is considered experimental. Use Zolatarev's method
  2561. instead (default).
  2562. %(after_notes)s
  2563. References
  2564. ----------
  2565. .. [MC] McCulloch, J., 1986. Simple consistent estimators of stable distribution parameters.
  2566. Communications in Statistics - Simulation and Computation 15, 11091136.
  2567. .. [MS] Mittnik, S.T. Rachev, T. Doganoglu, D. Chenyao, 1999. Maximum likelihood estimation
  2568. of stable Paretian models, Mathematical and Computer Modelling, Volume 29, Issue 10,
  2569. 1999, Pages 275-293.
  2570. .. [BS] Borak, S., Hardle, W., Rafal, W. 2005. Stable distributions, Economic Risk.
  2571. %(example)s
  2572. """
  2573. def _rvs(self, alpha, beta):
  2574. def alpha1func(alpha, beta, TH, aTH, bTH, cosTH, tanTH, W):
  2575. return (2/np.pi*(np.pi/2 + bTH)*tanTH -
  2576. beta*np.log((np.pi/2*W*cosTH)/(np.pi/2 + bTH)))
  2577. def beta0func(alpha, beta, TH, aTH, bTH, cosTH, tanTH, W):
  2578. return (W/(cosTH/np.tan(aTH) + np.sin(TH)) *
  2579. ((np.cos(aTH) + np.sin(aTH)*tanTH)/W)**(1.0/alpha))
  2580. def otherwise(alpha, beta, TH, aTH, bTH, cosTH, tanTH, W):
  2581. # alpha is not 1 and beta is not 0
  2582. val0 = beta*np.tan(np.pi*alpha/2)
  2583. th0 = np.arctan(val0)/alpha
  2584. val3 = W/(cosTH/np.tan(alpha*(th0 + TH)) + np.sin(TH))
  2585. res3 = val3*((np.cos(aTH) + np.sin(aTH)*tanTH -
  2586. val0*(np.sin(aTH) - np.cos(aTH)*tanTH))/W)**(1.0/alpha)
  2587. return res3
  2588. def alphanot1func(alpha, beta, TH, aTH, bTH, cosTH, tanTH, W):
  2589. res = _lazywhere(beta == 0,
  2590. (alpha, beta, TH, aTH, bTH, cosTH, tanTH, W),
  2591. beta0func, f2=otherwise)
  2592. return res
  2593. sz = self._size
  2594. alpha = broadcast_to(alpha, sz)
  2595. beta = broadcast_to(beta, sz)
  2596. TH = uniform.rvs(loc=-np.pi/2.0, scale=np.pi, size=sz,
  2597. random_state=self._random_state)
  2598. W = expon.rvs(size=sz, random_state=self._random_state)
  2599. aTH = alpha*TH
  2600. bTH = beta*TH
  2601. cosTH = np.cos(TH)
  2602. tanTH = np.tan(TH)
  2603. res = _lazywhere(alpha == 1,
  2604. (alpha, beta, TH, aTH, bTH, cosTH, tanTH, W),
  2605. alpha1func, f2=alphanot1func)
  2606. return res
  2607. def _argcheck(self, alpha, beta):
  2608. return (alpha > 0) & (alpha <= 2) & (beta <= 1) & (beta >= -1)
  2609. @staticmethod
  2610. def _cf(t, alpha, beta):
  2611. Phi = lambda alpha, t: np.tan(np.pi*alpha/2) if alpha != 1 else -2.0*np.log(np.abs(t))/np.pi
  2612. return np.exp(-(np.abs(t)**alpha)*(1-1j*beta*np.sign(t)*Phi(alpha, t)))
  2613. @staticmethod
  2614. def _pdf_from_cf_with_fft(cf, h=0.01, q=9):
  2615. """Calculates pdf from cf using fft. Using region around 0 with N=2**q points
  2616. separated by distance h. As suggested by [MS].
  2617. """
  2618. N = 2**q
  2619. n = np.arange(1,N+1)
  2620. density = ((-1)**(n-1-N/2))*np.fft.fft(((-1)**(n-1))*cf(2*np.pi*(n-1-N/2)/h/N))/h/N
  2621. x = (n-1-N/2)*h
  2622. return (x, density)
  2623. @staticmethod
  2624. def _pdf_single_value_best(x, alpha, beta):
  2625. if alpha != 1. or (alpha == 1. and beta == 0.):
  2626. return levy_stable_gen._pdf_single_value_zolotarev(x, alpha, beta)
  2627. else:
  2628. return levy_stable_gen._pdf_single_value_cf_integrate(x, alpha, beta)
  2629. @staticmethod
  2630. def _pdf_single_value_cf_integrate(x, alpha, beta):
  2631. cf = lambda t: levy_stable_gen._cf(t, alpha, beta)
  2632. return integrate.quad(lambda t: np.real(np.exp(-1j*t*x)*cf(t)), -np.inf, np.inf, limit=1000)[0]/np.pi/2
  2633. @staticmethod
  2634. def _pdf_single_value_zolotarev(x, alpha, beta):
  2635. """Calculate pdf using Zolotarev's methods as detailed in [BS].
  2636. """
  2637. zeta = -beta*np.tan(np.pi*alpha/2.)
  2638. if alpha != 1:
  2639. x0 = x + zeta # convert to S_0 parameterization
  2640. xi = np.arctan(-zeta)/alpha
  2641. def V(theta):
  2642. return np.cos(alpha*xi)**(1/(alpha-1)) * \
  2643. (np.cos(theta)/np.sin(alpha*(xi+theta)))**(alpha/(alpha-1)) * \
  2644. (np.cos(alpha*xi+(alpha-1)*theta)/np.cos(theta))
  2645. if x0 > zeta:
  2646. def g(theta):
  2647. return V(theta)*np.real(np.complex(x0-zeta)**(alpha/(alpha-1)))
  2648. def f(theta):
  2649. return g(theta) * np.exp(-g(theta))
  2650. # spare calculating integral on null set
  2651. # use isclose as macos has fp differences
  2652. if np.isclose(-xi, np.pi/2, rtol=1e-014, atol=1e-014):
  2653. return 0.
  2654. with np.errstate(all="ignore"):
  2655. intg_max = optimize.minimize_scalar(lambda theta: -f(theta), bounds=[-xi, np.pi/2])
  2656. intg_kwargs = {}
  2657. # windows quadpack less forgiving with points out of bounds
  2658. if intg_max.success and not np.isnan(intg_max.fun)\
  2659. and intg_max.x > -xi and intg_max.x < np.pi/2:
  2660. intg_kwargs["points"] = [intg_max.x]
  2661. intg = integrate.quad(f, -xi, np.pi/2, **intg_kwargs)[0]
  2662. return alpha * intg / np.pi / np.abs(alpha-1) / (x0-zeta)
  2663. elif x0 == zeta:
  2664. return sc.gamma(1+1/alpha)*np.cos(xi)/np.pi/((1+zeta**2)**(1/alpha/2))
  2665. else:
  2666. return levy_stable_gen._pdf_single_value_zolotarev(-x, alpha, -beta)
  2667. else:
  2668. # since location zero, no need to reposition x for S_0 parameterization
  2669. xi = np.pi/2
  2670. if beta != 0:
  2671. warnings.warn('Density calculation unstable for alpha=1 and beta!=0.' +
  2672. ' Use quadrature method instead.', RuntimeWarning)
  2673. def V(theta):
  2674. expr_1 = np.pi/2+beta*theta
  2675. return 2. * expr_1 * np.exp(expr_1*np.tan(theta)/beta) / np.cos(theta) / np.pi
  2676. def g(theta):
  2677. return np.exp(-np.pi * x / 2. / beta) * V(theta)
  2678. def f(theta):
  2679. return g(theta) * np.exp(-g(theta))
  2680. with np.errstate(all="ignore"):
  2681. intg_max = optimize.minimize_scalar(lambda theta: -f(theta), bounds=[-np.pi/2, np.pi/2])
  2682. intg = integrate.fixed_quad(f, -np.pi/2, intg_max.x)[0] + integrate.fixed_quad(f, intg_max.x, np.pi/2)[0]
  2683. return intg / np.abs(beta) / 2.
  2684. else:
  2685. return 1/(1+x**2)/np.pi
  2686. @staticmethod
  2687. def _cdf_single_value_zolotarev(x, alpha, beta):
  2688. """Calculate cdf using Zolotarev's methods as detailed in [BS].
  2689. """
  2690. zeta = -beta*np.tan(np.pi*alpha/2.)
  2691. if alpha != 1:
  2692. x0 = x + zeta # convert to S_0 parameterization
  2693. xi = np.arctan(-zeta)/alpha
  2694. def V(theta):
  2695. return np.cos(alpha*xi)**(1/(alpha-1)) * \
  2696. (np.cos(theta)/np.sin(alpha*(xi+theta)))**(alpha/(alpha-1)) * \
  2697. (np.cos(alpha*xi+(alpha-1)*theta)/np.cos(theta))
  2698. if x0 > zeta:
  2699. c_1 = 1 if alpha > 1 else .5 - xi/np.pi
  2700. def f(theta):
  2701. return np.exp(-V(theta)*np.real(np.complex(x0-zeta)**(alpha/(alpha-1))))
  2702. with np.errstate(all="ignore"):
  2703. # spare calculating integral on null set
  2704. # use isclose as macos has fp differences
  2705. if np.isclose(-xi, np.pi/2, rtol=1e-014, atol=1e-014):
  2706. intg = 0
  2707. else:
  2708. intg = integrate.quad(f, -xi, np.pi/2)[0]
  2709. return c_1 + np.sign(1-alpha) * intg / np.pi
  2710. elif x0 == zeta:
  2711. return .5 - xi/np.pi
  2712. else:
  2713. return 1 - levy_stable_gen._cdf_single_value_zolotarev(-x, alpha, -beta)
  2714. else:
  2715. # since location zero, no need to reposition x for S_0 parameterization
  2716. xi = np.pi/2
  2717. if beta > 0:
  2718. def V(theta):
  2719. expr_1 = np.pi/2+beta*theta
  2720. return 2. * expr_1 * np.exp(expr_1*np.tan(theta)/beta) / np.cos(theta) / np.pi
  2721. with np.errstate(all="ignore"):
  2722. expr_1 = np.exp(-np.pi*x/beta/2.)
  2723. int_1 = integrate.quad(lambda theta: np.exp(-expr_1 * V(theta)), -np.pi/2, np.pi/2)[0]
  2724. return int_1 / np.pi
  2725. elif beta == 0:
  2726. return .5 + np.arctan(x)/np.pi
  2727. else:
  2728. return 1 - levy_stable_gen._cdf_single_value_zolotarev(-x, 1, -beta)
  2729. def _pdf(self, x, alpha, beta):
  2730. x = np.asarray(x).reshape(1, -1)[0,:]
  2731. x, alpha, beta = np.broadcast_arrays(x, alpha, beta)
  2732. data_in = np.dstack((x, alpha, beta))[0]
  2733. data_out = np.empty(shape=(len(data_in),1))
  2734. pdf_default_method_name = getattr(self, 'pdf_default_method', 'best')
  2735. if pdf_default_method_name == 'best':
  2736. pdf_single_value_method = levy_stable_gen._pdf_single_value_best
  2737. elif pdf_default_method_name == 'zolotarev':
  2738. pdf_single_value_method = levy_stable_gen._pdf_single_value_zolotarev
  2739. else:
  2740. pdf_single_value_method = levy_stable_gen._pdf_single_value_cf_integrate
  2741. fft_min_points_threshold = getattr(self, 'pdf_fft_min_points_threshold', None)
  2742. fft_grid_spacing = getattr(self, 'pdf_fft_grid_spacing', 0.001)
  2743. fft_n_points_two_power = getattr(self, 'pdf_fft_n_points_two_power', None)
  2744. # group data in unique arrays of alpha, beta pairs
  2745. uniq_param_pairs = np.vstack(list({tuple(row) for row in
  2746. data_in[:, 1:]}))
  2747. for pair in uniq_param_pairs:
  2748. data_mask = np.all(data_in[:,1:] == pair, axis=-1)
  2749. data_subset = data_in[data_mask]
  2750. if fft_min_points_threshold is None or len(data_subset) < fft_min_points_threshold:
  2751. data_out[data_mask] = np.array([pdf_single_value_method(_x, _alpha, _beta)
  2752. for _x, _alpha, _beta in data_subset]).reshape(len(data_subset), 1)
  2753. else:
  2754. warnings.warn('Density calculations experimental for FFT method.' +
  2755. ' Use combination of zolatarev and quadrature methods instead.', RuntimeWarning)
  2756. _alpha, _beta = pair
  2757. _x = data_subset[:,(0,)]
  2758. # need enough points to "cover" _x for interpolation
  2759. h = fft_grid_spacing
  2760. q = np.ceil(np.log(2*np.max(np.abs(_x))/h)/np.log(2)) + 2 if fft_n_points_two_power is None else int(fft_n_points_two_power)
  2761. density_x, density = levy_stable_gen._pdf_from_cf_with_fft(lambda t: levy_stable_gen._cf(t, _alpha, _beta), h=h, q=q)
  2762. f = interpolate.interp1d(density_x, np.real(density))
  2763. data_out[data_mask] = f(_x)
  2764. return data_out.T[0]
  2765. def _cdf(self, x, alpha, beta):
  2766. x = np.asarray(x).reshape(1, -1)[0,:]
  2767. x, alpha, beta = np.broadcast_arrays(x, alpha, beta)
  2768. data_in = np.dstack((x, alpha, beta))[0]
  2769. data_out = np.empty(shape=(len(data_in),1))
  2770. fft_min_points_threshold = getattr(self, 'pdf_fft_min_points_threshold', None)
  2771. fft_grid_spacing = getattr(self, 'pdf_fft_grid_spacing', 0.001)
  2772. fft_n_points_two_power = getattr(self, 'pdf_fft_n_points_two_power', None)
  2773. # group data in unique arrays of alpha, beta pairs
  2774. uniq_param_pairs = np.vstack(
  2775. list({tuple(row) for row in data_in[:,1:]}))
  2776. for pair in uniq_param_pairs:
  2777. data_mask = np.all(data_in[:,1:] == pair, axis=-1)
  2778. data_subset = data_in[data_mask]
  2779. if fft_min_points_threshold is None or len(data_subset) < fft_min_points_threshold:
  2780. data_out[data_mask] = np.array([levy_stable._cdf_single_value_zolotarev(_x, _alpha, _beta)
  2781. for _x, _alpha, _beta in data_subset]).reshape(len(data_subset), 1)
  2782. else:
  2783. warnings.warn(u'FFT method is considered experimental for ' +
  2784. u'cumulative distribution function ' +
  2785. u'evaluations. Use Zolotarev’s method instead).',
  2786. RuntimeWarning)
  2787. _alpha, _beta = pair
  2788. _x = data_subset[:,(0,)]
  2789. # need enough points to "cover" _x for interpolation
  2790. h = fft_grid_spacing
  2791. q = 16 if fft_n_points_two_power is None else int(fft_n_points_two_power)
  2792. density_x, density = levy_stable_gen._pdf_from_cf_with_fft(lambda t: levy_stable_gen._cf(t, _alpha, _beta), h=h, q=q)
  2793. f = interpolate.InterpolatedUnivariateSpline(density_x, np.real(density))
  2794. data_out[data_mask] = np.array([f.integral(self.a, x_1) for x_1 in _x]).reshape(data_out[data_mask].shape)
  2795. return data_out.T[0]
  2796. def _fitstart(self, data):
  2797. # We follow McCullock 1986 method - Simple Consistent Estimators
  2798. # of Stable Distribution Parameters
  2799. # Table III and IV
  2800. nu_alpha_range = [2.439, 2.5, 2.6, 2.7, 2.8, 3, 3.2, 3.5, 4, 5, 6, 8, 10, 15, 25]
  2801. nu_beta_range = [0, 0.1, 0.2, 0.3, 0.5, 0.7, 1]
  2802. # table III - alpha = psi_1(nu_alpha, nu_beta)
  2803. alpha_table = [
  2804. [2.000, 2.000, 2.000, 2.000, 2.000, 2.000, 2.000],
  2805. [1.916, 1.924, 1.924, 1.924, 1.924, 1.924, 1.924],
  2806. [1.808, 1.813, 1.829, 1.829, 1.829, 1.829, 1.829],
  2807. [1.729, 1.730, 1.737, 1.745, 1.745, 1.745, 1.745],
  2808. [1.664, 1.663, 1.663, 1.668, 1.676, 1.676, 1.676],
  2809. [1.563, 1.560, 1.553, 1.548, 1.547, 1.547, 1.547],
  2810. [1.484, 1.480, 1.471, 1.460, 1.448, 1.438, 1.438],
  2811. [1.391, 1.386, 1.378, 1.364, 1.337, 1.318, 1.318],
  2812. [1.279, 1.273, 1.266, 1.250, 1.210, 1.184, 1.150],
  2813. [1.128, 1.121, 1.114, 1.101, 1.067, 1.027, 0.973],
  2814. [1.029, 1.021, 1.014, 1.004, 0.974, 0.935, 0.874],
  2815. [0.896, 0.892, 0.884, 0.883, 0.855, 0.823, 0.769],
  2816. [0.818, 0.812, 0.806, 0.801, 0.780, 0.756, 0.691],
  2817. [0.698, 0.695, 0.692, 0.689, 0.676, 0.656, 0.597],
  2818. [0.593, 0.590, 0.588, 0.586, 0.579, 0.563, 0.513]]
  2819. # table IV - beta = psi_2(nu_alpha, nu_beta)
  2820. beta_table = [
  2821. [0, 2.160, 1.000, 1.000, 1.000, 1.000, 1.000],
  2822. [0, 1.592, 3.390, 1.000, 1.000, 1.000, 1.000],
  2823. [0, 0.759, 1.800, 1.000, 1.000, 1.000, 1.000],
  2824. [0, 0.482, 1.048, 1.694, 1.000, 1.000, 1.000],
  2825. [0, 0.360, 0.760, 1.232, 2.229, 1.000, 1.000],
  2826. [0, 0.253, 0.518, 0.823, 1.575, 1.000, 1.000],
  2827. [0, 0.203, 0.410, 0.632, 1.244, 1.906, 1.000],
  2828. [0, 0.165, 0.332, 0.499, 0.943, 1.560, 1.000],
  2829. [0, 0.136, 0.271, 0.404, 0.689, 1.230, 2.195],
  2830. [0, 0.109, 0.216, 0.323, 0.539, 0.827, 1.917],
  2831. [0, 0.096, 0.190, 0.284, 0.472, 0.693, 1.759],
  2832. [0, 0.082, 0.163, 0.243, 0.412, 0.601, 1.596],
  2833. [0, 0.074, 0.147, 0.220, 0.377, 0.546, 1.482],
  2834. [0, 0.064, 0.128, 0.191, 0.330, 0.478, 1.362],
  2835. [0, 0.056, 0.112, 0.167, 0.285, 0.428, 1.274]]
  2836. # Table V and VII
  2837. alpha_range = [2, 1.9, 1.8, 1.7, 1.6, 1.5, 1.4, 1.3, 1.2, 1.1, 1, 0.9, 0.8, 0.7, 0.6, 0.5]
  2838. beta_range = [0, 0.25, 0.5, 0.75, 1]
  2839. # Table V - nu_c = psi_3(alpha, beta)
  2840. nu_c_table = [
  2841. [1.908, 1.908, 1.908, 1.908, 1.908],
  2842. [1.914, 1.915, 1.916, 1.918, 1.921],
  2843. [1.921, 1.922, 1.927, 1.936, 1.947],
  2844. [1.927, 1.930, 1.943, 1.961, 1.987],
  2845. [1.933, 1.940, 1.962, 1.997, 2.043],
  2846. [1.939, 1.952, 1.988, 2.045, 2.116],
  2847. [1.946, 1.967, 2.022, 2.106, 2.211],
  2848. [1.955, 1.984, 2.067, 2.188, 2.333],
  2849. [1.965, 2.007, 2.125, 2.294, 2.491],
  2850. [1.980, 2.040, 2.205, 2.435, 2.696],
  2851. [2.000, 2.085, 2.311, 2.624, 2.973],
  2852. [2.040, 2.149, 2.461, 2.886, 3.356],
  2853. [2.098, 2.244, 2.676, 3.265, 3.912],
  2854. [2.189, 2.392, 3.004, 3.844, 4.775],
  2855. [2.337, 2.634, 3.542, 4.808, 6.247],
  2856. [2.588, 3.073, 4.534, 6.636, 9.144]]
  2857. # Table VII - nu_zeta = psi_5(alpha, beta)
  2858. nu_zeta_table = [
  2859. [0, 0.000, 0.000, 0.000, 0.000],
  2860. [0, -0.017, -0.032, -0.049, -0.064],
  2861. [0, -0.030, -0.061, -0.092, -0.123],
  2862. [0, -0.043, -0.088, -0.132, -0.179],
  2863. [0, -0.056, -0.111, -0.170, -0.232],
  2864. [0, -0.066, -0.134, -0.206, -0.283],
  2865. [0, -0.075, -0.154, -0.241, -0.335],
  2866. [0, -0.084, -0.173, -0.276, -0.390],
  2867. [0, -0.090, -0.192, -0.310, -0.447],
  2868. [0, -0.095, -0.208, -0.346, -0.508],
  2869. [0, -0.098, -0.223, -0.380, -0.576],
  2870. [0, -0.099, -0.237, -0.424, -0.652],
  2871. [0, -0.096, -0.250, -0.469, -0.742],
  2872. [0, -0.089, -0.262, -0.520, -0.853],
  2873. [0, -0.078, -0.272, -0.581, -0.997],
  2874. [0, -0.061, -0.279, -0.659, -1.198]]
  2875. psi_1 = interpolate.interp2d(nu_beta_range, nu_alpha_range, alpha_table, kind='linear')
  2876. psi_2 = interpolate.interp2d(nu_beta_range, nu_alpha_range, beta_table, kind='linear')
  2877. psi_2_1 = lambda nu_beta, nu_alpha: psi_2(nu_beta, nu_alpha) if nu_beta > 0 else -psi_2(-nu_beta, nu_alpha)
  2878. phi_3 = interpolate.interp2d(beta_range, alpha_range, nu_c_table, kind='linear')
  2879. phi_3_1 = lambda beta, alpha: phi_3(beta, alpha) if beta > 0 else phi_3(-beta, alpha)
  2880. phi_5 = interpolate.interp2d(beta_range, alpha_range, nu_zeta_table, kind='linear')
  2881. phi_5_1 = lambda beta, alpha: phi_5(beta, alpha) if beta > 0 else -phi_5(-beta, alpha)
  2882. # quantiles
  2883. p05 = np.percentile(data, 5)
  2884. p50 = np.percentile(data, 50)
  2885. p95 = np.percentile(data, 95)
  2886. p25 = np.percentile(data, 25)
  2887. p75 = np.percentile(data, 75)
  2888. nu_alpha = (p95 - p05)/(p75 - p25)
  2889. nu_beta = (p95 + p05 - 2*p50)/(p95 - p05)
  2890. if nu_alpha >= 2.439:
  2891. alpha = np.clip(psi_1(nu_beta, nu_alpha)[0], np.finfo(float).eps, 2.)
  2892. beta = np.clip(psi_2_1(nu_beta, nu_alpha)[0], -1., 1.)
  2893. else:
  2894. alpha = 2.0
  2895. beta = np.sign(nu_beta)
  2896. c = (p75 - p25) / phi_3_1(beta, alpha)[0]
  2897. zeta = p50 + c*phi_5_1(beta, alpha)[0]
  2898. delta = np.clip(zeta-beta*c*np.tan(np.pi*alpha/2.) if alpha == 1. else zeta, np.finfo(float).eps, np.inf)
  2899. return (alpha, beta, delta, c)
  2900. def _stats(self, alpha, beta):
  2901. mu = 0 if alpha > 1 else np.nan
  2902. mu2 = 2 if alpha == 2 else np.inf
  2903. g1 = 0. if alpha == 2. else np.NaN
  2904. g2 = 0. if alpha == 2. else np.NaN
  2905. return mu, mu2, g1, g2
  2906. levy_stable = levy_stable_gen(name='levy_stable')
  2907. class logistic_gen(rv_continuous):
  2908. r"""A logistic (or Sech-squared) continuous random variable.
  2909. %(before_notes)s
  2910. Notes
  2911. -----
  2912. The probability density function for `logistic` is:
  2913. .. math::
  2914. f(x) = \frac{\exp(-x)}
  2915. {(1+\exp(-x))^2}
  2916. `logistic` is a special case of `genlogistic` with ``c=1``.
  2917. %(after_notes)s
  2918. %(example)s
  2919. """
  2920. def _rvs(self):
  2921. return self._random_state.logistic(size=self._size)
  2922. def _pdf(self, x):
  2923. # logistic.pdf(x) = exp(-x) / (1+exp(-x))**2
  2924. return np.exp(self._logpdf(x))
  2925. def _logpdf(self, x):
  2926. return -x - 2. * sc.log1p(np.exp(-x))
  2927. def _cdf(self, x):
  2928. return sc.expit(x)
  2929. def _ppf(self, q):
  2930. return sc.logit(q)
  2931. def _sf(self, x):
  2932. return sc.expit(-x)
  2933. def _isf(self, q):
  2934. return -sc.logit(q)
  2935. def _stats(self):
  2936. return 0, np.pi*np.pi/3.0, 0, 6.0/5.0
  2937. def _entropy(self):
  2938. # https://en.wikipedia.org/wiki/Logistic_distribution
  2939. return 2.0
  2940. logistic = logistic_gen(name='logistic')
  2941. class loggamma_gen(rv_continuous):
  2942. r"""A log gamma continuous random variable.
  2943. %(before_notes)s
  2944. Notes
  2945. -----
  2946. The probability density function for `loggamma` is:
  2947. .. math::
  2948. f(x, c) = \frac{\exp(c x - \exp(x))}
  2949. {\Gamma(c)}
  2950. for all :math:`x, c > 0`. Here, :math:`\Gamma` is the
  2951. gamma function (`scipy.special.gamma`).
  2952. `loggamma` takes ``c`` as a shape parameter for :math:`c`.
  2953. %(after_notes)s
  2954. %(example)s
  2955. """
  2956. def _rvs(self, c):
  2957. return np.log(self._random_state.gamma(c, size=self._size))
  2958. def _pdf(self, x, c):
  2959. # loggamma.pdf(x, c) = exp(c*x-exp(x)) / gamma(c)
  2960. return np.exp(c*x-np.exp(x)-sc.gammaln(c))
  2961. def _cdf(self, x, c):
  2962. return sc.gammainc(c, np.exp(x))
  2963. def _ppf(self, q, c):
  2964. return np.log(sc.gammaincinv(c, q))
  2965. def _stats(self, c):
  2966. # See, for example, "A Statistical Study of Log-Gamma Distribution", by
  2967. # Ping Shing Chan (thesis, McMaster University, 1993).
  2968. mean = sc.digamma(c)
  2969. var = sc.polygamma(1, c)
  2970. skewness = sc.polygamma(2, c) / np.power(var, 1.5)
  2971. excess_kurtosis = sc.polygamma(3, c) / (var*var)
  2972. return mean, var, skewness, excess_kurtosis
  2973. loggamma = loggamma_gen(name='loggamma')
  2974. class loglaplace_gen(rv_continuous):
  2975. r"""A log-Laplace continuous random variable.
  2976. %(before_notes)s
  2977. Notes
  2978. -----
  2979. The probability density function for `loglaplace` is:
  2980. .. math::
  2981. f(x, c) = \begin{cases}\frac{c}{2} x^{ c-1} &\text{for } 0 < x < 1\\
  2982. \frac{c}{2} x^{-c-1} &\text{for } x \ge 1
  2983. \end{cases}
  2984. for :math:`c > 0`.
  2985. `loglaplace` takes ``c`` as a shape parameter for :math:`c`.
  2986. %(after_notes)s
  2987. References
  2988. ----------
  2989. T.J. Kozubowski and K. Podgorski, "A log-Laplace growth rate model",
  2990. The Mathematical Scientist, vol. 28, pp. 49-60, 2003.
  2991. %(example)s
  2992. """
  2993. def _pdf(self, x, c):
  2994. # loglaplace.pdf(x, c) = c / 2 * x**(c-1), for 0 < x < 1
  2995. # = c / 2 * x**(-c-1), for x >= 1
  2996. cd2 = c/2.0
  2997. c = np.where(x < 1, c, -c)
  2998. return cd2*x**(c-1)
  2999. def _cdf(self, x, c):
  3000. return np.where(x < 1, 0.5*x**c, 1-0.5*x**(-c))
  3001. def _ppf(self, q, c):
  3002. return np.where(q < 0.5, (2.0*q)**(1.0/c), (2*(1.0-q))**(-1.0/c))
  3003. def _munp(self, n, c):
  3004. return c**2 / (c**2 - n**2)
  3005. def _entropy(self, c):
  3006. return np.log(2.0/c) + 1.0
  3007. loglaplace = loglaplace_gen(a=0.0, name='loglaplace')
  3008. def _lognorm_logpdf(x, s):
  3009. return _lazywhere(x != 0, (x, s),
  3010. lambda x, s: -np.log(x)**2 / (2*s**2) - np.log(s*x*np.sqrt(2*np.pi)),
  3011. -np.inf)
  3012. class lognorm_gen(rv_continuous):
  3013. r"""A lognormal continuous random variable.
  3014. %(before_notes)s
  3015. Notes
  3016. -----
  3017. The probability density function for `lognorm` is:
  3018. .. math::
  3019. f(x, s) = \frac{1}{s x \sqrt{2\pi}}
  3020. \exp\left(-\frac{\log^2(x)}{2s^2}\right)
  3021. for :math:`x > 0`, :math:`s > 0`.
  3022. `lognorm` takes ``s`` as a shape parameter for :math:`s`.
  3023. %(after_notes)s
  3024. A common parametrization for a lognormal random variable ``Y`` is in
  3025. terms of the mean, ``mu``, and standard deviation, ``sigma``, of the
  3026. unique normally distributed random variable ``X`` such that exp(X) = Y.
  3027. This parametrization corresponds to setting ``s = sigma`` and ``scale =
  3028. exp(mu)``.
  3029. %(example)s
  3030. """
  3031. _support_mask = rv_continuous._open_support_mask
  3032. def _rvs(self, s):
  3033. return np.exp(s * self._random_state.standard_normal(self._size))
  3034. def _pdf(self, x, s):
  3035. # lognorm.pdf(x, s) = 1 / (s*x*sqrt(2*pi)) * exp(-1/2*(log(x)/s)**2)
  3036. return np.exp(self._logpdf(x, s))
  3037. def _logpdf(self, x, s):
  3038. return _lognorm_logpdf(x, s)
  3039. def _cdf(self, x, s):
  3040. return _norm_cdf(np.log(x) / s)
  3041. def _logcdf(self, x, s):
  3042. return _norm_logcdf(np.log(x) / s)
  3043. def _ppf(self, q, s):
  3044. return np.exp(s * _norm_ppf(q))
  3045. def _sf(self, x, s):
  3046. return _norm_sf(np.log(x) / s)
  3047. def _logsf(self, x, s):
  3048. return _norm_logsf(np.log(x) / s)
  3049. def _stats(self, s):
  3050. p = np.exp(s*s)
  3051. mu = np.sqrt(p)
  3052. mu2 = p*(p-1)
  3053. g1 = np.sqrt((p-1))*(2+p)
  3054. g2 = np.polyval([1, 2, 3, 0, -6.0], p)
  3055. return mu, mu2, g1, g2
  3056. def _entropy(self, s):
  3057. return 0.5 * (1 + np.log(2*np.pi) + 2 * np.log(s))
  3058. @extend_notes_in_docstring(rv_continuous, notes="""\
  3059. When the location parameter is fixed by using the `floc` argument,
  3060. this function uses explicit formulas for the maximum likelihood
  3061. estimation of the log-normal shape and scale parameters, so the
  3062. `optimizer`, `loc` and `scale` keyword arguments are ignored.\n\n""")
  3063. def fit(self, data, *args, **kwds):
  3064. floc = kwds.get('floc', None)
  3065. if floc is None:
  3066. # loc is not fixed. Use the default fit method.
  3067. return super(lognorm_gen, self).fit(data, *args, **kwds)
  3068. f0 = (kwds.get('f0', None) or kwds.get('fs', None) or
  3069. kwds.get('fix_s', None))
  3070. fscale = kwds.get('fscale', None)
  3071. if len(args) > 1:
  3072. raise TypeError("Too many input arguments.")
  3073. for name in ['f0', 'fs', 'fix_s', 'floc', 'fscale', 'loc', 'scale',
  3074. 'optimizer']:
  3075. kwds.pop(name, None)
  3076. if kwds:
  3077. raise TypeError("Unknown arguments: %s." % kwds)
  3078. # Special case: loc is fixed. Use the maximum likelihood formulas
  3079. # instead of the numerical solver.
  3080. if f0 is not None and fscale is not None:
  3081. # This check is for consistency with `rv_continuous.fit`.
  3082. raise ValueError("All parameters fixed. There is nothing to "
  3083. "optimize.")
  3084. data = np.asarray(data)
  3085. floc = float(floc)
  3086. if floc != 0:
  3087. # Shifting the data by floc. Don't do the subtraction in-place,
  3088. # because `data` might be a view of the input array.
  3089. data = data - floc
  3090. if np.any(data <= 0):
  3091. raise FitDataError("lognorm", lower=floc, upper=np.inf)
  3092. lndata = np.log(data)
  3093. # Three cases to handle:
  3094. # * shape and scale both free
  3095. # * shape fixed, scale free
  3096. # * shape free, scale fixed
  3097. if fscale is None:
  3098. # scale is free.
  3099. scale = np.exp(lndata.mean())
  3100. if f0 is None:
  3101. # shape is free.
  3102. shape = lndata.std()
  3103. else:
  3104. # shape is fixed.
  3105. shape = float(f0)
  3106. else:
  3107. # scale is fixed, shape is free
  3108. scale = float(fscale)
  3109. shape = np.sqrt(((lndata - np.log(scale))**2).mean())
  3110. return shape, floc, scale
  3111. lognorm = lognorm_gen(a=0.0, name='lognorm')
  3112. class gilbrat_gen(rv_continuous):
  3113. r"""A Gilbrat continuous random variable.
  3114. %(before_notes)s
  3115. Notes
  3116. -----
  3117. The probability density function for `gilbrat` is:
  3118. .. math::
  3119. f(x) = \frac{1}{x \sqrt{2\pi}} \exp(-\frac{1}{2} (\log(x))^2)
  3120. `gilbrat` is a special case of `lognorm` with ``s=1``.
  3121. %(after_notes)s
  3122. %(example)s
  3123. """
  3124. _support_mask = rv_continuous._open_support_mask
  3125. def _rvs(self):
  3126. return np.exp(self._random_state.standard_normal(self._size))
  3127. def _pdf(self, x):
  3128. # gilbrat.pdf(x) = 1/(x*sqrt(2*pi)) * exp(-1/2*(log(x))**2)
  3129. return np.exp(self._logpdf(x))
  3130. def _logpdf(self, x):
  3131. return _lognorm_logpdf(x, 1.0)
  3132. def _cdf(self, x):
  3133. return _norm_cdf(np.log(x))
  3134. def _ppf(self, q):
  3135. return np.exp(_norm_ppf(q))
  3136. def _stats(self):
  3137. p = np.e
  3138. mu = np.sqrt(p)
  3139. mu2 = p * (p - 1)
  3140. g1 = np.sqrt((p - 1)) * (2 + p)
  3141. g2 = np.polyval([1, 2, 3, 0, -6.0], p)
  3142. return mu, mu2, g1, g2
  3143. def _entropy(self):
  3144. return 0.5 * np.log(2 * np.pi) + 0.5
  3145. gilbrat = gilbrat_gen(a=0.0, name='gilbrat')
  3146. class maxwell_gen(rv_continuous):
  3147. r"""A Maxwell continuous random variable.
  3148. %(before_notes)s
  3149. Notes
  3150. -----
  3151. A special case of a `chi` distribution, with ``df=3``, ``loc=0.0``,
  3152. and given ``scale = a``, where ``a`` is the parameter used in the
  3153. Mathworld description [1]_.
  3154. The probability density function for `maxwell` is:
  3155. .. math::
  3156. f(x) = \sqrt{2/\pi}x^2 \exp(-x^2/2)
  3157. for :math:`x > 0`.
  3158. %(after_notes)s
  3159. References
  3160. ----------
  3161. .. [1] http://mathworld.wolfram.com/MaxwellDistribution.html
  3162. %(example)s
  3163. """
  3164. def _rvs(self):
  3165. return chi.rvs(3.0, size=self._size, random_state=self._random_state)
  3166. def _pdf(self, x):
  3167. # maxwell.pdf(x) = sqrt(2/pi)x**2 * exp(-x**2/2)
  3168. return np.sqrt(2.0/np.pi)*x*x*np.exp(-x*x/2.0)
  3169. def _cdf(self, x):
  3170. return sc.gammainc(1.5, x*x/2.0)
  3171. def _ppf(self, q):
  3172. return np.sqrt(2*sc.gammaincinv(1.5, q))
  3173. def _stats(self):
  3174. val = 3*np.pi-8
  3175. return (2*np.sqrt(2.0/np.pi),
  3176. 3-8/np.pi,
  3177. np.sqrt(2)*(32-10*np.pi)/val**1.5,
  3178. (-12*np.pi*np.pi + 160*np.pi - 384) / val**2.0)
  3179. def _entropy(self):
  3180. return _EULER + 0.5*np.log(2*np.pi)-0.5
  3181. maxwell = maxwell_gen(a=0.0, name='maxwell')
  3182. class mielke_gen(rv_continuous):
  3183. r"""A Mielke's Beta-Kappa continuous random variable.
  3184. %(before_notes)s
  3185. Notes
  3186. -----
  3187. The probability density function for `mielke` is:
  3188. .. math::
  3189. f(x, k, s) = \frac{k x^{k-1}}{(1+x^s)^{1+k/s}}
  3190. for :math:`x > 0` and :math:`k, s > 0`.
  3191. `mielke` takes ``k`` and ``s`` as shape parameters.
  3192. %(after_notes)s
  3193. %(example)s
  3194. """
  3195. def _pdf(self, x, k, s):
  3196. # mielke.pdf(x, k, s) = k * x**(k-1) / (1+x**s)**(1+k/s)
  3197. return k*x**(k-1.0) / (1.0+x**s)**(1.0+k*1.0/s)
  3198. def _cdf(self, x, k, s):
  3199. return x**k / (1.0+x**s)**(k*1.0/s)
  3200. def _ppf(self, q, k, s):
  3201. qsk = pow(q, s*1.0/k)
  3202. return pow(qsk/(1.0-qsk), 1.0/s)
  3203. mielke = mielke_gen(a=0.0, name='mielke')
  3204. class kappa4_gen(rv_continuous):
  3205. r"""Kappa 4 parameter distribution.
  3206. %(before_notes)s
  3207. Notes
  3208. -----
  3209. The probability density function for kappa4 is:
  3210. .. math::
  3211. f(x, h, k) = (1 - k x)^{1/k - 1} (1 - h (1 - k x)^{1/k})^{1/h-1}
  3212. if :math:`h` and :math:`k` are not equal to 0.
  3213. If :math:`h` or :math:`k` are zero then the pdf can be simplified:
  3214. h = 0 and k != 0::
  3215. kappa4.pdf(x, h, k) = (1.0 - k*x)**(1.0/k - 1.0)*
  3216. exp(-(1.0 - k*x)**(1.0/k))
  3217. h != 0 and k = 0::
  3218. kappa4.pdf(x, h, k) = exp(-x)*(1.0 - h*exp(-x))**(1.0/h - 1.0)
  3219. h = 0 and k = 0::
  3220. kappa4.pdf(x, h, k) = exp(-x)*exp(-exp(-x))
  3221. kappa4 takes :math:`h` and :math:`k` as shape parameters.
  3222. The kappa4 distribution returns other distributions when certain
  3223. :math:`h` and :math:`k` values are used.
  3224. +------+-------------+----------------+------------------+
  3225. | h | k=0.0 | k=1.0 | -inf<=k<=inf |
  3226. +======+=============+================+==================+
  3227. | -1.0 | Logistic | | Generalized |
  3228. | | | | Logistic(1) |
  3229. | | | | |
  3230. | | logistic(x) | | |
  3231. +------+-------------+----------------+------------------+
  3232. | 0.0 | Gumbel | Reverse | Generalized |
  3233. | | | Exponential(2) | Extreme Value |
  3234. | | | | |
  3235. | | gumbel_r(x) | | genextreme(x, k) |
  3236. +------+-------------+----------------+------------------+
  3237. | 1.0 | Exponential | Uniform | Generalized |
  3238. | | | | Pareto |
  3239. | | | | |
  3240. | | expon(x) | uniform(x) | genpareto(x, -k) |
  3241. +------+-------------+----------------+------------------+
  3242. (1) There are at least five generalized logistic distributions.
  3243. Four are described here:
  3244. https://en.wikipedia.org/wiki/Generalized_logistic_distribution
  3245. The "fifth" one is the one kappa4 should match which currently
  3246. isn't implemented in scipy:
  3247. https://en.wikipedia.org/wiki/Talk:Generalized_logistic_distribution
  3248. https://www.mathwave.com/help/easyfit/html/analyses/distributions/gen_logistic.html
  3249. (2) This distribution is currently not in scipy.
  3250. References
  3251. ----------
  3252. J.C. Finney, "Optimization of a Skewed Logistic Distribution With Respect
  3253. to the Kolmogorov-Smirnov Test", A Dissertation Submitted to the Graduate
  3254. Faculty of the Louisiana State University and Agricultural and Mechanical
  3255. College, (August, 2004),
  3256. https://digitalcommons.lsu.edu/gradschool_dissertations/3672
  3257. J.R.M. Hosking, "The four-parameter kappa distribution". IBM J. Res.
  3258. Develop. 38 (3), 25 1-258 (1994).
  3259. B. Kumphon, A. Kaew-Man, P. Seenoi, "A Rainfall Distribution for the Lampao
  3260. Site in the Chi River Basin, Thailand", Journal of Water Resource and
  3261. Protection, vol. 4, 866-869, (2012).
  3262. https://doi.org/10.4236/jwarp.2012.410101
  3263. C. Winchester, "On Estimation of the Four-Parameter Kappa Distribution", A
  3264. Thesis Submitted to Dalhousie University, Halifax, Nova Scotia, (March
  3265. 2000).
  3266. http://www.nlc-bnc.ca/obj/s4/f2/dsk2/ftp01/MQ57336.pdf
  3267. %(after_notes)s
  3268. %(example)s
  3269. """
  3270. def _argcheck(self, h, k):
  3271. condlist = [np.logical_and(h > 0, k > 0),
  3272. np.logical_and(h > 0, k == 0),
  3273. np.logical_and(h > 0, k < 0),
  3274. np.logical_and(h <= 0, k > 0),
  3275. np.logical_and(h <= 0, k == 0),
  3276. np.logical_and(h <= 0, k < 0)]
  3277. def f0(h, k):
  3278. return (1.0 - float_power(h, -k))/k
  3279. def f1(h, k):
  3280. return np.log(h)
  3281. def f3(h, k):
  3282. a = np.empty(np.shape(h))
  3283. a[:] = -np.inf
  3284. return a
  3285. def f5(h, k):
  3286. return 1.0/k
  3287. self.a = _lazyselect(condlist,
  3288. [f0, f1, f0, f3, f3, f5],
  3289. [h, k],
  3290. default=np.nan)
  3291. def f0(h, k):
  3292. return 1.0/k
  3293. def f1(h, k):
  3294. a = np.empty(np.shape(h))
  3295. a[:] = np.inf
  3296. return a
  3297. self.b = _lazyselect(condlist,
  3298. [f0, f1, f1, f0, f1, f1],
  3299. [h, k],
  3300. default=np.nan)
  3301. return h == h
  3302. def _pdf(self, x, h, k):
  3303. # kappa4.pdf(x, h, k) = (1.0 - k*x)**(1.0/k - 1.0)*
  3304. # (1.0 - h*(1.0 - k*x)**(1.0/k))**(1.0/h-1)
  3305. return np.exp(self._logpdf(x, h, k))
  3306. def _logpdf(self, x, h, k):
  3307. condlist = [np.logical_and(h != 0, k != 0),
  3308. np.logical_and(h == 0, k != 0),
  3309. np.logical_and(h != 0, k == 0),
  3310. np.logical_and(h == 0, k == 0)]
  3311. def f0(x, h, k):
  3312. '''pdf = (1.0 - k*x)**(1.0/k - 1.0)*(
  3313. 1.0 - h*(1.0 - k*x)**(1.0/k))**(1.0/h-1.0)
  3314. logpdf = ...
  3315. '''
  3316. return (sc.xlog1py(1.0/k - 1.0, -k*x) +
  3317. sc.xlog1py(1.0/h - 1.0, -h*(1.0 - k*x)**(1.0/k)))
  3318. def f1(x, h, k):
  3319. '''pdf = (1.0 - k*x)**(1.0/k - 1.0)*np.exp(-(
  3320. 1.0 - k*x)**(1.0/k))
  3321. logpdf = ...
  3322. '''
  3323. return sc.xlog1py(1.0/k - 1.0, -k*x) - (1.0 - k*x)**(1.0/k)
  3324. def f2(x, h, k):
  3325. '''pdf = np.exp(-x)*(1.0 - h*np.exp(-x))**(1.0/h - 1.0)
  3326. logpdf = ...
  3327. '''
  3328. return -x + sc.xlog1py(1.0/h - 1.0, -h*np.exp(-x))
  3329. def f3(x, h, k):
  3330. '''pdf = np.exp(-x-np.exp(-x))
  3331. logpdf = ...
  3332. '''
  3333. return -x - np.exp(-x)
  3334. return _lazyselect(condlist,
  3335. [f0, f1, f2, f3],
  3336. [x, h, k],
  3337. default=np.nan)
  3338. def _cdf(self, x, h, k):
  3339. return np.exp(self._logcdf(x, h, k))
  3340. def _logcdf(self, x, h, k):
  3341. condlist = [np.logical_and(h != 0, k != 0),
  3342. np.logical_and(h == 0, k != 0),
  3343. np.logical_and(h != 0, k == 0),
  3344. np.logical_and(h == 0, k == 0)]
  3345. def f0(x, h, k):
  3346. '''cdf = (1.0 - h*(1.0 - k*x)**(1.0/k))**(1.0/h)
  3347. logcdf = ...
  3348. '''
  3349. return (1.0/h)*sc.log1p(-h*(1.0 - k*x)**(1.0/k))
  3350. def f1(x, h, k):
  3351. '''cdf = np.exp(-(1.0 - k*x)**(1.0/k))
  3352. logcdf = ...
  3353. '''
  3354. return -(1.0 - k*x)**(1.0/k)
  3355. def f2(x, h, k):
  3356. '''cdf = (1.0 - h*np.exp(-x))**(1.0/h)
  3357. logcdf = ...
  3358. '''
  3359. return (1.0/h)*sc.log1p(-h*np.exp(-x))
  3360. def f3(x, h, k):
  3361. '''cdf = np.exp(-np.exp(-x))
  3362. logcdf = ...
  3363. '''
  3364. return -np.exp(-x)
  3365. return _lazyselect(condlist,
  3366. [f0, f1, f2, f3],
  3367. [x, h, k],
  3368. default=np.nan)
  3369. def _ppf(self, q, h, k):
  3370. condlist = [np.logical_and(h != 0, k != 0),
  3371. np.logical_and(h == 0, k != 0),
  3372. np.logical_and(h != 0, k == 0),
  3373. np.logical_and(h == 0, k == 0)]
  3374. def f0(q, h, k):
  3375. return 1.0/k*(1.0 - ((1.0 - (q**h))/h)**k)
  3376. def f1(q, h, k):
  3377. return 1.0/k*(1.0 - (-np.log(q))**k)
  3378. def f2(q, h, k):
  3379. '''ppf = -np.log((1.0 - (q**h))/h)
  3380. '''
  3381. return -sc.log1p(-(q**h)) + np.log(h)
  3382. def f3(q, h, k):
  3383. return -np.log(-np.log(q))
  3384. return _lazyselect(condlist,
  3385. [f0, f1, f2, f3],
  3386. [q, h, k],
  3387. default=np.nan)
  3388. def _stats(self, h, k):
  3389. if h >= 0 and k >= 0:
  3390. maxr = 5
  3391. elif h < 0 and k >= 0:
  3392. maxr = int(-1.0/h*k)
  3393. elif k < 0:
  3394. maxr = int(-1.0/k)
  3395. else:
  3396. maxr = 5
  3397. outputs = [None if r < maxr else np.nan for r in range(1, 5)]
  3398. return outputs[:]
  3399. kappa4 = kappa4_gen(name='kappa4')
  3400. class kappa3_gen(rv_continuous):
  3401. r"""Kappa 3 parameter distribution.
  3402. %(before_notes)s
  3403. Notes
  3404. -----
  3405. The probability density function for `kappa3` is:
  3406. .. math::
  3407. f(x, a) = a (a + x^a)^{-(a + 1)/a}
  3408. for :math:`x > 0` and :math:`a > 0`.
  3409. `kappa3` takes ``a`` as a shape parameter for :math:`a`.
  3410. References
  3411. ----------
  3412. P.W. Mielke and E.S. Johnson, "Three-Parameter Kappa Distribution Maximum
  3413. Likelihood and Likelihood Ratio Tests", Methods in Weather Research,
  3414. 701-707, (September, 1973),
  3415. https://doi.org/10.1175/1520-0493(1973)101<0701:TKDMLE>2.3.CO;2
  3416. B. Kumphon, "Maximum Entropy and Maximum Likelihood Estimation for the
  3417. Three-Parameter Kappa Distribution", Open Journal of Statistics, vol 2,
  3418. 415-419 (2012), https://doi.org/10.4236/ojs.2012.24050
  3419. %(after_notes)s
  3420. %(example)s
  3421. """
  3422. def _argcheck(self, a):
  3423. return a > 0
  3424. def _pdf(self, x, a):
  3425. # kappa3.pdf(x, a) = a*(a + x**a)**(-(a + 1)/a), for x > 0
  3426. return a*(a + x**a)**(-1.0/a-1)
  3427. def _cdf(self, x, a):
  3428. return x*(a + x**a)**(-1.0/a)
  3429. def _ppf(self, q, a):
  3430. return (a/(q**-a - 1.0))**(1.0/a)
  3431. def _stats(self, a):
  3432. outputs = [None if i < a else np.nan for i in range(1, 5)]
  3433. return outputs[:]
  3434. kappa3 = kappa3_gen(a=0.0, name='kappa3')
  3435. class moyal_gen(rv_continuous):
  3436. r"""A Moyal continuous random variable.
  3437. %(before_notes)s
  3438. Notes
  3439. -----
  3440. The probability density function for `moyal` is:
  3441. .. math::
  3442. f(x) = \exp(-(x + \exp(-x))/2) / \sqrt{2\pi}
  3443. for a real number :math:`x`.
  3444. %(after_notes)s
  3445. This distribution has utility in high-energy physics and radiation
  3446. detection. It describes the energy loss of a charged relativistic
  3447. particle due to ionization of the medium [1]_. It also provides an
  3448. approximation for the Landau distribution. For an in depth description
  3449. see [2]_. For additional description, see [3]_.
  3450. References
  3451. ----------
  3452. .. [1] J.E. Moyal, "XXX. Theory of ionization fluctuations",
  3453. The London, Edinburgh, and Dublin Philosophical Magazine
  3454. and Journal of Science, vol 46, 263-280, (1955).
  3455. :doi:`10.1080/14786440308521076` (gated)
  3456. .. [2] G. Cordeiro et al., "The beta Moyal: a useful skew distribution",
  3457. International Journal of Research and Reviews in Applied Sciences,
  3458. vol 10, 171-192, (2012).
  3459. http://www.arpapress.com/Volumes/Vol10Issue2/IJRRAS_10_2_02.pdf
  3460. .. [3] C. Walck, "Handbook on Statistical Distributions for
  3461. Experimentalists; International Report SUF-PFY/96-01", Chapter 26,
  3462. University of Stockholm: Stockholm, Sweden, (2007).
  3463. http://www.stat.rice.edu/~dobelman/textfiles/DistributionsHandbook.pdf
  3464. .. versionadded:: 1.1.0
  3465. %(example)s
  3466. """
  3467. def _rvs(self):
  3468. sz, rndm = self._size, self._random_state
  3469. u1 = gamma.rvs(a = 0.5, scale = 2, size=sz, random_state=rndm)
  3470. return -np.log(u1)
  3471. def _pdf(self, x):
  3472. return np.exp(-0.5 * (x + np.exp(-x))) / np.sqrt(2*np.pi)
  3473. def _cdf(self, x):
  3474. return sc.erfc(np.exp(-0.5 * x) / np.sqrt(2))
  3475. def _sf(self, x):
  3476. return sc.erf(np.exp(-0.5 * x) / np.sqrt(2))
  3477. def _ppf(self, x):
  3478. return -np.log(2 * sc.erfcinv(x)**2)
  3479. def _stats(self):
  3480. mu = np.log(2) + np.euler_gamma
  3481. mu2 = np.pi**2 / 2
  3482. g1 = 28 * np.sqrt(2) * sc.zeta(3) / np.pi**3
  3483. g2 = 4.
  3484. return mu, mu2, g1, g2
  3485. def _munp(self, n):
  3486. if n == 1.0:
  3487. return np.log(2) + np.euler_gamma
  3488. elif n == 2.0:
  3489. return np.pi**2 / 2 + (np.log(2) + np.euler_gamma)**2
  3490. elif n == 3.0:
  3491. tmp1 = 1.5 * np.pi**2 * (np.log(2)+np.euler_gamma)
  3492. tmp2 = (np.log(2)+np.euler_gamma)**3
  3493. tmp3 = 14 * sc.zeta(3)
  3494. return tmp1 + tmp2 + tmp3
  3495. elif n == 4.0:
  3496. tmp1 = 4 * 14 * sc.zeta(3) * (np.log(2) + np.euler_gamma)
  3497. tmp2 = 3 * np.pi**2 * (np.log(2) + np.euler_gamma)**2
  3498. tmp3 = (np.log(2) + np.euler_gamma)**4
  3499. tmp4 = 7 * np.pi**4 / 4
  3500. return tmp1 + tmp2 + tmp3 + tmp4
  3501. else:
  3502. # return generic for higher moments
  3503. # return rv_continuous._mom1_sc(self, n, b)
  3504. return self._mom1_sc(n)
  3505. moyal = moyal_gen(name="moyal")
  3506. class nakagami_gen(rv_continuous):
  3507. r"""A Nakagami continuous random variable.
  3508. %(before_notes)s
  3509. Notes
  3510. -----
  3511. The probability density function for `nakagami` is:
  3512. .. math::
  3513. f(x, \nu) = \frac{2 \nu^\nu}{\Gamma(\nu)} x^{2\nu-1} \exp(-\nu x^2)
  3514. for :math:`x > 0`, :math:`\nu > 0`.
  3515. `nakagami` takes ``nu`` as a shape parameter for :math:`\nu`.
  3516. %(after_notes)s
  3517. %(example)s
  3518. """
  3519. def _pdf(self, x, nu):
  3520. # nakagami.pdf(x, nu) = 2 * nu**nu / gamma(nu) *
  3521. # x**(2*nu-1) * exp(-nu*x**2)
  3522. return 2*nu**nu/sc.gamma(nu)*(x**(2*nu-1.0))*np.exp(-nu*x*x)
  3523. def _cdf(self, x, nu):
  3524. return sc.gammainc(nu, nu*x*x)
  3525. def _ppf(self, q, nu):
  3526. return np.sqrt(1.0/nu*sc.gammaincinv(nu, q))
  3527. def _stats(self, nu):
  3528. mu = sc.gamma(nu+0.5)/sc.gamma(nu)/np.sqrt(nu)
  3529. mu2 = 1.0-mu*mu
  3530. g1 = mu * (1 - 4*nu*mu2) / 2.0 / nu / np.power(mu2, 1.5)
  3531. g2 = -6*mu**4*nu + (8*nu-2)*mu**2-2*nu + 1
  3532. g2 /= nu*mu2**2.0
  3533. return mu, mu2, g1, g2
  3534. nakagami = nakagami_gen(a=0.0, name="nakagami")
  3535. class ncx2_gen(rv_continuous):
  3536. r"""A non-central chi-squared continuous random variable.
  3537. %(before_notes)s
  3538. Notes
  3539. -----
  3540. The probability density function for `ncx2` is:
  3541. .. math::
  3542. f(x, k, \lambda) = \frac{1}{2} \exp(-(\lambda+x)/2)
  3543. (x/\lambda)^{(k-2)/4} I_{(k-2)/2}(\sqrt{\lambda x})
  3544. for :math:`x > 0` and :math:`k, \lambda > 0`. :math:`k` specifies the
  3545. degrees of freedom (denoted ``df`` in the implementation) and
  3546. :math:`\lambda` is the non-centrality parameter (denoted ``nc`` in the
  3547. implementation). :math:`I_\nu` denotes the modified Bessel function of
  3548. first order of degree :math:`\nu` (`scipy.special.iv`).
  3549. `ncx2` takes ``df`` and ``nc`` as shape parameters.
  3550. %(after_notes)s
  3551. %(example)s
  3552. """
  3553. def _rvs(self, df, nc):
  3554. return self._random_state.noncentral_chisquare(df, nc, self._size)
  3555. def _logpdf(self, x, df, nc):
  3556. return _ncx2_log_pdf(x, df, nc)
  3557. def _pdf(self, x, df, nc):
  3558. # ncx2.pdf(x, df, nc) = exp(-(nc+x)/2) * 1/2 * (x/nc)**((df-2)/4)
  3559. # * I[(df-2)/2](sqrt(nc*x))
  3560. return _ncx2_pdf(x, df, nc)
  3561. def _cdf(self, x, df, nc):
  3562. return _ncx2_cdf(x, df, nc)
  3563. def _ppf(self, q, df, nc):
  3564. return sc.chndtrix(q, df, nc)
  3565. def _stats(self, df, nc):
  3566. val = df + 2.0*nc
  3567. return (df + nc,
  3568. 2*val,
  3569. np.sqrt(8)*(val+nc)/val**1.5,
  3570. 12.0*(val+2*nc)/val**2.0)
  3571. ncx2 = ncx2_gen(a=0.0, name='ncx2')
  3572. class ncf_gen(rv_continuous):
  3573. r"""A non-central F distribution continuous random variable.
  3574. %(before_notes)s
  3575. Notes
  3576. -----
  3577. The probability density function for `ncf` is:
  3578. .. math::
  3579. f(x, n_1, n_2, \lambda) =
  3580. \exp(\frac{\lambda}{2} + \lambda n_1 \frac{x}{2(n_1 x+n_2)})
  3581. n_1^{n_1/2} n_2^{n_2/2} x^{n_1/2 - 1} \\
  3582. (n_2+n_1 x)^{-(n_1+n_2)/2}
  3583. \gamma(n_1/2) \gamma(1+n_2/2) \\
  3584. \frac{L^{\frac{v_1}{2}-1}_{v_2/2}
  3585. (-\lambda v_1 \frac{x}{2(v_1 x+v_2)})}
  3586. {B(v_1/2, v_2/2) \gamma(\frac{v_1+v_2}{2})}
  3587. for :math:`n_1 > 1`, :math:`n_2, \lambda > 0`. Here :math:`n_1` is the
  3588. degrees of freedom in the numerator, :math:`n_2` the degrees of freedom in
  3589. the denominator, :math:`\lambda` the non-centrality parameter,
  3590. :math:`\gamma` is the logarithm of the Gamma function, :math:`L_n^k` is a
  3591. generalized Laguerre polynomial and :math:`B` is the beta function.
  3592. `ncf` takes ``df1``, ``df2`` and ``nc`` as shape parameters.
  3593. %(after_notes)s
  3594. %(example)s
  3595. """
  3596. def _rvs(self, dfn, dfd, nc):
  3597. return self._random_state.noncentral_f(dfn, dfd, nc, self._size)
  3598. def _pdf_skip(self, x, dfn, dfd, nc):
  3599. # ncf.pdf(x, df1, df2, nc) = exp(nc/2 + nc*df1*x/(2*(df1*x+df2))) *
  3600. # df1**(df1/2) * df2**(df2/2) * x**(df1/2-1) *
  3601. # (df2+df1*x)**(-(df1+df2)/2) *
  3602. # gamma(df1/2)*gamma(1+df2/2) *
  3603. # L^{v1/2-1}^{v2/2}(-nc*v1*x/(2*(v1*x+v2))) /
  3604. # (B(v1/2, v2/2) * gamma((v1+v2)/2))
  3605. n1, n2 = dfn, dfd
  3606. term = -nc/2+nc*n1*x/(2*(n2+n1*x)) + sc.gammaln(n1/2.)+sc.gammaln(1+n2/2.)
  3607. term -= sc.gammaln((n1+n2)/2.0)
  3608. Px = np.exp(term)
  3609. Px *= n1**(n1/2) * n2**(n2/2) * x**(n1/2-1)
  3610. Px *= (n2+n1*x)**(-(n1+n2)/2)
  3611. Px *= sc.assoc_laguerre(-nc*n1*x/(2.0*(n2+n1*x)), n2/2, n1/2-1)
  3612. Px /= sc.beta(n1/2, n2/2)
  3613. # This function does not have a return. Drop it for now, the generic
  3614. # function seems to work OK.
  3615. def _cdf(self, x, dfn, dfd, nc):
  3616. return sc.ncfdtr(dfn, dfd, nc, x)
  3617. def _ppf(self, q, dfn, dfd, nc):
  3618. return sc.ncfdtri(dfn, dfd, nc, q)
  3619. def _munp(self, n, dfn, dfd, nc):
  3620. val = (dfn * 1.0/dfd)**n
  3621. term = sc.gammaln(n+0.5*dfn) + sc.gammaln(0.5*dfd-n) - sc.gammaln(dfd*0.5)
  3622. val *= np.exp(-nc / 2.0+term)
  3623. val *= sc.hyp1f1(n+0.5*dfn, 0.5*dfn, 0.5*nc)
  3624. return val
  3625. def _stats(self, dfn, dfd, nc):
  3626. mu = np.where(dfd <= 2, np.inf, dfd / (dfd-2.0)*(1+nc*1.0/dfn))
  3627. mu2 = np.where(dfd <= 4, np.inf, 2*(dfd*1.0/dfn)**2.0 *
  3628. ((dfn+nc/2.0)**2.0 + (dfn+nc)*(dfd-2.0)) /
  3629. ((dfd-2.0)**2.0 * (dfd-4.0)))
  3630. return mu, mu2, None, None
  3631. ncf = ncf_gen(a=0.0, name='ncf')
  3632. class t_gen(rv_continuous):
  3633. r"""A Student's t continuous random variable.
  3634. %(before_notes)s
  3635. Notes
  3636. -----
  3637. The probability density function for `t` is:
  3638. .. math::
  3639. f(x, \nu) = \frac{\Gamma((\nu+1)/2)}
  3640. {\sqrt{\pi \nu} \Gamma(\nu)}
  3641. (1+x^2/\nu)^{-(\nu+1)/2}
  3642. where :math:`x` is a real number and the degrees of freedom parameter
  3643. :math:`\nu` (denoted ``df`` in the implementation) satisfies
  3644. :math:`\nu > 0`. :math:`\Gamma` is the gamma function
  3645. (`scipy.special.gamma`).
  3646. %(after_notes)s
  3647. %(example)s
  3648. """
  3649. def _argcheck(self, df):
  3650. return df > 0
  3651. def _rvs(self, df):
  3652. return self._random_state.standard_t(df, size=self._size)
  3653. def _pdf(self, x, df):
  3654. # gamma((df+1)/2)
  3655. # t.pdf(x, df) = ---------------------------------------------------
  3656. # sqrt(pi*df) * gamma(df/2) * (1+x**2/df)**((df+1)/2)
  3657. r = np.asarray(df*1.0)
  3658. Px = np.exp(sc.gammaln((r+1)/2)-sc.gammaln(r/2))
  3659. Px /= np.sqrt(r*np.pi)*(1+(x**2)/r)**((r+1)/2)
  3660. return Px
  3661. def _logpdf(self, x, df):
  3662. r = df*1.0
  3663. lPx = sc.gammaln((r+1)/2)-sc.gammaln(r/2)
  3664. lPx -= 0.5*np.log(r*np.pi) + (r+1)/2*np.log(1+(x**2)/r)
  3665. return lPx
  3666. def _cdf(self, x, df):
  3667. return sc.stdtr(df, x)
  3668. def _sf(self, x, df):
  3669. return sc.stdtr(df, -x)
  3670. def _ppf(self, q, df):
  3671. return sc.stdtrit(df, q)
  3672. def _isf(self, q, df):
  3673. return -sc.stdtrit(df, q)
  3674. def _stats(self, df):
  3675. mu = np.where(df > 1, 0.0, np.inf)
  3676. mu2 = _lazywhere(df > 2, (df,),
  3677. lambda df: df / (df-2.0),
  3678. np.inf)
  3679. mu2 = np.where(df <= 1, np.nan, mu2)
  3680. g1 = np.where(df > 3, 0.0, np.nan)
  3681. g2 = _lazywhere(df > 4, (df,),
  3682. lambda df: 6.0 / (df-4.0),
  3683. np.inf)
  3684. g2 = np.where(df <= 2, np.nan, g2)
  3685. return mu, mu2, g1, g2
  3686. t = t_gen(name='t')
  3687. class nct_gen(rv_continuous):
  3688. r"""A non-central Student's t continuous random variable.
  3689. %(before_notes)s
  3690. Notes
  3691. -----
  3692. If :math:`Y` is a standard normal random variable and :math:`V` is
  3693. an independent chi-square random variable (`chi2`) with :math:`k` degrees
  3694. of freedom, then
  3695. .. math::
  3696. X = \frac{Y + c}{\sqrt{V/k}}
  3697. has a non-central Student's t distribution on the real line.
  3698. The degrees of freedom parameter :math:`k` (denoted ``df`` in the
  3699. implementation) satisfies :math:`k > 0` and the noncentrality parameter
  3700. :math:`c` (denoted ``nct`` in the implementation) is a real number.
  3701. %(after_notes)s
  3702. %(example)s
  3703. """
  3704. def _argcheck(self, df, nc):
  3705. return (df > 0) & (nc == nc)
  3706. def _rvs(self, df, nc):
  3707. sz, rndm = self._size, self._random_state
  3708. n = norm.rvs(loc=nc, size=sz, random_state=rndm)
  3709. c2 = chi2.rvs(df, size=sz, random_state=rndm)
  3710. return n * np.sqrt(df) / np.sqrt(c2)
  3711. def _pdf(self, x, df, nc):
  3712. n = df*1.0
  3713. nc = nc*1.0
  3714. x2 = x*x
  3715. ncx2 = nc*nc*x2
  3716. fac1 = n + x2
  3717. trm1 = n/2.*np.log(n) + sc.gammaln(n+1)
  3718. trm1 -= n*np.log(2)+nc*nc/2.+(n/2.)*np.log(fac1)+sc.gammaln(n/2.)
  3719. Px = np.exp(trm1)
  3720. valF = ncx2 / (2*fac1)
  3721. trm1 = np.sqrt(2)*nc*x*sc.hyp1f1(n/2+1, 1.5, valF)
  3722. trm1 /= np.asarray(fac1*sc.gamma((n+1)/2))
  3723. trm2 = sc.hyp1f1((n+1)/2, 0.5, valF)
  3724. trm2 /= np.asarray(np.sqrt(fac1)*sc.gamma(n/2+1))
  3725. Px *= trm1+trm2
  3726. return Px
  3727. def _cdf(self, x, df, nc):
  3728. return sc.nctdtr(df, nc, x)
  3729. def _ppf(self, q, df, nc):
  3730. return sc.nctdtrit(df, nc, q)
  3731. def _stats(self, df, nc, moments='mv'):
  3732. #
  3733. # See D. Hogben, R.S. Pinkham, and M.B. Wilk,
  3734. # 'The moments of the non-central t-distribution'
  3735. # Biometrika 48, p. 465 (2961).
  3736. # e.g. https://www.jstor.org/stable/2332772 (gated)
  3737. #
  3738. mu, mu2, g1, g2 = None, None, None, None
  3739. gfac = sc.gamma(df/2.-0.5) / sc.gamma(df/2.)
  3740. c11 = np.sqrt(df/2.) * gfac
  3741. c20 = df / (df-2.)
  3742. c22 = c20 - c11*c11
  3743. mu = np.where(df > 1, nc*c11, np.inf)
  3744. mu2 = np.where(df > 2, c22*nc*nc + c20, np.inf)
  3745. if 's' in moments:
  3746. c33t = df * (7.-2.*df) / (df-2.) / (df-3.) + 2.*c11*c11
  3747. c31t = 3.*df / (df-2.) / (df-3.)
  3748. mu3 = (c33t*nc*nc + c31t) * c11*nc
  3749. g1 = np.where(df > 3, mu3 / np.power(mu2, 1.5), np.nan)
  3750. # kurtosis
  3751. if 'k' in moments:
  3752. c44 = df*df / (df-2.) / (df-4.)
  3753. c44 -= c11*c11 * 2.*df*(5.-df) / (df-2.) / (df-3.)
  3754. c44 -= 3.*c11**4
  3755. c42 = df / (df-4.) - c11*c11 * (df-1.) / (df-3.)
  3756. c42 *= 6.*df / (df-2.)
  3757. c40 = 3.*df*df / (df-2.) / (df-4.)
  3758. mu4 = c44 * nc**4 + c42*nc**2 + c40
  3759. g2 = np.where(df > 4, mu4/mu2**2 - 3., np.nan)
  3760. return mu, mu2, g1, g2
  3761. nct = nct_gen(name="nct")
  3762. class pareto_gen(rv_continuous):
  3763. r"""A Pareto continuous random variable.
  3764. %(before_notes)s
  3765. Notes
  3766. -----
  3767. The probability density function for `pareto` is:
  3768. .. math::
  3769. f(x, b) = \frac{b}{x^{b+1}}
  3770. for :math:`x \ge 1`, :math:`b > 0`.
  3771. `pareto` takes ``b`` as a shape parameter for :math:`b`.
  3772. %(after_notes)s
  3773. %(example)s
  3774. """
  3775. def _pdf(self, x, b):
  3776. # pareto.pdf(x, b) = b / x**(b+1)
  3777. return b * x**(-b-1)
  3778. def _cdf(self, x, b):
  3779. return 1 - x**(-b)
  3780. def _ppf(self, q, b):
  3781. return pow(1-q, -1.0/b)
  3782. def _sf(self, x, b):
  3783. return x**(-b)
  3784. def _stats(self, b, moments='mv'):
  3785. mu, mu2, g1, g2 = None, None, None, None
  3786. if 'm' in moments:
  3787. mask = b > 1
  3788. bt = np.extract(mask, b)
  3789. mu = valarray(np.shape(b), value=np.inf)
  3790. np.place(mu, mask, bt / (bt-1.0))
  3791. if 'v' in moments:
  3792. mask = b > 2
  3793. bt = np.extract(mask, b)
  3794. mu2 = valarray(np.shape(b), value=np.inf)
  3795. np.place(mu2, mask, bt / (bt-2.0) / (bt-1.0)**2)
  3796. if 's' in moments:
  3797. mask = b > 3
  3798. bt = np.extract(mask, b)
  3799. g1 = valarray(np.shape(b), value=np.nan)
  3800. vals = 2 * (bt + 1.0) * np.sqrt(bt - 2.0) / ((bt - 3.0) * np.sqrt(bt))
  3801. np.place(g1, mask, vals)
  3802. if 'k' in moments:
  3803. mask = b > 4
  3804. bt = np.extract(mask, b)
  3805. g2 = valarray(np.shape(b), value=np.nan)
  3806. vals = (6.0*np.polyval([1.0, 1.0, -6, -2], bt) /
  3807. np.polyval([1.0, -7.0, 12.0, 0.0], bt))
  3808. np.place(g2, mask, vals)
  3809. return mu, mu2, g1, g2
  3810. def _entropy(self, c):
  3811. return 1 + 1.0/c - np.log(c)
  3812. pareto = pareto_gen(a=1.0, name="pareto")
  3813. class lomax_gen(rv_continuous):
  3814. r"""A Lomax (Pareto of the second kind) continuous random variable.
  3815. %(before_notes)s
  3816. Notes
  3817. -----
  3818. The probability density function for `lomax` is:
  3819. .. math::
  3820. f(x, c) = \frac{c}{(1+x)^{c+1}}
  3821. for :math:`x \ge 0`, :math:`c > 0`.
  3822. `lomax` takes ``c`` as a shape parameter for :math:`c`.
  3823. `lomax` is a special case of `pareto` with ``loc=-1.0``.
  3824. %(after_notes)s
  3825. %(example)s
  3826. """
  3827. def _pdf(self, x, c):
  3828. # lomax.pdf(x, c) = c / (1+x)**(c+1)
  3829. return c*1.0/(1.0+x)**(c+1.0)
  3830. def _logpdf(self, x, c):
  3831. return np.log(c) - (c+1)*sc.log1p(x)
  3832. def _cdf(self, x, c):
  3833. return -sc.expm1(-c*sc.log1p(x))
  3834. def _sf(self, x, c):
  3835. return np.exp(-c*sc.log1p(x))
  3836. def _logsf(self, x, c):
  3837. return -c*sc.log1p(x)
  3838. def _ppf(self, q, c):
  3839. return sc.expm1(-sc.log1p(-q)/c)
  3840. def _stats(self, c):
  3841. mu, mu2, g1, g2 = pareto.stats(c, loc=-1.0, moments='mvsk')
  3842. return mu, mu2, g1, g2
  3843. def _entropy(self, c):
  3844. return 1+1.0/c-np.log(c)
  3845. lomax = lomax_gen(a=0.0, name="lomax")
  3846. class pearson3_gen(rv_continuous):
  3847. r"""A pearson type III continuous random variable.
  3848. %(before_notes)s
  3849. Notes
  3850. -----
  3851. The probability density function for `pearson3` is:
  3852. .. math::
  3853. f(x, skew) = \frac{|\beta|}{\Gamma(\alpha)}
  3854. (\beta (x - \zeta))^{\alpha - 1}
  3855. \exp(-\beta (x - \zeta))
  3856. where:
  3857. .. math::
  3858. \beta = \frac{2}{skew stddev}
  3859. \alpha = (stddev \beta)^2
  3860. \zeta = loc - \frac{\alpha}{\beta}
  3861. :math:`\Gamma` is the gamma function (`scipy.special.gamma`).
  3862. `pearson3` takes ``skew`` as a shape parameter for :math:`skew`.
  3863. %(after_notes)s
  3864. %(example)s
  3865. References
  3866. ----------
  3867. R.W. Vogel and D.E. McMartin, "Probability Plot Goodness-of-Fit and
  3868. Skewness Estimation Procedures for the Pearson Type 3 Distribution", Water
  3869. Resources Research, Vol.27, 3149-3158 (1991).
  3870. L.R. Salvosa, "Tables of Pearson's Type III Function", Ann. Math. Statist.,
  3871. Vol.1, 191-198 (1930).
  3872. "Using Modern Computing Tools to Fit the Pearson Type III Distribution to
  3873. Aviation Loads Data", Office of Aviation Research (2003).
  3874. """
  3875. def _preprocess(self, x, skew):
  3876. # The real 'loc' and 'scale' are handled in the calling pdf(...). The
  3877. # local variables 'loc' and 'scale' within pearson3._pdf are set to
  3878. # the defaults just to keep them as part of the equations for
  3879. # documentation.
  3880. loc = 0.0
  3881. scale = 1.0
  3882. # If skew is small, return _norm_pdf. The divide between pearson3
  3883. # and norm was found by brute force and is approximately a skew of
  3884. # 0.000016. No one, I hope, would actually use a skew value even
  3885. # close to this small.
  3886. norm2pearson_transition = 0.000016
  3887. ans, x, skew = np.broadcast_arrays([1.0], x, skew)
  3888. ans = ans.copy()
  3889. # mask is True where skew is small enough to use the normal approx.
  3890. mask = np.absolute(skew) < norm2pearson_transition
  3891. invmask = ~mask
  3892. beta = 2.0 / (skew[invmask] * scale)
  3893. alpha = (scale * beta)**2
  3894. zeta = loc - alpha / beta
  3895. transx = beta * (x[invmask] - zeta)
  3896. return ans, x, transx, mask, invmask, beta, alpha, zeta
  3897. def _argcheck(self, skew):
  3898. # The _argcheck function in rv_continuous only allows positive
  3899. # arguments. The skew argument for pearson3 can be zero (which I want
  3900. # to handle inside pearson3._pdf) or negative. So just return True
  3901. # for all skew args.
  3902. return np.ones(np.shape(skew), dtype=bool)
  3903. def _stats(self, skew):
  3904. _, _, _, _, _, beta, alpha, zeta = (
  3905. self._preprocess([1], skew))
  3906. m = zeta + alpha / beta
  3907. v = alpha / (beta**2)
  3908. s = 2.0 / (alpha**0.5) * np.sign(beta)
  3909. k = 6.0 / alpha
  3910. return m, v, s, k
  3911. def _pdf(self, x, skew):
  3912. # pearson3.pdf(x, skew) = abs(beta) / gamma(alpha) *
  3913. # (beta * (x - zeta))**(alpha - 1) * exp(-beta*(x - zeta))
  3914. # Do the calculation in _logpdf since helps to limit
  3915. # overflow/underflow problems
  3916. ans = np.exp(self._logpdf(x, skew))
  3917. if ans.ndim == 0:
  3918. if np.isnan(ans):
  3919. return 0.0
  3920. return ans
  3921. ans[np.isnan(ans)] = 0.0
  3922. return ans
  3923. def _logpdf(self, x, skew):
  3924. # PEARSON3 logpdf GAMMA logpdf
  3925. # np.log(abs(beta))
  3926. # + (alpha - 1)*np.log(beta*(x - zeta)) + (a - 1)*np.log(x)
  3927. # - beta*(x - zeta) - x
  3928. # - sc.gammalnalpha) - sc.gammalna)
  3929. ans, x, transx, mask, invmask, beta, alpha, _ = (
  3930. self._preprocess(x, skew))
  3931. ans[mask] = np.log(_norm_pdf(x[mask]))
  3932. ans[invmask] = np.log(abs(beta)) + gamma._logpdf(transx, alpha)
  3933. return ans
  3934. def _cdf(self, x, skew):
  3935. ans, x, transx, mask, invmask, _, alpha, _ = (
  3936. self._preprocess(x, skew))
  3937. ans[mask] = _norm_cdf(x[mask])
  3938. ans[invmask] = gamma._cdf(transx, alpha)
  3939. return ans
  3940. def _rvs(self, skew):
  3941. skew = broadcast_to(skew, self._size)
  3942. ans, _, _, mask, invmask, beta, alpha, zeta = (
  3943. self._preprocess([0], skew))
  3944. nsmall = mask.sum()
  3945. nbig = mask.size - nsmall
  3946. ans[mask] = self._random_state.standard_normal(nsmall)
  3947. ans[invmask] = (self._random_state.standard_gamma(alpha, nbig)/beta +
  3948. zeta)
  3949. if self._size == ():
  3950. ans = ans[0]
  3951. return ans
  3952. def _ppf(self, q, skew):
  3953. ans, q, _, mask, invmask, beta, alpha, zeta = (
  3954. self._preprocess(q, skew))
  3955. ans[mask] = _norm_ppf(q[mask])
  3956. ans[invmask] = sc.gammaincinv(alpha, q[invmask])/beta + zeta
  3957. return ans
  3958. pearson3 = pearson3_gen(name="pearson3")
  3959. class powerlaw_gen(rv_continuous):
  3960. r"""A power-function continuous random variable.
  3961. %(before_notes)s
  3962. Notes
  3963. -----
  3964. The probability density function for `powerlaw` is:
  3965. .. math::
  3966. f(x, a) = a x^{a-1}
  3967. for :math:`0 \le x \le 1`, :math:`a > 0`.
  3968. `powerlaw` takes ``a`` as a shape parameter for :math:`a`.
  3969. %(after_notes)s
  3970. `powerlaw` is a special case of `beta` with ``b=1``.
  3971. %(example)s
  3972. """
  3973. def _pdf(self, x, a):
  3974. # powerlaw.pdf(x, a) = a * x**(a-1)
  3975. return a*x**(a-1.0)
  3976. def _logpdf(self, x, a):
  3977. return np.log(a) + sc.xlogy(a - 1, x)
  3978. def _cdf(self, x, a):
  3979. return x**(a*1.0)
  3980. def _logcdf(self, x, a):
  3981. return a*np.log(x)
  3982. def _ppf(self, q, a):
  3983. return pow(q, 1.0/a)
  3984. def _stats(self, a):
  3985. return (a / (a + 1.0),
  3986. a / (a + 2.0) / (a + 1.0) ** 2,
  3987. -2.0 * ((a - 1.0) / (a + 3.0)) * np.sqrt((a + 2.0) / a),
  3988. 6 * np.polyval([1, -1, -6, 2], a) / (a * (a + 3.0) * (a + 4)))
  3989. def _entropy(self, a):
  3990. return 1 - 1.0/a - np.log(a)
  3991. powerlaw = powerlaw_gen(a=0.0, b=1.0, name="powerlaw")
  3992. class powerlognorm_gen(rv_continuous):
  3993. r"""A power log-normal continuous random variable.
  3994. %(before_notes)s
  3995. Notes
  3996. -----
  3997. The probability density function for `powerlognorm` is:
  3998. .. math::
  3999. f(x, c, s) = \frac{c}{x s} \phi(\log(x)/s)
  4000. (\Phi(-\log(x)/s))^{c-1}
  4001. where :math:`\phi` is the normal pdf, and :math:`\Phi` is the normal cdf,
  4002. and :math:`x > 0`, :math:`s, c > 0`.
  4003. `powerlognorm` takes :math:`c` and :math:`s` as shape parameters.
  4004. %(after_notes)s
  4005. %(example)s
  4006. """
  4007. _support_mask = rv_continuous._open_support_mask
  4008. def _pdf(self, x, c, s):
  4009. # powerlognorm.pdf(x, c, s) = c / (x*s) * phi(log(x)/s) *
  4010. # (Phi(-log(x)/s))**(c-1),
  4011. return (c/(x*s) * _norm_pdf(np.log(x)/s) *
  4012. pow(_norm_cdf(-np.log(x)/s), c*1.0-1.0))
  4013. def _cdf(self, x, c, s):
  4014. return 1.0 - pow(_norm_cdf(-np.log(x)/s), c*1.0)
  4015. def _ppf(self, q, c, s):
  4016. return np.exp(-s * _norm_ppf(pow(1.0 - q, 1.0 / c)))
  4017. powerlognorm = powerlognorm_gen(a=0.0, name="powerlognorm")
  4018. class powernorm_gen(rv_continuous):
  4019. r"""A power normal continuous random variable.
  4020. %(before_notes)s
  4021. Notes
  4022. -----
  4023. The probability density function for `powernorm` is:
  4024. .. math::
  4025. f(x, c) = c \phi(x) (\Phi(-x))^{c-1}
  4026. where :math:`\phi` is the normal pdf, and :math:`\Phi` is the normal cdf,
  4027. and :math:`x > 0`, :math:`c > 0`.
  4028. `powernorm` takes ``c`` as a shape parameter for :math:`c`.
  4029. %(after_notes)s
  4030. %(example)s
  4031. """
  4032. def _pdf(self, x, c):
  4033. # powernorm.pdf(x, c) = c * phi(x) * (Phi(-x))**(c-1)
  4034. return c*_norm_pdf(x) * (_norm_cdf(-x)**(c-1.0))
  4035. def _logpdf(self, x, c):
  4036. return np.log(c) + _norm_logpdf(x) + (c-1)*_norm_logcdf(-x)
  4037. def _cdf(self, x, c):
  4038. return 1.0-_norm_cdf(-x)**(c*1.0)
  4039. def _ppf(self, q, c):
  4040. return -_norm_ppf(pow(1.0 - q, 1.0 / c))
  4041. powernorm = powernorm_gen(name='powernorm')
  4042. class rdist_gen(rv_continuous):
  4043. r"""An R-distributed continuous random variable.
  4044. %(before_notes)s
  4045. Notes
  4046. -----
  4047. The probability density function for `rdist` is:
  4048. .. math::
  4049. f(x, c) = \frac{(1-x^2)^{c/2-1}}{B(1/2, c/2)}
  4050. for :math:`-1 \le x \le 1`, :math:`c > 0`.
  4051. `rdist` takes ``c`` as a shape parameter for :math:`c`.
  4052. This distribution includes the following distribution kernels as
  4053. special cases::
  4054. c = 2: uniform
  4055. c = 4: Epanechnikov (parabolic)
  4056. c = 6: quartic (biweight)
  4057. c = 8: triweight
  4058. %(after_notes)s
  4059. %(example)s
  4060. """
  4061. def _pdf(self, x, c):
  4062. # rdist.pdf(x, c) = (1-x**2)**(c/2-1) / B(1/2, c/2)
  4063. return np.power((1.0 - x**2), c / 2.0 - 1) / sc.beta(0.5, c / 2.0)
  4064. def _cdf(self, x, c):
  4065. term1 = x / sc.beta(0.5, c / 2.0)
  4066. res = 0.5 + term1 * sc.hyp2f1(0.5, 1 - c / 2.0, 1.5, x**2)
  4067. # There's an issue with hyp2f1, it returns nans near x = +-1, c > 100.
  4068. # Use the generic implementation in that case. See gh-1285 for
  4069. # background.
  4070. if np.any(np.isnan(res)):
  4071. return rv_continuous._cdf(self, x, c)
  4072. return res
  4073. def _munp(self, n, c):
  4074. numerator = (1 - (n % 2)) * sc.beta((n + 1.0) / 2, c / 2.0)
  4075. return numerator / sc.beta(1. / 2, c / 2.)
  4076. rdist = rdist_gen(a=-1.0, b=1.0, name="rdist")
  4077. class rayleigh_gen(rv_continuous):
  4078. r"""A Rayleigh continuous random variable.
  4079. %(before_notes)s
  4080. Notes
  4081. -----
  4082. The probability density function for `rayleigh` is:
  4083. .. math::
  4084. f(x) = x \exp(-x^2/2)
  4085. for :math:`x \ge 0`.
  4086. `rayleigh` is a special case of `chi` with ``df=2``.
  4087. %(after_notes)s
  4088. %(example)s
  4089. """
  4090. _support_mask = rv_continuous._open_support_mask
  4091. def _rvs(self):
  4092. return chi.rvs(2, size=self._size, random_state=self._random_state)
  4093. def _pdf(self, r):
  4094. # rayleigh.pdf(r) = r * exp(-r**2/2)
  4095. return np.exp(self._logpdf(r))
  4096. def _logpdf(self, r):
  4097. return np.log(r) - 0.5 * r * r
  4098. def _cdf(self, r):
  4099. return -sc.expm1(-0.5 * r**2)
  4100. def _ppf(self, q):
  4101. return np.sqrt(-2 * sc.log1p(-q))
  4102. def _sf(self, r):
  4103. return np.exp(self._logsf(r))
  4104. def _logsf(self, r):
  4105. return -0.5 * r * r
  4106. def _isf(self, q):
  4107. return np.sqrt(-2 * np.log(q))
  4108. def _stats(self):
  4109. val = 4 - np.pi
  4110. return (np.sqrt(np.pi/2),
  4111. val/2,
  4112. 2*(np.pi-3)*np.sqrt(np.pi)/val**1.5,
  4113. 6*np.pi/val-16/val**2)
  4114. def _entropy(self):
  4115. return _EULER/2.0 + 1 - 0.5*np.log(2)
  4116. rayleigh = rayleigh_gen(a=0.0, name="rayleigh")
  4117. class reciprocal_gen(rv_continuous):
  4118. r"""A reciprocal continuous random variable.
  4119. %(before_notes)s
  4120. Notes
  4121. -----
  4122. The probability density function for `reciprocal` is:
  4123. .. math::
  4124. f(x, a, b) = \frac{1}{x \log(b/a)}
  4125. for :math:`a \le x \le b`, :math:`b > a > 0`.
  4126. `reciprocal` takes :math:`a` and :math:`b` as shape parameters.
  4127. %(after_notes)s
  4128. %(example)s
  4129. """
  4130. def _argcheck(self, a, b):
  4131. self.a = a
  4132. self.b = b
  4133. self.d = np.log(b*1.0 / a)
  4134. return (a > 0) & (b > a)
  4135. def _pdf(self, x, a, b):
  4136. # reciprocal.pdf(x, a, b) = 1 / (x*log(b/a))
  4137. return 1.0 / (x * self.d)
  4138. def _logpdf(self, x, a, b):
  4139. return -np.log(x) - np.log(self.d)
  4140. def _cdf(self, x, a, b):
  4141. return (np.log(x)-np.log(a)) / self.d
  4142. def _ppf(self, q, a, b):
  4143. return a*pow(b*1.0/a, q)
  4144. def _munp(self, n, a, b):
  4145. return 1.0/self.d / n * (pow(b*1.0, n) - pow(a*1.0, n))
  4146. def _entropy(self, a, b):
  4147. return 0.5*np.log(a*b)+np.log(np.log(b/a))
  4148. reciprocal = reciprocal_gen(name="reciprocal")
  4149. class rice_gen(rv_continuous):
  4150. r"""A Rice continuous random variable.
  4151. %(before_notes)s
  4152. Notes
  4153. -----
  4154. The probability density function for `rice` is:
  4155. .. math::
  4156. f(x, b) = x \exp(- \frac{x^2 + b^2}{2}) I_0(x b)
  4157. for :math:`x > 0`, :math:`b > 0`. :math:`I_0` is the modified Bessel
  4158. function of order zero (`scipy.special.i0`).
  4159. `rice` takes ``b`` as a shape parameter for :math:`b`.
  4160. %(after_notes)s
  4161. The Rice distribution describes the length, :math:`r`, of a 2-D vector with
  4162. components :math:`(U+u, V+v)`, where :math:`U, V` are constant, :math:`u,
  4163. v` are independent Gaussian random variables with standard deviation
  4164. :math:`s`. Let :math:`R = \sqrt{U^2 + V^2}`. Then the pdf of :math:`r` is
  4165. ``rice.pdf(x, R/s, scale=s)``.
  4166. %(example)s
  4167. """
  4168. def _argcheck(self, b):
  4169. return b >= 0
  4170. def _rvs(self, b):
  4171. # https://en.wikipedia.org/wiki/Rice_distribution
  4172. t = b/np.sqrt(2) + self._random_state.standard_normal(size=(2,) +
  4173. self._size)
  4174. return np.sqrt((t*t).sum(axis=0))
  4175. def _cdf(self, x, b):
  4176. return sc.chndtr(np.square(x), 2, np.square(b))
  4177. def _ppf(self, q, b):
  4178. return np.sqrt(sc.chndtrix(q, 2, np.square(b)))
  4179. def _pdf(self, x, b):
  4180. # rice.pdf(x, b) = x * exp(-(x**2+b**2)/2) * I[0](x*b)
  4181. #
  4182. # We use (x**2 + b**2)/2 = ((x-b)**2)/2 + xb.
  4183. # The factor of np.exp(-xb) is then included in the i0e function
  4184. # in place of the modified Bessel function, i0, improving
  4185. # numerical stability for large values of xb.
  4186. return x * np.exp(-(x-b)*(x-b)/2.0) * sc.i0e(x*b)
  4187. def _munp(self, n, b):
  4188. nd2 = n/2.0
  4189. n1 = 1 + nd2
  4190. b2 = b*b/2.0
  4191. return (2.0**(nd2) * np.exp(-b2) * sc.gamma(n1) *
  4192. sc.hyp1f1(n1, 1, b2))
  4193. rice = rice_gen(a=0.0, name="rice")
  4194. # FIXME: PPF does not work.
  4195. class recipinvgauss_gen(rv_continuous):
  4196. r"""A reciprocal inverse Gaussian continuous random variable.
  4197. %(before_notes)s
  4198. Notes
  4199. -----
  4200. The probability density function for `recipinvgauss` is:
  4201. .. math::
  4202. f(x, \mu) = \frac{1}{\sqrt{2\pi x}}
  4203. \exp\left(\frac{-(1-\mu x)^2}{2\mu^2x}\right)
  4204. for :math:`x \ge 0`.
  4205. `recipinvgauss` takes ``mu`` as a shape parameter for :math:`\mu`.
  4206. %(after_notes)s
  4207. %(example)s
  4208. """
  4209. def _pdf(self, x, mu):
  4210. # recipinvgauss.pdf(x, mu) =
  4211. # 1/sqrt(2*pi*x) * exp(-(1-mu*x)**2/(2*x*mu**2))
  4212. return 1.0/np.sqrt(2*np.pi*x)*np.exp(-(1-mu*x)**2.0 / (2*x*mu**2.0))
  4213. def _logpdf(self, x, mu):
  4214. return -(1-mu*x)**2.0 / (2*x*mu**2.0) - 0.5*np.log(2*np.pi*x)
  4215. def _cdf(self, x, mu):
  4216. trm1 = 1.0/mu - x
  4217. trm2 = 1.0/mu + x
  4218. isqx = 1.0/np.sqrt(x)
  4219. return 1.0-_norm_cdf(isqx*trm1)-np.exp(2.0/mu)*_norm_cdf(-isqx*trm2)
  4220. def _rvs(self, mu):
  4221. return 1.0/self._random_state.wald(mu, 1.0, size=self._size)
  4222. recipinvgauss = recipinvgauss_gen(a=0.0, name='recipinvgauss')
  4223. class semicircular_gen(rv_continuous):
  4224. r"""A semicircular continuous random variable.
  4225. %(before_notes)s
  4226. Notes
  4227. -----
  4228. The probability density function for `semicircular` is:
  4229. .. math::
  4230. f(x) = \frac{2}{\pi} \sqrt{1-x^2}
  4231. for :math:`-1 \le x \le 1`.
  4232. %(after_notes)s
  4233. %(example)s
  4234. """
  4235. def _pdf(self, x):
  4236. # semicircular.pdf(x) = 2/pi * sqrt(1-x**2)
  4237. return 2.0/np.pi*np.sqrt(1-x*x)
  4238. def _cdf(self, x):
  4239. return 0.5+1.0/np.pi*(x*np.sqrt(1-x*x) + np.arcsin(x))
  4240. def _stats(self):
  4241. return 0, 0.25, 0, -1.0
  4242. def _entropy(self):
  4243. return 0.64472988584940017414
  4244. semicircular = semicircular_gen(a=-1.0, b=1.0, name="semicircular")
  4245. class skew_norm_gen(rv_continuous):
  4246. r"""A skew-normal random variable.
  4247. %(before_notes)s
  4248. Notes
  4249. -----
  4250. The pdf is::
  4251. skewnorm.pdf(x, a) = 2 * norm.pdf(x) * norm.cdf(a*x)
  4252. `skewnorm` takes a real number :math:`a` as a skewness parameter
  4253. When ``a = 0`` the distribution is identical to a normal distribution
  4254. (`norm`). `rvs` implements the method of [1]_.
  4255. %(after_notes)s
  4256. %(example)s
  4257. References
  4258. ----------
  4259. .. [1] A. Azzalini and A. Capitanio (1999). Statistical applications of the
  4260. multivariate skew-normal distribution. J. Roy. Statist. Soc., B 61, 579-602.
  4261. http://azzalini.stat.unipd.it/SN/faq-r.html
  4262. """
  4263. def _argcheck(self, a):
  4264. return np.isfinite(a)
  4265. def _pdf(self, x, a):
  4266. return 2.*_norm_pdf(x)*_norm_cdf(a*x)
  4267. def _cdf_single(self, x, *args):
  4268. if x <= 0:
  4269. cdf = integrate.quad(self._pdf, self.a, x, args=args)[0]
  4270. else:
  4271. t1 = integrate.quad(self._pdf, self.a, 0, args=args)[0]
  4272. t2 = integrate.quad(self._pdf, 0, x, args=args)[0]
  4273. cdf = t1 + t2
  4274. if cdf > 1:
  4275. # Presumably numerical noise, e.g. 1.0000000000000002
  4276. cdf = 1.0
  4277. return cdf
  4278. def _sf(self, x, a):
  4279. return self._cdf(-x, -a)
  4280. def _rvs(self, a):
  4281. u0 = self._random_state.normal(size=self._size)
  4282. v = self._random_state.normal(size=self._size)
  4283. d = a/np.sqrt(1 + a**2)
  4284. u1 = d*u0 + v*np.sqrt(1 - d**2)
  4285. return np.where(u0 >= 0, u1, -u1)
  4286. def _stats(self, a, moments='mvsk'):
  4287. output = [None, None, None, None]
  4288. const = np.sqrt(2/np.pi) * a/np.sqrt(1 + a**2)
  4289. if 'm' in moments:
  4290. output[0] = const
  4291. if 'v' in moments:
  4292. output[1] = 1 - const**2
  4293. if 's' in moments:
  4294. output[2] = ((4 - np.pi)/2) * (const/np.sqrt(1 - const**2))**3
  4295. if 'k' in moments:
  4296. output[3] = (2*(np.pi - 3)) * (const**4/(1 - const**2)**2)
  4297. return output
  4298. skewnorm = skew_norm_gen(name='skewnorm')
  4299. class trapz_gen(rv_continuous):
  4300. r"""A trapezoidal continuous random variable.
  4301. %(before_notes)s
  4302. Notes
  4303. -----
  4304. The trapezoidal distribution can be represented with an up-sloping line
  4305. from ``loc`` to ``(loc + c*scale)``, then constant to ``(loc + d*scale)``
  4306. and then downsloping from ``(loc + d*scale)`` to ``(loc+scale)``.
  4307. `trapz` takes :math:`c` and :math:`d` as shape parameters.
  4308. %(after_notes)s
  4309. The standard form is in the range [0, 1] with c the mode.
  4310. The location parameter shifts the start to `loc`.
  4311. The scale parameter changes the width from 1 to `scale`.
  4312. %(example)s
  4313. """
  4314. def _argcheck(self, c, d):
  4315. return (c >= 0) & (c <= 1) & (d >= 0) & (d <= 1) & (d >= c)
  4316. def _pdf(self, x, c, d):
  4317. u = 2 / (d-c+1)
  4318. return _lazyselect([x < c,
  4319. (c <= x) & (x <= d),
  4320. x > d],
  4321. [lambda x, c, d, u: u * x / c,
  4322. lambda x, c, d, u: u,
  4323. lambda x, c, d, u: u * (1-x) / (1-d)],
  4324. (x, c, d, u))
  4325. def _cdf(self, x, c, d):
  4326. return _lazyselect([x < c,
  4327. (c <= x) & (x <= d),
  4328. x > d],
  4329. [lambda x, c, d: x**2 / c / (d-c+1),
  4330. lambda x, c, d: (c + 2 * (x-c)) / (d-c+1),
  4331. lambda x, c, d: 1-((1-x) ** 2
  4332. / (d-c+1) / (1-d))],
  4333. (x, c, d))
  4334. def _ppf(self, q, c, d):
  4335. qc, qd = self._cdf(c, c, d), self._cdf(d, c, d)
  4336. condlist = [q < qc, q <= qd, q > qd]
  4337. choicelist = [np.sqrt(q * c * (1 + d - c)),
  4338. 0.5 * q * (1 + d - c) + 0.5 * c,
  4339. 1 - np.sqrt((1 - q) * (d - c + 1) * (1 - d))]
  4340. return np.select(condlist, choicelist)
  4341. trapz = trapz_gen(a=0.0, b=1.0, name="trapz")
  4342. class triang_gen(rv_continuous):
  4343. r"""A triangular continuous random variable.
  4344. %(before_notes)s
  4345. Notes
  4346. -----
  4347. The triangular distribution can be represented with an up-sloping line from
  4348. ``loc`` to ``(loc + c*scale)`` and then downsloping for ``(loc + c*scale)``
  4349. to ``(loc + scale)``.
  4350. `triang` takes ``c`` as a shape parameter for :math:`c`.
  4351. %(after_notes)s
  4352. The standard form is in the range [0, 1] with c the mode.
  4353. The location parameter shifts the start to `loc`.
  4354. The scale parameter changes the width from 1 to `scale`.
  4355. %(example)s
  4356. """
  4357. def _rvs(self, c):
  4358. return self._random_state.triangular(0, c, 1, self._size)
  4359. def _argcheck(self, c):
  4360. return (c >= 0) & (c <= 1)
  4361. def _pdf(self, x, c):
  4362. # 0: edge case where c=0
  4363. # 1: generalised case for x < c, don't use x <= c, as it doesn't cope
  4364. # with c = 0.
  4365. # 2: generalised case for x >= c, but doesn't cope with c = 1
  4366. # 3: edge case where c=1
  4367. r = _lazyselect([c == 0,
  4368. x < c,
  4369. (x >= c) & (c != 1),
  4370. c == 1],
  4371. [lambda x, c: 2 - 2 * x,
  4372. lambda x, c: 2 * x / c,
  4373. lambda x, c: 2 * (1 - x) / (1 - c),
  4374. lambda x, c: 2 * x],
  4375. (x, c))
  4376. return r
  4377. def _cdf(self, x, c):
  4378. r = _lazyselect([c == 0,
  4379. x < c,
  4380. (x >= c) & (c != 1),
  4381. c == 1],
  4382. [lambda x, c: 2*x - x*x,
  4383. lambda x, c: x * x / c,
  4384. lambda x, c: (x*x - 2*x + c) / (c-1),
  4385. lambda x, c: x * x],
  4386. (x, c))
  4387. return r
  4388. def _ppf(self, q, c):
  4389. return np.where(q < c, np.sqrt(c * q), 1-np.sqrt((1-c) * (1-q)))
  4390. def _stats(self, c):
  4391. return ((c+1.0)/3.0,
  4392. (1.0-c+c*c)/18,
  4393. np.sqrt(2)*(2*c-1)*(c+1)*(c-2) / (5*np.power((1.0-c+c*c), 1.5)),
  4394. -3.0/5.0)
  4395. def _entropy(self, c):
  4396. return 0.5-np.log(2)
  4397. triang = triang_gen(a=0.0, b=1.0, name="triang")
  4398. class truncexpon_gen(rv_continuous):
  4399. r"""A truncated exponential continuous random variable.
  4400. %(before_notes)s
  4401. Notes
  4402. -----
  4403. The probability density function for `truncexpon` is:
  4404. .. math::
  4405. f(x, b) = \frac{\exp(-x)}{1 - \exp(-b)}
  4406. for :math:`0 < x < b`.
  4407. `truncexpon` takes ``b`` as a shape parameter for :math:`b`.
  4408. %(after_notes)s
  4409. %(example)s
  4410. """
  4411. def _argcheck(self, b):
  4412. self.b = b
  4413. return b > 0
  4414. def _pdf(self, x, b):
  4415. # truncexpon.pdf(x, b) = exp(-x) / (1-exp(-b))
  4416. return np.exp(-x)/(-sc.expm1(-b))
  4417. def _logpdf(self, x, b):
  4418. return -x - np.log(-sc.expm1(-b))
  4419. def _cdf(self, x, b):
  4420. return sc.expm1(-x)/sc.expm1(-b)
  4421. def _ppf(self, q, b):
  4422. return -sc.log1p(q*sc.expm1(-b))
  4423. def _munp(self, n, b):
  4424. # wrong answer with formula, same as in continuous.pdf
  4425. # return sc.gamman+1)-sc.gammainc1+n, b)
  4426. if n == 1:
  4427. return (1-(b+1)*np.exp(-b))/(-sc.expm1(-b))
  4428. elif n == 2:
  4429. return 2*(1-0.5*(b*b+2*b+2)*np.exp(-b))/(-sc.expm1(-b))
  4430. else:
  4431. # return generic for higher moments
  4432. # return rv_continuous._mom1_sc(self, n, b)
  4433. return self._mom1_sc(n, b)
  4434. def _entropy(self, b):
  4435. eB = np.exp(b)
  4436. return np.log(eB-1)+(1+eB*(b-1.0))/(1.0-eB)
  4437. truncexpon = truncexpon_gen(a=0.0, name='truncexpon')
  4438. class truncnorm_gen(rv_continuous):
  4439. r"""A truncated normal continuous random variable.
  4440. %(before_notes)s
  4441. Notes
  4442. -----
  4443. The standard form of this distribution is a standard normal truncated to
  4444. the range [a, b] --- notice that a and b are defined over the domain of the
  4445. standard normal. To convert clip values for a specific mean and standard
  4446. deviation, use::
  4447. a, b = (myclip_a - my_mean) / my_std, (myclip_b - my_mean) / my_std
  4448. `truncnorm` takes :math:`a` and :math:`b` as shape parameters.
  4449. %(after_notes)s
  4450. %(example)s
  4451. """
  4452. def _argcheck(self, a, b):
  4453. self.a = a
  4454. self.b = b
  4455. self._nb = _norm_cdf(b)
  4456. self._na = _norm_cdf(a)
  4457. self._sb = _norm_sf(b)
  4458. self._sa = _norm_sf(a)
  4459. self._delta = np.where(self.a > 0,
  4460. -(self._sb - self._sa),
  4461. self._nb - self._na)
  4462. self._logdelta = np.log(self._delta)
  4463. return a < b
  4464. def _pdf(self, x, a, b):
  4465. return _norm_pdf(x) / self._delta
  4466. def _logpdf(self, x, a, b):
  4467. return _norm_logpdf(x) - self._logdelta
  4468. def _cdf(self, x, a, b):
  4469. return (_norm_cdf(x) - self._na) / self._delta
  4470. def _ppf(self, q, a, b):
  4471. # XXX Use _lazywhere...
  4472. ppf = np.where(self.a > 0,
  4473. _norm_isf(q*self._sb + self._sa*(1.0-q)),
  4474. _norm_ppf(q*self._nb + self._na*(1.0-q)))
  4475. return ppf
  4476. def _stats(self, a, b):
  4477. nA, nB = self._na, self._nb
  4478. d = nB - nA
  4479. pA, pB = _norm_pdf(a), _norm_pdf(b)
  4480. mu = (pA - pB) / d # correction sign
  4481. mu2 = 1 + (a*pA - b*pB) / d - mu*mu
  4482. return mu, mu2, None, None
  4483. truncnorm = truncnorm_gen(name='truncnorm')
  4484. # FIXME: RVS does not work.
  4485. class tukeylambda_gen(rv_continuous):
  4486. r"""A Tukey-Lamdba continuous random variable.
  4487. %(before_notes)s
  4488. Notes
  4489. -----
  4490. A flexible distribution, able to represent and interpolate between the
  4491. following distributions:
  4492. - Cauchy (:math:`lambda = -1`)
  4493. - logistic (:math:`lambda = 0`)
  4494. - approx Normal (:math:`lambda = 0.14`)
  4495. - uniform from -1 to 1 (:math:`lambda = 1`)
  4496. `tukeylambda` takes a real number :math:`lambda` (denoted ``lam``
  4497. in the implementation) as a shape parameter.
  4498. %(after_notes)s
  4499. %(example)s
  4500. """
  4501. def _argcheck(self, lam):
  4502. return np.ones(np.shape(lam), dtype=bool)
  4503. def _pdf(self, x, lam):
  4504. Fx = np.asarray(sc.tklmbda(x, lam))
  4505. Px = Fx**(lam-1.0) + (np.asarray(1-Fx))**(lam-1.0)
  4506. Px = 1.0/np.asarray(Px)
  4507. return np.where((lam <= 0) | (abs(x) < 1.0/np.asarray(lam)), Px, 0.0)
  4508. def _cdf(self, x, lam):
  4509. return sc.tklmbda(x, lam)
  4510. def _ppf(self, q, lam):
  4511. return sc.boxcox(q, lam) - sc.boxcox1p(-q, lam)
  4512. def _stats(self, lam):
  4513. return 0, _tlvar(lam), 0, _tlkurt(lam)
  4514. def _entropy(self, lam):
  4515. def integ(p):
  4516. return np.log(pow(p, lam-1)+pow(1-p, lam-1))
  4517. return integrate.quad(integ, 0, 1)[0]
  4518. tukeylambda = tukeylambda_gen(name='tukeylambda')
  4519. class FitUniformFixedScaleDataError(FitDataError):
  4520. def __init__(self, ptp, fscale):
  4521. self.args = (
  4522. "Invalid values in `data`. Maximum likelihood estimation with "
  4523. "the uniform distribution and fixed scale requires that "
  4524. "data.ptp() <= fscale, but data.ptp() = %r and fscale = %r." %
  4525. (ptp, fscale),
  4526. )
  4527. class uniform_gen(rv_continuous):
  4528. r"""A uniform continuous random variable.
  4529. In the standard form, the distribution is uniform on ``[0, 1]``. Using
  4530. the parameters ``loc`` and ``scale``, one obtains the uniform distribution
  4531. on ``[loc, loc + scale]``.
  4532. %(before_notes)s
  4533. %(example)s
  4534. """
  4535. def _rvs(self):
  4536. return self._random_state.uniform(0.0, 1.0, self._size)
  4537. def _pdf(self, x):
  4538. return 1.0*(x == x)
  4539. def _cdf(self, x):
  4540. return x
  4541. def _ppf(self, q):
  4542. return q
  4543. def _stats(self):
  4544. return 0.5, 1.0/12, 0, -1.2
  4545. def _entropy(self):
  4546. return 0.0
  4547. def fit(self, data, *args, **kwds):
  4548. """
  4549. Maximum likelihood estimate for the location and scale parameters.
  4550. `uniform.fit` uses only the following parameters. Because exact
  4551. formulas are used, the parameters related to optimization that are
  4552. available in the `fit` method of other distributions are ignored
  4553. here. The only positional argument accepted is `data`.
  4554. Parameters
  4555. ----------
  4556. data : array_like
  4557. Data to use in calculating the maximum likelihood estimate.
  4558. floc : float, optional
  4559. Hold the location parameter fixed to the specified value.
  4560. fscale : float, optional
  4561. Hold the scale parameter fixed to the specified value.
  4562. Returns
  4563. -------
  4564. loc, scale : float
  4565. Maximum likelihood estimates for the location and scale.
  4566. Notes
  4567. -----
  4568. An error is raised if `floc` is given and any values in `data` are
  4569. less than `floc`, or if `fscale` is given and `fscale` is less
  4570. than ``data.max() - data.min()``. An error is also raised if both
  4571. `floc` and `fscale` are given.
  4572. Examples
  4573. --------
  4574. >>> from scipy.stats import uniform
  4575. We'll fit the uniform distribution to `x`:
  4576. >>> x = np.array([2, 2.5, 3.1, 9.5, 13.0])
  4577. For a uniform distribution MLE, the location is the minimum of the
  4578. data, and the scale is the maximum minus the minimum.
  4579. >>> loc, scale = uniform.fit(x)
  4580. >>> loc
  4581. 2.0
  4582. >>> scale
  4583. 11.0
  4584. If we know the data comes from a uniform distribution where the support
  4585. starts at 0, we can use `floc=0`:
  4586. >>> loc, scale = uniform.fit(x, floc=0)
  4587. >>> loc
  4588. 0.0
  4589. >>> scale
  4590. 13.0
  4591. Alternatively, if we know the length of the support is 12, we can use
  4592. `fscale=12`:
  4593. >>> loc, scale = uniform.fit(x, fscale=12)
  4594. >>> loc
  4595. 1.5
  4596. >>> scale
  4597. 12.0
  4598. In that last example, the support interval is [1.5, 13.5]. This
  4599. solution is not unique. For example, the distribution with ``loc=2``
  4600. and ``scale=12`` has the same likelihood as the one above. When
  4601. `fscale` is given and it is larger than ``data.max() - data.min()``,
  4602. the parameters returned by the `fit` method center the support over
  4603. the interval ``[data.min(), data.max()]``.
  4604. """
  4605. if len(args) > 0:
  4606. raise TypeError("Too many arguments.")
  4607. floc = kwds.pop('floc', None)
  4608. fscale = kwds.pop('fscale', None)
  4609. # Ignore the optimizer-related keyword arguments, if given.
  4610. kwds.pop('loc', None)
  4611. kwds.pop('scale', None)
  4612. kwds.pop('optimizer', None)
  4613. if kwds:
  4614. raise TypeError("Unknown arguments: %s." % kwds)
  4615. if floc is not None and fscale is not None:
  4616. # This check is for consistency with `rv_continuous.fit`.
  4617. raise ValueError("All parameters fixed. There is nothing to "
  4618. "optimize.")
  4619. data = np.asarray(data)
  4620. # MLE for the uniform distribution
  4621. # --------------------------------
  4622. # The PDF is
  4623. #
  4624. # f(x, loc, scale) = {1/scale for loc <= x <= loc + scale
  4625. # {0 otherwise}
  4626. #
  4627. # The likelihood function is
  4628. # L(x, loc, scale) = (1/scale)**n
  4629. # where n is len(x), assuming loc <= x <= loc + scale for all x.
  4630. # The log-likelihood is
  4631. # l(x, loc, scale) = -n*log(scale)
  4632. # The log-likelihood is maximized by making scale as small as possible,
  4633. # while keeping loc <= x <= loc + scale. So if neither loc nor scale
  4634. # are fixed, the log-likelihood is maximized by choosing
  4635. # loc = x.min()
  4636. # scale = x.ptp()
  4637. # If loc is fixed, it must be less than or equal to x.min(), and then
  4638. # the scale is
  4639. # scale = x.max() - loc
  4640. # If scale is fixed, it must not be less than x.ptp(). If scale is
  4641. # greater than x.ptp(), the solution is not unique. Note that the
  4642. # likelihood does not depend on loc, except for the requirement that
  4643. # loc <= x <= loc + scale. All choices of loc for which
  4644. # x.max() - scale <= loc <= x.min()
  4645. # have the same log-likelihood. In this case, we choose loc such that
  4646. # the support is centered over the interval [data.min(), data.max()]:
  4647. # loc = x.min() = 0.5*(scale - x.ptp())
  4648. if fscale is None:
  4649. # scale is not fixed.
  4650. if floc is None:
  4651. # loc is not fixed, scale is not fixed.
  4652. loc = data.min()
  4653. scale = data.ptp()
  4654. else:
  4655. # loc is fixed, scale is not fixed.
  4656. loc = floc
  4657. scale = data.max() - loc
  4658. if data.min() < loc:
  4659. raise FitDataError("uniform", lower=loc, upper=loc + scale)
  4660. else:
  4661. # loc is not fixed, scale is fixed.
  4662. ptp = data.ptp()
  4663. if ptp > fscale:
  4664. raise FitUniformFixedScaleDataError(ptp=ptp, fscale=fscale)
  4665. # If ptp < fscale, the ML estimate is not unique; see the comments
  4666. # above. We choose the distribution for which the support is
  4667. # centered over the interval [data.min(), data.max()].
  4668. loc = data.min() - 0.5*(fscale - ptp)
  4669. scale = fscale
  4670. # We expect the return values to be floating point, so ensure it
  4671. # by explicitly converting to float.
  4672. return float(loc), float(scale)
  4673. uniform = uniform_gen(a=0.0, b=1.0, name='uniform')
  4674. class vonmises_gen(rv_continuous):
  4675. r"""A Von Mises continuous random variable.
  4676. %(before_notes)s
  4677. Notes
  4678. -----
  4679. The probability density function for `vonmises` and `vonmises_line` is:
  4680. .. math::
  4681. f(x, \kappa) = \frac{ \exp(\kappa \cos(x)) }{ 2 \pi I_0(\kappa) }
  4682. for :math:`-\pi \le x \le \pi`, :math:`\kappa > 0`. :math:`I_0` is the
  4683. modified Bessel function of order zero (`scipy.special.i0`).
  4684. `vonmises` is a circular distribution which does not restrict the
  4685. distribution to a fixed interval. Currently, there is no circular
  4686. distribution framework in scipy. The ``cdf`` is implemented such that
  4687. ``cdf(x + 2*np.pi) == cdf(x) + 1``.
  4688. `vonmises_line` is the same distribution, defined on :math:`[-\pi, \pi]`
  4689. on the real line. This is a regular (i.e. non-circular) distribution.
  4690. `vonmises` and `vonmises_line` take ``kappa`` as a shape parameter.
  4691. %(after_notes)s
  4692. %(example)s
  4693. """
  4694. def _rvs(self, kappa):
  4695. return self._random_state.vonmises(0.0, kappa, size=self._size)
  4696. def _pdf(self, x, kappa):
  4697. # vonmises.pdf(x, \kappa) = exp(\kappa * cos(x)) / (2*pi*I[0](\kappa))
  4698. return np.exp(kappa * np.cos(x)) / (2*np.pi*sc.i0(kappa))
  4699. def _cdf(self, x, kappa):
  4700. return _stats.von_mises_cdf(kappa, x)
  4701. def _stats_skip(self, kappa):
  4702. return 0, None, 0, None
  4703. def _entropy(self, kappa):
  4704. return (-kappa * sc.i1(kappa) / sc.i0(kappa) +
  4705. np.log(2 * np.pi * sc.i0(kappa)))
  4706. vonmises = vonmises_gen(name='vonmises')
  4707. vonmises_line = vonmises_gen(a=-np.pi, b=np.pi, name='vonmises_line')
  4708. class wald_gen(invgauss_gen):
  4709. r"""A Wald continuous random variable.
  4710. %(before_notes)s
  4711. Notes
  4712. -----
  4713. The probability density function for `wald` is:
  4714. .. math::
  4715. f(x) = \frac{1}{\sqrt{2\pi x^3}} \exp(- \frac{ (x-1)^2 }{ 2x })
  4716. for :math:`x > 0`.
  4717. `wald` is a special case of `invgauss` with ``mu=1``.
  4718. %(after_notes)s
  4719. %(example)s
  4720. """
  4721. _support_mask = rv_continuous._open_support_mask
  4722. def _rvs(self):
  4723. return self._random_state.wald(1.0, 1.0, size=self._size)
  4724. def _pdf(self, x):
  4725. # wald.pdf(x) = 1/sqrt(2*pi*x**3) * exp(-(x-1)**2/(2*x))
  4726. return invgauss._pdf(x, 1.0)
  4727. def _logpdf(self, x):
  4728. return invgauss._logpdf(x, 1.0)
  4729. def _cdf(self, x):
  4730. return invgauss._cdf(x, 1.0)
  4731. def _stats(self):
  4732. return 1.0, 1.0, 3.0, 15.0
  4733. wald = wald_gen(a=0.0, name="wald")
  4734. class wrapcauchy_gen(rv_continuous):
  4735. r"""A wrapped Cauchy continuous random variable.
  4736. %(before_notes)s
  4737. Notes
  4738. -----
  4739. The probability density function for `wrapcauchy` is:
  4740. .. math::
  4741. f(x, c) = \frac{1-c^2}{2\pi (1+c^2 - 2c \cos(x))}
  4742. for :math:`0 \le x \le 2\pi`, :math:`0 < c < 1`.
  4743. `wrapcauchy` takes ``c`` as a shape parameter for :math:`c`.
  4744. %(after_notes)s
  4745. %(example)s
  4746. """
  4747. def _argcheck(self, c):
  4748. return (c > 0) & (c < 1)
  4749. def _pdf(self, x, c):
  4750. # wrapcauchy.pdf(x, c) = (1-c**2) / (2*pi*(1+c**2-2*c*cos(x)))
  4751. return (1.0-c*c)/(2*np.pi*(1+c*c-2*c*np.cos(x)))
  4752. def _cdf(self, x, c):
  4753. output = np.zeros(x.shape, dtype=x.dtype)
  4754. val = (1.0+c)/(1.0-c)
  4755. c1 = x < np.pi
  4756. c2 = 1-c1
  4757. xp = np.extract(c1, x)
  4758. xn = np.extract(c2, x)
  4759. if np.any(xn):
  4760. valn = np.extract(c2, np.ones_like(x)*val)
  4761. xn = 2*np.pi - xn
  4762. yn = np.tan(xn/2.0)
  4763. on = 1.0-1.0/np.pi*np.arctan(valn*yn)
  4764. np.place(output, c2, on)
  4765. if np.any(xp):
  4766. valp = np.extract(c1, np.ones_like(x)*val)
  4767. yp = np.tan(xp/2.0)
  4768. op = 1.0/np.pi*np.arctan(valp*yp)
  4769. np.place(output, c1, op)
  4770. return output
  4771. def _ppf(self, q, c):
  4772. val = (1.0-c)/(1.0+c)
  4773. rcq = 2*np.arctan(val*np.tan(np.pi*q))
  4774. rcmq = 2*np.pi-2*np.arctan(val*np.tan(np.pi*(1-q)))
  4775. return np.where(q < 1.0/2, rcq, rcmq)
  4776. def _entropy(self, c):
  4777. return np.log(2*np.pi*(1-c*c))
  4778. wrapcauchy = wrapcauchy_gen(a=0.0, b=2*np.pi, name='wrapcauchy')
  4779. class gennorm_gen(rv_continuous):
  4780. r"""A generalized normal continuous random variable.
  4781. %(before_notes)s
  4782. Notes
  4783. -----
  4784. The probability density function for `gennorm` is [1]_:
  4785. .. math::
  4786. f(x, \beta) = \frac{\beta}{2 \Gamma(1/\beta)} \exp(-|x|^\beta)
  4787. :math:`\Gamma` is the gamma function (`scipy.special.gamma`).
  4788. `gennorm` takes ``beta`` as a shape parameter for :math:`\beta`.
  4789. For :math:`\beta = 1`, it is identical to a Laplace distribution.
  4790. For :math:`\beta = 2`, it is identical to a normal distribution
  4791. (with ``scale=1/sqrt(2)``).
  4792. See Also
  4793. --------
  4794. laplace : Laplace distribution
  4795. norm : normal distribution
  4796. References
  4797. ----------
  4798. .. [1] "Generalized normal distribution, Version 1",
  4799. https://en.wikipedia.org/wiki/Generalized_normal_distribution#Version_1
  4800. %(example)s
  4801. """
  4802. def _pdf(self, x, beta):
  4803. return np.exp(self._logpdf(x, beta))
  4804. def _logpdf(self, x, beta):
  4805. return np.log(0.5*beta) - sc.gammaln(1.0/beta) - abs(x)**beta
  4806. def _cdf(self, x, beta):
  4807. c = 0.5 * np.sign(x)
  4808. # evaluating (.5 + c) first prevents numerical cancellation
  4809. return (0.5 + c) - c * sc.gammaincc(1.0/beta, abs(x)**beta)
  4810. def _ppf(self, x, beta):
  4811. c = np.sign(x - 0.5)
  4812. # evaluating (1. + c) first prevents numerical cancellation
  4813. return c * sc.gammainccinv(1.0/beta, (1.0 + c) - 2.0*c*x)**(1.0/beta)
  4814. def _sf(self, x, beta):
  4815. return self._cdf(-x, beta)
  4816. def _isf(self, x, beta):
  4817. return -self._ppf(x, beta)
  4818. def _stats(self, beta):
  4819. c1, c3, c5 = sc.gammaln([1.0/beta, 3.0/beta, 5.0/beta])
  4820. return 0., np.exp(c3 - c1), 0., np.exp(c5 + c1 - 2.0*c3) - 3.
  4821. def _entropy(self, beta):
  4822. return 1. / beta - np.log(.5 * beta) + sc.gammaln(1. / beta)
  4823. gennorm = gennorm_gen(name='gennorm')
  4824. class halfgennorm_gen(rv_continuous):
  4825. r"""The upper half of a generalized normal continuous random variable.
  4826. %(before_notes)s
  4827. Notes
  4828. -----
  4829. The probability density function for `halfgennorm` is:
  4830. .. math::
  4831. f(x, \beta) = \frac{\beta}{\Gamma(1/\beta)} \exp(-|x|^\beta)
  4832. for :math:`x > 0`. :math:`\Gamma` is the gamma function
  4833. (`scipy.special.gamma`).
  4834. `gennorm` takes ``beta`` as a shape parameter for :math:`\beta`.
  4835. For :math:`\beta = 1`, it is identical to an exponential distribution.
  4836. For :math:`\beta = 2`, it is identical to a half normal distribution
  4837. (with ``scale=1/sqrt(2)``).
  4838. See Also
  4839. --------
  4840. gennorm : generalized normal distribution
  4841. expon : exponential distribution
  4842. halfnorm : half normal distribution
  4843. References
  4844. ----------
  4845. .. [1] "Generalized normal distribution, Version 1",
  4846. https://en.wikipedia.org/wiki/Generalized_normal_distribution#Version_1
  4847. %(example)s
  4848. """
  4849. def _pdf(self, x, beta):
  4850. # beta
  4851. # halfgennorm.pdf(x, beta) = ------------- exp(-|x|**beta)
  4852. # gamma(1/beta)
  4853. return np.exp(self._logpdf(x, beta))
  4854. def _logpdf(self, x, beta):
  4855. return np.log(beta) - sc.gammaln(1.0/beta) - x**beta
  4856. def _cdf(self, x, beta):
  4857. return sc.gammainc(1.0/beta, x**beta)
  4858. def _ppf(self, x, beta):
  4859. return sc.gammaincinv(1.0/beta, x)**(1.0/beta)
  4860. def _sf(self, x, beta):
  4861. return sc.gammaincc(1.0/beta, x**beta)
  4862. def _isf(self, x, beta):
  4863. return sc.gammainccinv(1.0/beta, x)**(1.0/beta)
  4864. def _entropy(self, beta):
  4865. return 1.0/beta - np.log(beta) + sc.gammaln(1.0/beta)
  4866. halfgennorm = halfgennorm_gen(a=0, name='halfgennorm')
  4867. class crystalball_gen(rv_continuous):
  4868. r"""
  4869. Crystalball distribution
  4870. %(before_notes)s
  4871. Notes
  4872. -----
  4873. The probability density function for `crystalball` is:
  4874. .. math::
  4875. f(x, \beta, m) = \begin{cases}
  4876. N \exp(-x^2 / 2), &\text{for } x > -\beta\\
  4877. N A (B - x)^{-m} &\text{for } x \le -\beta
  4878. \end{cases}
  4879. where :math:`A = (m / |\beta|)^n \exp(-\beta^2 / 2)`,
  4880. :math:`B = m/|\beta| - |\beta|` and :math:`N` is a normalisation constant.
  4881. `crystalball` takes :math:`\beta > 0` and :math:`m > 1` as shape
  4882. parameters. :math:`\beta` defines the point where the pdf changes
  4883. from a power-law to a Gaussian distribution. :math:`m` is the power
  4884. of the power-law tail.
  4885. References
  4886. ----------
  4887. .. [1] "Crystal Ball Function",
  4888. https://en.wikipedia.org/wiki/Crystal_Ball_function
  4889. %(after_notes)s
  4890. .. versionadded:: 0.19.0
  4891. %(example)s
  4892. """
  4893. def _pdf(self, x, beta, m):
  4894. """
  4895. Return PDF of the crystalball function.
  4896. --
  4897. | exp(-x**2 / 2), for x > -beta
  4898. crystalball.pdf(x, beta, m) = N * |
  4899. | A * (B - x)**(-m), for x <= -beta
  4900. --
  4901. """
  4902. N = 1.0 / (m/beta / (m-1) * np.exp(-beta**2 / 2.0) +
  4903. _norm_pdf_C * _norm_cdf(beta))
  4904. def rhs(x, beta, m):
  4905. return np.exp(-x**2 / 2)
  4906. def lhs(x, beta, m):
  4907. return ((m/beta)**m * np.exp(-beta**2 / 2.0) *
  4908. (m/beta - beta - x)**(-m))
  4909. return N * _lazywhere(x > -beta, (x, beta, m), f=rhs, f2=lhs)
  4910. def _logpdf(self, x, beta, m):
  4911. """
  4912. Return the log of the PDF of the crystalball function.
  4913. """
  4914. N = 1.0 / (m/beta / (m-1) * np.exp(-beta**2 / 2.0) +
  4915. _norm_pdf_C * _norm_cdf(beta))
  4916. def rhs(x, beta, m):
  4917. return -x**2/2
  4918. def lhs(x, beta, m):
  4919. return m*np.log(m/beta) - beta**2/2 - m*np.log(m/beta - beta - x)
  4920. return np.log(N) + _lazywhere(x > -beta, (x, beta, m), f=rhs, f2=lhs)
  4921. def _cdf(self, x, beta, m):
  4922. """
  4923. Return CDF of the crystalball function
  4924. """
  4925. N = 1.0 / (m/beta / (m-1) * np.exp(-beta**2 / 2.0) +
  4926. _norm_pdf_C * _norm_cdf(beta))
  4927. def rhs(x, beta, m):
  4928. return ((m/beta) * np.exp(-beta**2 / 2.0) / (m-1) +
  4929. _norm_pdf_C * (_norm_cdf(x) - _norm_cdf(-beta)))
  4930. def lhs(x, beta, m):
  4931. return ((m/beta)**m * np.exp(-beta**2 / 2.0) *
  4932. (m/beta - beta - x)**(-m+1) / (m-1))
  4933. return N * _lazywhere(x > -beta, (x, beta, m), f=rhs, f2=lhs)
  4934. def _ppf(self, p, beta, m):
  4935. N = 1.0 / (m/beta / (m-1) * np.exp(-beta**2 / 2.0) +
  4936. _norm_pdf_C * _norm_cdf(beta))
  4937. pbeta = N * (m/beta) * np.exp(-beta**2/2) / (m - 1)
  4938. def ppf_less(p, beta, m):
  4939. eb2 = np.exp(-beta**2/2)
  4940. C = (m/beta) * eb2 / (m-1)
  4941. N = 1/(C + _norm_pdf_C * _norm_cdf(beta))
  4942. return (m/beta - beta -
  4943. ((m - 1)*(m/beta)**(-m)/eb2*p/N)**(1/(1-m)))
  4944. def ppf_greater(p, beta, m):
  4945. eb2 = np.exp(-beta**2/2)
  4946. C = (m/beta) * eb2 / (m-1)
  4947. N = 1/(C + _norm_pdf_C * _norm_cdf(beta))
  4948. return _norm_ppf(_norm_cdf(-beta) + (1/_norm_pdf_C)*(p/N - C))
  4949. return _lazywhere(p < pbeta, (p, beta, m), f=ppf_less, f2=ppf_greater)
  4950. def _munp(self, n, beta, m):
  4951. """
  4952. Returns the n-th non-central moment of the crystalball function.
  4953. """
  4954. N = 1.0 / (m/beta / (m-1) * np.exp(-beta**2 / 2.0) +
  4955. _norm_pdf_C * _norm_cdf(beta))
  4956. def n_th_moment(n, beta, m):
  4957. """
  4958. Returns n-th moment. Defined only if n+1 < m
  4959. Function cannot broadcast due to the loop over n
  4960. """
  4961. A = (m/beta)**m * np.exp(-beta**2 / 2.0)
  4962. B = m/beta - beta
  4963. rhs = (2**((n-1)/2.0) * sc.gamma((n+1)/2) *
  4964. (1.0 + (-1)**n * sc.gammainc((n+1)/2, beta**2 / 2)))
  4965. lhs = np.zeros(rhs.shape)
  4966. for k in range(n + 1):
  4967. lhs += (sc.binom(n, k) * B**(n-k) * (-1)**k / (m - k - 1) *
  4968. (m/beta)**(-m + k + 1))
  4969. return A * lhs + rhs
  4970. return N * _lazywhere(n + 1 < m, (n, beta, m),
  4971. np.vectorize(n_th_moment, otypes=[np.float]),
  4972. np.inf)
  4973. def _argcheck(self, beta, m):
  4974. """
  4975. Shape parameter bounds are m > 1 and beta > 0.
  4976. """
  4977. return (m > 1) & (beta > 0)
  4978. crystalball = crystalball_gen(name='crystalball', longname="A Crystalball Function")
  4979. def _argus_phi(chi):
  4980. """
  4981. Utility function for the argus distribution
  4982. used in the CDF and norm of the Argus Funktion
  4983. """
  4984. return _norm_cdf(chi) - chi * _norm_pdf(chi) - 0.5
  4985. class argus_gen(rv_continuous):
  4986. r"""
  4987. Argus distribution
  4988. %(before_notes)s
  4989. Notes
  4990. -----
  4991. The probability density function for `argus` is:
  4992. .. math::
  4993. f(x, \chi) = \frac{\chi^3}{\sqrt{2\pi} \Psi(\chi)} x \sqrt{1-x^2}
  4994. \exp(-\chi^2 (1 - x^2)/2)
  4995. for :math:`0 < x < 1`, where
  4996. .. math::
  4997. \Psi(\chi) = \Phi(\chi) - \chi \phi(\chi) - 1/2
  4998. with :math:`\Phi` and :math:`\phi` being the CDF and PDF of a standard
  4999. normal distribution, respectively.
  5000. `argus` takes :math:`\chi` as shape a parameter.
  5001. References
  5002. ----------
  5003. .. [1] "ARGUS distribution",
  5004. https://en.wikipedia.org/wiki/ARGUS_distribution
  5005. %(after_notes)s
  5006. .. versionadded:: 0.19.0
  5007. %(example)s
  5008. """
  5009. def _pdf(self, x, chi):
  5010. """
  5011. Return PDF of the argus function
  5012. argus.pdf(x, chi) = chi**3 / (sqrt(2*pi) * Psi(chi)) * x *
  5013. sqrt(1-x**2) * exp(- 0.5 * chi**2 * (1 - x**2))
  5014. """
  5015. y = 1.0 - x**2
  5016. return chi**3 / (_norm_pdf_C * _argus_phi(chi)) * x * np.sqrt(y) * np.exp(-chi**2 * y / 2)
  5017. def _cdf(self, x, chi):
  5018. """
  5019. Return CDF of the argus function
  5020. """
  5021. return 1.0 - self._sf(x, chi)
  5022. def _sf(self, x, chi):
  5023. """
  5024. Return survival function of the argus function
  5025. """
  5026. return _argus_phi(chi * np.sqrt(1 - x**2)) / _argus_phi(chi)
  5027. argus = argus_gen(name='argus', longname="An Argus Function", a=0.0, b=1.0)
  5028. class rv_histogram(rv_continuous):
  5029. """
  5030. Generates a distribution given by a histogram.
  5031. This is useful to generate a template distribution from a binned
  5032. datasample.
  5033. As a subclass of the `rv_continuous` class, `rv_histogram` inherits from it
  5034. a collection of generic methods (see `rv_continuous` for the full list),
  5035. and implements them based on the properties of the provided binned
  5036. datasample.
  5037. Parameters
  5038. ----------
  5039. histogram : tuple of array_like
  5040. Tuple containing two array_like objects
  5041. The first containing the content of n bins
  5042. The second containing the (n+1) bin boundaries
  5043. In particular the return value np.histogram is accepted
  5044. Notes
  5045. -----
  5046. There are no additional shape parameters except for the loc and scale.
  5047. The pdf is defined as a stepwise function from the provided histogram
  5048. The cdf is a linear interpolation of the pdf.
  5049. .. versionadded:: 0.19.0
  5050. Examples
  5051. --------
  5052. Create a scipy.stats distribution from a numpy histogram
  5053. >>> import scipy.stats
  5054. >>> import numpy as np
  5055. >>> data = scipy.stats.norm.rvs(size=100000, loc=0, scale=1.5, random_state=123)
  5056. >>> hist = np.histogram(data, bins=100)
  5057. >>> hist_dist = scipy.stats.rv_histogram(hist)
  5058. Behaves like an ordinary scipy rv_continuous distribution
  5059. >>> hist_dist.pdf(1.0)
  5060. 0.20538577847618705
  5061. >>> hist_dist.cdf(2.0)
  5062. 0.90818568543056499
  5063. PDF is zero above (below) the highest (lowest) bin of the histogram,
  5064. defined by the max (min) of the original dataset
  5065. >>> hist_dist.pdf(np.max(data))
  5066. 0.0
  5067. >>> hist_dist.cdf(np.max(data))
  5068. 1.0
  5069. >>> hist_dist.pdf(np.min(data))
  5070. 7.7591907244498314e-05
  5071. >>> hist_dist.cdf(np.min(data))
  5072. 0.0
  5073. PDF and CDF follow the histogram
  5074. >>> import matplotlib.pyplot as plt
  5075. >>> X = np.linspace(-5.0, 5.0, 100)
  5076. >>> plt.title("PDF from Template")
  5077. >>> plt.hist(data, density=True, bins=100)
  5078. >>> plt.plot(X, hist_dist.pdf(X), label='PDF')
  5079. >>> plt.plot(X, hist_dist.cdf(X), label='CDF')
  5080. >>> plt.show()
  5081. """
  5082. _support_mask = rv_continuous._support_mask
  5083. def __init__(self, histogram, *args, **kwargs):
  5084. """
  5085. Create a new distribution using the given histogram
  5086. Parameters
  5087. ----------
  5088. histogram : tuple of array_like
  5089. Tuple containing two array_like objects
  5090. The first containing the content of n bins
  5091. The second containing the (n+1) bin boundaries
  5092. In particular the return value np.histogram is accepted
  5093. """
  5094. self._histogram = histogram
  5095. if len(histogram) != 2:
  5096. raise ValueError("Expected length 2 for parameter histogram")
  5097. self._hpdf = np.asarray(histogram[0])
  5098. self._hbins = np.asarray(histogram[1])
  5099. if len(self._hpdf) + 1 != len(self._hbins):
  5100. raise ValueError("Number of elements in histogram content "
  5101. "and histogram boundaries do not match, "
  5102. "expected n and n+1.")
  5103. self._hbin_widths = self._hbins[1:] - self._hbins[:-1]
  5104. self._hpdf = self._hpdf / float(np.sum(self._hpdf * self._hbin_widths))
  5105. self._hcdf = np.cumsum(self._hpdf * self._hbin_widths)
  5106. self._hpdf = np.hstack([0.0, self._hpdf, 0.0])
  5107. self._hcdf = np.hstack([0.0, self._hcdf])
  5108. # Set support
  5109. kwargs['a'] = self._hbins[0]
  5110. kwargs['b'] = self._hbins[-1]
  5111. super(rv_histogram, self).__init__(*args, **kwargs)
  5112. def _pdf(self, x):
  5113. """
  5114. PDF of the histogram
  5115. """
  5116. return self._hpdf[np.searchsorted(self._hbins, x, side='right')]
  5117. def _cdf(self, x):
  5118. """
  5119. CDF calculated from the histogram
  5120. """
  5121. return np.interp(x, self._hbins, self._hcdf)
  5122. def _ppf(self, x):
  5123. """
  5124. Percentile function calculated from the histogram
  5125. """
  5126. return np.interp(x, self._hcdf, self._hbins)
  5127. def _munp(self, n):
  5128. """Compute the n-th non-central moment."""
  5129. integrals = (self._hbins[1:]**(n+1) - self._hbins[:-1]**(n+1)) / (n+1)
  5130. return np.sum(self._hpdf[1:-1] * integrals)
  5131. def _entropy(self):
  5132. """Compute entropy of distribution"""
  5133. res = _lazywhere(self._hpdf[1:-1] > 0.0,
  5134. (self._hpdf[1:-1],),
  5135. np.log,
  5136. 0.0)
  5137. return -np.sum(self._hpdf[1:-1] * res * self._hbin_widths)
  5138. def _updated_ctor_param(self):
  5139. """
  5140. Set the histogram as additional constructor argument
  5141. """
  5142. dct = super(rv_histogram, self)._updated_ctor_param()
  5143. dct['histogram'] = self._histogram
  5144. return dct
  5145. # Collect names of classes and objects in this module.
  5146. pairs = list(globals().items())
  5147. _distn_names, _distn_gen_names = get_distribution_names(pairs, rv_continuous)
  5148. __all__ = _distn_names + _distn_gen_names + ['rv_histogram']