test_distributions.py 292 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625
  1. """
  2. Test functions for stats module
  3. """
  4. import warnings
  5. import re
  6. import sys
  7. import pickle
  8. from pathlib import Path
  9. import os
  10. import json
  11. import platform
  12. from numpy.testing import (assert_equal, assert_array_equal,
  13. assert_almost_equal, assert_array_almost_equal,
  14. assert_allclose, assert_, assert_warns,
  15. assert_array_less, suppress_warnings, IS_PYPY)
  16. import pytest
  17. from pytest import raises as assert_raises
  18. import numpy
  19. import numpy as np
  20. from numpy import typecodes, array
  21. from numpy.lib.recfunctions import rec_append_fields
  22. from scipy import special
  23. from scipy._lib._util import check_random_state
  24. from scipy.integrate import (IntegrationWarning, quad, trapezoid,
  25. cumulative_trapezoid)
  26. import scipy.stats as stats
  27. from scipy.stats._distn_infrastructure import argsreduce
  28. import scipy.stats.distributions
  29. from scipy.special import xlogy, polygamma, entr
  30. from scipy.stats._distr_params import distcont, invdistcont
  31. from .test_discrete_basic import distdiscrete, invdistdiscrete
  32. from scipy.stats._continuous_distns import FitDataError, _argus_phi
  33. from scipy.optimize import root, fmin
  34. from itertools import product
  35. # python -OO strips docstrings
  36. DOCSTRINGS_STRIPPED = sys.flags.optimize > 1
  37. # Failing on macOS 11, Intel CPUs. See gh-14901
  38. MACOS_INTEL = (sys.platform == 'darwin') and (platform.machine() == 'x86_64')
  39. # distributions to skip while testing the fix for the support method
  40. # introduced in gh-13294. These distributions are skipped as they
  41. # always return a non-nan support for every parametrization.
  42. skip_test_support_gh13294_regression = ['tukeylambda', 'pearson3']
  43. def _assert_hasattr(a, b, msg=None):
  44. if msg is None:
  45. msg = '%s does not have attribute %s' % (a, b)
  46. assert_(hasattr(a, b), msg=msg)
  47. def test_api_regression():
  48. # https://github.com/scipy/scipy/issues/3802
  49. _assert_hasattr(scipy.stats.distributions, 'f_gen')
  50. def check_vonmises_pdf_periodic(k, L, s, x):
  51. vm = stats.vonmises(k, loc=L, scale=s)
  52. assert_almost_equal(vm.pdf(x), vm.pdf(x % (2*numpy.pi*s)))
  53. def check_vonmises_cdf_periodic(k, L, s, x):
  54. vm = stats.vonmises(k, loc=L, scale=s)
  55. assert_almost_equal(vm.cdf(x) % 1, vm.cdf(x % (2*numpy.pi*s)) % 1)
  56. def test_distributions_submodule():
  57. actual = set(scipy.stats.distributions.__all__)
  58. continuous = [dist[0] for dist in distcont] # continuous dist names
  59. discrete = [dist[0] for dist in distdiscrete] # discrete dist names
  60. other = ['rv_discrete', 'rv_continuous', 'rv_histogram',
  61. 'entropy', 'trapz']
  62. expected = continuous + discrete + other
  63. # need to remove, e.g.,
  64. # <scipy.stats._continuous_distns.trapezoid_gen at 0x1df83bbc688>
  65. expected = set(filter(lambda s: not str(s).startswith('<'), expected))
  66. # gilbrat is deprecated and no longer in distcont
  67. actual.remove('gilbrat')
  68. assert actual == expected
  69. def test_vonmises_pdf_periodic():
  70. for k in [0.1, 1, 101]:
  71. for x in [0, 1, numpy.pi, 10, 100]:
  72. check_vonmises_pdf_periodic(k, 0, 1, x)
  73. check_vonmises_pdf_periodic(k, 1, 1, x)
  74. check_vonmises_pdf_periodic(k, 0, 10, x)
  75. check_vonmises_cdf_periodic(k, 0, 1, x)
  76. check_vonmises_cdf_periodic(k, 1, 1, x)
  77. check_vonmises_cdf_periodic(k, 0, 10, x)
  78. def test_vonmises_line_support():
  79. assert_equal(stats.vonmises_line.a, -np.pi)
  80. assert_equal(stats.vonmises_line.b, np.pi)
  81. def test_vonmises_numerical():
  82. vm = stats.vonmises(800)
  83. assert_almost_equal(vm.cdf(0), 0.5)
  84. # Expected values of the vonmises PDF were computed using
  85. # mpmath with 50 digits of precision:
  86. #
  87. # def vmpdf_mp(x, kappa):
  88. # x = mpmath.mpf(x)
  89. # kappa = mpmath.mpf(kappa)
  90. # num = mpmath.exp(kappa*mpmath.cos(x))
  91. # den = 2 * mpmath.pi * mpmath.besseli(0, kappa)
  92. # return num/den
  93. @pytest.mark.parametrize('x, kappa, expected_pdf',
  94. [(0.1, 0.01, 0.16074242744907072),
  95. (0.1, 25.0, 1.7515464099118245),
  96. (0.1, 800, 0.2073272544458798),
  97. (2.0, 0.01, 0.15849003875385817),
  98. (2.0, 25.0, 8.356882934278192e-16),
  99. (2.0, 800, 0.0)])
  100. def test_vonmises_pdf(x, kappa, expected_pdf):
  101. pdf = stats.vonmises.pdf(x, kappa)
  102. assert_allclose(pdf, expected_pdf, rtol=1e-15)
  103. # Expected values of the vonmises entropy were computed using
  104. # mpmath with 50 digits of precision:
  105. #
  106. # def vonmises_entropy(kappa):
  107. # kappa = mpmath.mpf(kappa)
  108. # return (-kappa * mpmath.besseli(1, kappa) /
  109. # mpmath.besseli(0, kappa) + mpmath.log(2 * mpmath.pi *
  110. # mpmath.besseli(0, kappa)))
  111. # >>> float(vonmises_entropy(kappa))
  112. @pytest.mark.parametrize('kappa, expected_entropy',
  113. [(1, 1.6274014590199897),
  114. (5, 0.6756431570114528),
  115. (100, -0.8811275441649473),
  116. (1000, -2.03468891852547),
  117. (2000, -2.3813876496587847)])
  118. def test_vonmises_entropy(kappa, expected_entropy):
  119. entropy = stats.vonmises.entropy(kappa)
  120. assert_allclose(entropy, expected_entropy, rtol=1e-13)
  121. def test_vonmises_rvs_gh4598():
  122. # check that random variates wrap around as discussed in gh-4598
  123. seed = abs(hash('von_mises_rvs'))
  124. rng1 = np.random.default_rng(seed)
  125. rng2 = np.random.default_rng(seed)
  126. rng3 = np.random.default_rng(seed)
  127. rvs1 = stats.vonmises(1, loc=0, scale=1).rvs(random_state=rng1)
  128. rvs2 = stats.vonmises(1, loc=2*np.pi, scale=1).rvs(random_state=rng2)
  129. rvs3 = stats.vonmises(1, loc=0,
  130. scale=(2*np.pi/abs(rvs1)+1)).rvs(random_state=rng3)
  131. assert_allclose(rvs1, rvs2, atol=1e-15)
  132. assert_allclose(rvs1, rvs3, atol=1e-15)
  133. # Expected values of the vonmises LOGPDF were computed
  134. # using wolfram alpha:
  135. # kappa * cos(x) - log(2*pi*I0(kappa))
  136. @pytest.mark.parametrize('x, kappa, expected_logpdf',
  137. [(0.1, 0.01, -1.8279520246003170),
  138. (0.1, 25.0, 0.5604990605420549),
  139. (0.1, 800, -1.5734567947337514),
  140. (2.0, 0.01, -1.8420635346185686),
  141. (2.0, 25.0, -34.7182759850871489),
  142. (2.0, 800, -1130.4942582548682739)])
  143. def test_vonmises_logpdf(x, kappa, expected_logpdf):
  144. logpdf = stats.vonmises.logpdf(x, kappa)
  145. assert_allclose(logpdf, expected_logpdf, rtol=1e-15)
  146. def test_vonmises_expect():
  147. """
  148. Test that the vonmises expectation values are
  149. computed correctly. This test checks that the
  150. numeric integration estimates the correct normalization
  151. (1) and mean angle (loc). These expectations are
  152. independent of the chosen 2pi interval.
  153. """
  154. rng = np.random.default_rng(6762668991392531563)
  155. loc, kappa, lb = rng.random(3) * 10
  156. res = stats.vonmises(loc=loc, kappa=kappa).expect(lambda x: 1)
  157. assert_allclose(res, 1)
  158. assert np.issubdtype(res.dtype, np.floating)
  159. bounds = lb, lb + 2 * np.pi
  160. res = stats.vonmises(loc=loc, kappa=kappa).expect(lambda x: 1, *bounds)
  161. assert_allclose(res, 1)
  162. assert np.issubdtype(res.dtype, np.floating)
  163. bounds = lb, lb + 2 * np.pi
  164. res = stats.vonmises(loc=loc, kappa=kappa).expect(lambda x: np.exp(1j*x),
  165. *bounds, complex_func=1)
  166. assert_allclose(np.angle(res), loc % (2*np.pi))
  167. assert np.issubdtype(res.dtype, np.complexfloating)
  168. def _assert_less_or_close_loglike(dist, data, func, **kwds):
  169. """
  170. This utility function checks that the log-likelihood (computed by
  171. func) of the result computed using dist.fit() is less than or equal
  172. to the result computed using the generic fit method. Because of
  173. normal numerical imprecision, the "equality" check is made using
  174. `np.allclose` with a relative tolerance of 1e-15.
  175. """
  176. mle_analytical = dist.fit(data, **kwds)
  177. numerical_opt = super(type(dist), dist).fit(data, **kwds)
  178. ll_mle_analytical = func(mle_analytical, data)
  179. ll_numerical_opt = func(numerical_opt, data)
  180. assert (ll_mle_analytical <= ll_numerical_opt or
  181. np.allclose(ll_mle_analytical, ll_numerical_opt, rtol=1e-15))
  182. def assert_fit_warnings(dist):
  183. param = ['floc', 'fscale']
  184. if dist.shapes:
  185. nshapes = len(dist.shapes.split(","))
  186. param += ['f0', 'f1', 'f2'][:nshapes]
  187. all_fixed = dict(zip(param, np.arange(len(param))))
  188. data = [1, 2, 3]
  189. with pytest.raises(RuntimeError,
  190. match="All parameters fixed. There is nothing "
  191. "to optimize."):
  192. dist.fit(data, **all_fixed)
  193. with pytest.raises(ValueError,
  194. match="The data contains non-finite values"):
  195. dist.fit([np.nan])
  196. with pytest.raises(ValueError,
  197. match="The data contains non-finite values"):
  198. dist.fit([np.inf])
  199. with pytest.raises(TypeError, match="Unknown keyword arguments:"):
  200. dist.fit(data, extra_keyword=2)
  201. with pytest.raises(TypeError, match="Too many positional arguments."):
  202. dist.fit(data, *[1]*(len(param) - 1))
  203. @pytest.mark.parametrize('dist',
  204. ['alpha', 'betaprime',
  205. 'fatiguelife', 'invgamma', 'invgauss', 'invweibull',
  206. 'johnsonsb', 'levy', 'levy_l', 'lognorm', 'gibrat',
  207. 'powerlognorm', 'rayleigh', 'wald'])
  208. def test_support(dist):
  209. """gh-6235"""
  210. dct = dict(distcont)
  211. args = dct[dist]
  212. dist = getattr(stats, dist)
  213. assert_almost_equal(dist.pdf(dist.a, *args), 0)
  214. assert_equal(dist.logpdf(dist.a, *args), -np.inf)
  215. assert_almost_equal(dist.pdf(dist.b, *args), 0)
  216. assert_equal(dist.logpdf(dist.b, *args), -np.inf)
  217. class TestRandInt:
  218. def setup_method(self):
  219. np.random.seed(1234)
  220. def test_rvs(self):
  221. vals = stats.randint.rvs(5, 30, size=100)
  222. assert_(numpy.all(vals < 30) & numpy.all(vals >= 5))
  223. assert_(len(vals) == 100)
  224. vals = stats.randint.rvs(5, 30, size=(2, 50))
  225. assert_(numpy.shape(vals) == (2, 50))
  226. assert_(vals.dtype.char in typecodes['AllInteger'])
  227. val = stats.randint.rvs(15, 46)
  228. assert_((val >= 15) & (val < 46))
  229. assert_(isinstance(val, numpy.ScalarType), msg=repr(type(val)))
  230. val = stats.randint(15, 46).rvs(3)
  231. assert_(val.dtype.char in typecodes['AllInteger'])
  232. def test_pdf(self):
  233. k = numpy.r_[0:36]
  234. out = numpy.where((k >= 5) & (k < 30), 1.0/(30-5), 0)
  235. vals = stats.randint.pmf(k, 5, 30)
  236. assert_array_almost_equal(vals, out)
  237. def test_cdf(self):
  238. x = np.linspace(0, 36, 100)
  239. k = numpy.floor(x)
  240. out = numpy.select([k >= 30, k >= 5], [1.0, (k-5.0+1)/(30-5.0)], 0)
  241. vals = stats.randint.cdf(x, 5, 30)
  242. assert_array_almost_equal(vals, out, decimal=12)
  243. class TestBinom:
  244. def setup_method(self):
  245. np.random.seed(1234)
  246. def test_rvs(self):
  247. vals = stats.binom.rvs(10, 0.75, size=(2, 50))
  248. assert_(numpy.all(vals >= 0) & numpy.all(vals <= 10))
  249. assert_(numpy.shape(vals) == (2, 50))
  250. assert_(vals.dtype.char in typecodes['AllInteger'])
  251. val = stats.binom.rvs(10, 0.75)
  252. assert_(isinstance(val, int))
  253. val = stats.binom(10, 0.75).rvs(3)
  254. assert_(isinstance(val, numpy.ndarray))
  255. assert_(val.dtype.char in typecodes['AllInteger'])
  256. def test_pmf(self):
  257. # regression test for Ticket #1842
  258. vals1 = stats.binom.pmf(100, 100, 1)
  259. vals2 = stats.binom.pmf(0, 100, 0)
  260. assert_allclose(vals1, 1.0, rtol=1e-15, atol=0)
  261. assert_allclose(vals2, 1.0, rtol=1e-15, atol=0)
  262. def test_entropy(self):
  263. # Basic entropy tests.
  264. b = stats.binom(2, 0.5)
  265. expected_p = np.array([0.25, 0.5, 0.25])
  266. expected_h = -sum(xlogy(expected_p, expected_p))
  267. h = b.entropy()
  268. assert_allclose(h, expected_h)
  269. b = stats.binom(2, 0.0)
  270. h = b.entropy()
  271. assert_equal(h, 0.0)
  272. b = stats.binom(2, 1.0)
  273. h = b.entropy()
  274. assert_equal(h, 0.0)
  275. def test_warns_p0(self):
  276. # no spurious warnigns are generated for p=0; gh-3817
  277. with warnings.catch_warnings():
  278. warnings.simplefilter("error", RuntimeWarning)
  279. assert_equal(stats.binom(n=2, p=0).mean(), 0)
  280. assert_equal(stats.binom(n=2, p=0).std(), 0)
  281. class TestArcsine:
  282. def test_endpoints(self):
  283. # Regression test for gh-13697. The following calculation
  284. # should not generate a warning.
  285. p = stats.arcsine.pdf([0, 1])
  286. assert_equal(p, [np.inf, np.inf])
  287. class TestBernoulli:
  288. def setup_method(self):
  289. np.random.seed(1234)
  290. def test_rvs(self):
  291. vals = stats.bernoulli.rvs(0.75, size=(2, 50))
  292. assert_(numpy.all(vals >= 0) & numpy.all(vals <= 1))
  293. assert_(numpy.shape(vals) == (2, 50))
  294. assert_(vals.dtype.char in typecodes['AllInteger'])
  295. val = stats.bernoulli.rvs(0.75)
  296. assert_(isinstance(val, int))
  297. val = stats.bernoulli(0.75).rvs(3)
  298. assert_(isinstance(val, numpy.ndarray))
  299. assert_(val.dtype.char in typecodes['AllInteger'])
  300. def test_entropy(self):
  301. # Simple tests of entropy.
  302. b = stats.bernoulli(0.25)
  303. expected_h = -0.25*np.log(0.25) - 0.75*np.log(0.75)
  304. h = b.entropy()
  305. assert_allclose(h, expected_h)
  306. b = stats.bernoulli(0.0)
  307. h = b.entropy()
  308. assert_equal(h, 0.0)
  309. b = stats.bernoulli(1.0)
  310. h = b.entropy()
  311. assert_equal(h, 0.0)
  312. class TestBradford:
  313. # gh-6216
  314. def test_cdf_ppf(self):
  315. c = 0.1
  316. x = np.logspace(-20, -4)
  317. q = stats.bradford.cdf(x, c)
  318. xx = stats.bradford.ppf(q, c)
  319. assert_allclose(x, xx)
  320. class TestChi:
  321. # "Exact" value of chi.sf(10, 4), as computed by Wolfram Alpha with
  322. # 1 - CDF[ChiDistribution[4], 10]
  323. CHI_SF_10_4 = 9.83662422461598e-21
  324. # "Exact" value of chi.mean(df=1000) as computed by Wolfram Alpha with
  325. # Mean[ChiDistribution[1000]]
  326. CHI_MEAN_1000 = 31.614871896980
  327. def test_sf(self):
  328. s = stats.chi.sf(10, 4)
  329. assert_allclose(s, self.CHI_SF_10_4, rtol=1e-15)
  330. def test_isf(self):
  331. x = stats.chi.isf(self.CHI_SF_10_4, 4)
  332. assert_allclose(x, 10, rtol=1e-15)
  333. def test_mean(self):
  334. x = stats.chi.mean(df=1000)
  335. assert_allclose(x, self.CHI_MEAN_1000, rtol=1e-12)
  336. class TestNBinom:
  337. def setup_method(self):
  338. np.random.seed(1234)
  339. def test_rvs(self):
  340. vals = stats.nbinom.rvs(10, 0.75, size=(2, 50))
  341. assert_(numpy.all(vals >= 0))
  342. assert_(numpy.shape(vals) == (2, 50))
  343. assert_(vals.dtype.char in typecodes['AllInteger'])
  344. val = stats.nbinom.rvs(10, 0.75)
  345. assert_(isinstance(val, int))
  346. val = stats.nbinom(10, 0.75).rvs(3)
  347. assert_(isinstance(val, numpy.ndarray))
  348. assert_(val.dtype.char in typecodes['AllInteger'])
  349. def test_pmf(self):
  350. # regression test for ticket 1779
  351. assert_allclose(np.exp(stats.nbinom.logpmf(700, 721, 0.52)),
  352. stats.nbinom.pmf(700, 721, 0.52))
  353. # logpmf(0,1,1) shouldn't return nan (regression test for gh-4029)
  354. val = scipy.stats.nbinom.logpmf(0, 1, 1)
  355. assert_equal(val, 0)
  356. def test_logcdf_gh16159(self):
  357. # check that gh16159 is resolved.
  358. vals = stats.nbinom.logcdf([0, 5, 0, 5], n=4.8, p=0.45)
  359. ref = np.log(stats.nbinom.cdf([0, 5, 0, 5], n=4.8, p=0.45))
  360. assert_allclose(vals, ref)
  361. class TestGenInvGauss:
  362. def setup_method(self):
  363. np.random.seed(1234)
  364. @pytest.mark.slow
  365. def test_rvs_with_mode_shift(self):
  366. # ratio_unif w/ mode shift
  367. gig = stats.geninvgauss(2.3, 1.5)
  368. _, p = stats.kstest(gig.rvs(size=1500, random_state=1234), gig.cdf)
  369. assert_equal(p > 0.05, True)
  370. @pytest.mark.slow
  371. def test_rvs_without_mode_shift(self):
  372. # ratio_unif w/o mode shift
  373. gig = stats.geninvgauss(0.9, 0.75)
  374. _, p = stats.kstest(gig.rvs(size=1500, random_state=1234), gig.cdf)
  375. assert_equal(p > 0.05, True)
  376. @pytest.mark.slow
  377. def test_rvs_new_method(self):
  378. # new algorithm of Hoermann / Leydold
  379. gig = stats.geninvgauss(0.1, 0.2)
  380. _, p = stats.kstest(gig.rvs(size=1500, random_state=1234), gig.cdf)
  381. assert_equal(p > 0.05, True)
  382. @pytest.mark.slow
  383. def test_rvs_p_zero(self):
  384. def my_ks_check(p, b):
  385. gig = stats.geninvgauss(p, b)
  386. rvs = gig.rvs(size=1500, random_state=1234)
  387. return stats.kstest(rvs, gig.cdf)[1] > 0.05
  388. # boundary cases when p = 0
  389. assert_equal(my_ks_check(0, 0.2), True) # new algo
  390. assert_equal(my_ks_check(0, 0.9), True) # ratio_unif w/o shift
  391. assert_equal(my_ks_check(0, 1.5), True) # ratio_unif with shift
  392. def test_rvs_negative_p(self):
  393. # if p negative, return inverse
  394. assert_equal(
  395. stats.geninvgauss(-1.5, 2).rvs(size=10, random_state=1234),
  396. 1 / stats.geninvgauss(1.5, 2).rvs(size=10, random_state=1234))
  397. def test_invgauss(self):
  398. # test that invgauss is special case
  399. ig = stats.geninvgauss.rvs(size=1500, p=-0.5, b=1, random_state=1234)
  400. assert_equal(stats.kstest(ig, 'invgauss', args=[1])[1] > 0.15, True)
  401. # test pdf and cdf
  402. mu, x = 100, np.linspace(0.01, 1, 10)
  403. pdf_ig = stats.geninvgauss.pdf(x, p=-0.5, b=1 / mu, scale=mu)
  404. assert_allclose(pdf_ig, stats.invgauss(mu).pdf(x))
  405. cdf_ig = stats.geninvgauss.cdf(x, p=-0.5, b=1 / mu, scale=mu)
  406. assert_allclose(cdf_ig, stats.invgauss(mu).cdf(x))
  407. def test_pdf_R(self):
  408. # test against R package GIGrvg
  409. # x <- seq(0.01, 5, length.out = 10)
  410. # GIGrvg::dgig(x, 0.5, 1, 1)
  411. vals_R = np.array([2.081176820e-21, 4.488660034e-01, 3.747774338e-01,
  412. 2.693297528e-01, 1.905637275e-01, 1.351476913e-01,
  413. 9.636538981e-02, 6.909040154e-02, 4.978006801e-02,
  414. 3.602084467e-02])
  415. x = np.linspace(0.01, 5, 10)
  416. assert_allclose(vals_R, stats.geninvgauss.pdf(x, 0.5, 1))
  417. def test_pdf_zero(self):
  418. # pdf at 0 is 0, needs special treatment to avoid 1/x in pdf
  419. assert_equal(stats.geninvgauss.pdf(0, 0.5, 0.5), 0)
  420. # if x is large and p is moderate, make sure that pdf does not
  421. # overflow because of x**(p-1); exp(-b*x) forces pdf to zero
  422. assert_equal(stats.geninvgauss.pdf(2e6, 50, 2), 0)
  423. class TestGenHyperbolic:
  424. def setup_method(self):
  425. np.random.seed(1234)
  426. def test_pdf_r(self):
  427. # test against R package GeneralizedHyperbolic
  428. # x <- seq(-10, 10, length.out = 10)
  429. # GeneralizedHyperbolic::dghyp(
  430. # x = x, lambda = 2, alpha = 2, beta = 1, delta = 1.5, mu = 0.5
  431. # )
  432. vals_R = np.array([
  433. 2.94895678275316e-13, 1.75746848647696e-10, 9.48149804073045e-08,
  434. 4.17862521692026e-05, 0.0103947630463822, 0.240864958986839,
  435. 0.162833527161649, 0.0374609592899472, 0.00634894847327781,
  436. 0.000941920705790324
  437. ])
  438. lmbda, alpha, beta = 2, 2, 1
  439. mu, delta = 0.5, 1.5
  440. args = (lmbda, alpha*delta, beta*delta)
  441. gh = stats.genhyperbolic(*args, loc=mu, scale=delta)
  442. x = np.linspace(-10, 10, 10)
  443. assert_allclose(gh.pdf(x), vals_R, atol=0, rtol=1e-13)
  444. def test_cdf_r(self):
  445. # test against R package GeneralizedHyperbolic
  446. # q <- seq(-10, 10, length.out = 10)
  447. # GeneralizedHyperbolic::pghyp(
  448. # q = q, lambda = 2, alpha = 2, beta = 1, delta = 1.5, mu = 0.5
  449. # )
  450. vals_R = np.array([
  451. 1.01881590921421e-13, 6.13697274983578e-11, 3.37504977637992e-08,
  452. 1.55258698166181e-05, 0.00447005453832497, 0.228935323956347,
  453. 0.755759458895243, 0.953061062884484, 0.992598013917513,
  454. 0.998942646586662
  455. ])
  456. lmbda, alpha, beta = 2, 2, 1
  457. mu, delta = 0.5, 1.5
  458. args = (lmbda, alpha*delta, beta*delta)
  459. gh = stats.genhyperbolic(*args, loc=mu, scale=delta)
  460. x = np.linspace(-10, 10, 10)
  461. assert_allclose(gh.cdf(x), vals_R, atol=0, rtol=1e-6)
  462. def test_moments_r(self):
  463. # test against R package GeneralizedHyperbolic
  464. # sapply(1:4,
  465. # function(x) GeneralizedHyperbolic::ghypMom(
  466. # order = x, lambda = 2, alpha = 2,
  467. # beta = 1, delta = 1.5, mu = 0.5,
  468. # momType = 'raw')
  469. # )
  470. vals_R = [2.36848366948115, 8.4739346779246,
  471. 37.8870502710066, 205.76608511485]
  472. lmbda, alpha, beta = 2, 2, 1
  473. mu, delta = 0.5, 1.5
  474. args = (lmbda, alpha*delta, beta*delta)
  475. vals_us = [
  476. stats.genhyperbolic(*args, loc=mu, scale=delta).moment(i)
  477. for i in range(1, 5)
  478. ]
  479. assert_allclose(vals_us, vals_R, atol=0, rtol=1e-13)
  480. def test_rvs(self):
  481. # Kolmogorov-Smirnov test to ensure alignemnt
  482. # of analytical and empirical cdfs
  483. lmbda, alpha, beta = 2, 2, 1
  484. mu, delta = 0.5, 1.5
  485. args = (lmbda, alpha*delta, beta*delta)
  486. gh = stats.genhyperbolic(*args, loc=mu, scale=delta)
  487. _, p = stats.kstest(gh.rvs(size=1500, random_state=1234), gh.cdf)
  488. assert_equal(p > 0.05, True)
  489. def test_pdf_t(self):
  490. # Test Against T-Student with 1 - 30 df
  491. df = np.linspace(1, 30, 10)
  492. # in principle alpha should be zero in practice for big lmbdas
  493. # alpha cannot be too small else pdf does not integrate
  494. alpha, beta = np.float_power(df, 2)*np.finfo(np.float32).eps, 0
  495. mu, delta = 0, np.sqrt(df)
  496. args = (-df/2, alpha, beta)
  497. gh = stats.genhyperbolic(*args, loc=mu, scale=delta)
  498. x = np.linspace(gh.ppf(0.01), gh.ppf(0.99), 50)[:, np.newaxis]
  499. assert_allclose(
  500. gh.pdf(x), stats.t.pdf(x, df),
  501. atol=0, rtol=1e-6
  502. )
  503. def test_pdf_cauchy(self):
  504. # Test Against Cauchy distribution
  505. # in principle alpha should be zero in practice for big lmbdas
  506. # alpha cannot be too small else pdf does not integrate
  507. lmbda, alpha, beta = -0.5, np.finfo(np.float32).eps, 0
  508. mu, delta = 0, 1
  509. args = (lmbda, alpha, beta)
  510. gh = stats.genhyperbolic(*args, loc=mu, scale=delta)
  511. x = np.linspace(gh.ppf(0.01), gh.ppf(0.99), 50)[:, np.newaxis]
  512. assert_allclose(
  513. gh.pdf(x), stats.cauchy.pdf(x),
  514. atol=0, rtol=1e-6
  515. )
  516. def test_pdf_laplace(self):
  517. # Test Against Laplace with location param [-10, 10]
  518. loc = np.linspace(-10, 10, 10)
  519. # in principle delta should be zero in practice for big loc delta
  520. # cannot be too small else pdf does not integrate
  521. delta = np.finfo(np.float32).eps
  522. lmbda, alpha, beta = 1, 1, 0
  523. args = (lmbda, alpha*delta, beta*delta)
  524. # ppf does not integrate for scale < 5e-4
  525. # therefore using simple linspace to define the support
  526. gh = stats.genhyperbolic(*args, loc=loc, scale=delta)
  527. x = np.linspace(-20, 20, 50)[:, np.newaxis]
  528. assert_allclose(
  529. gh.pdf(x), stats.laplace.pdf(x, loc=loc, scale=1),
  530. atol=0, rtol=1e-11
  531. )
  532. def test_pdf_norminvgauss(self):
  533. # Test Against NIG with varying alpha/beta/delta/mu
  534. alpha, beta, delta, mu = (
  535. np.linspace(1, 20, 10),
  536. np.linspace(0, 19, 10)*np.float_power(-1, range(10)),
  537. np.linspace(1, 1, 10),
  538. np.linspace(-100, 100, 10)
  539. )
  540. lmbda = - 0.5
  541. args = (lmbda, alpha * delta, beta * delta)
  542. gh = stats.genhyperbolic(*args, loc=mu, scale=delta)
  543. x = np.linspace(gh.ppf(0.01), gh.ppf(0.99), 50)[:, np.newaxis]
  544. assert_allclose(
  545. gh.pdf(x), stats.norminvgauss.pdf(
  546. x, a=alpha, b=beta, loc=mu, scale=delta),
  547. atol=0, rtol=1e-13
  548. )
  549. class TestNormInvGauss:
  550. def setup_method(self):
  551. np.random.seed(1234)
  552. def test_cdf_R(self):
  553. # test pdf and cdf vals against R
  554. # require("GeneralizedHyperbolic")
  555. # x_test <- c(-7, -5, 0, 8, 15)
  556. # r_cdf <- GeneralizedHyperbolic::pnig(x_test, mu = 0, a = 1, b = 0.5)
  557. # r_pdf <- GeneralizedHyperbolic::dnig(x_test, mu = 0, a = 1, b = 0.5)
  558. r_cdf = np.array([8.034920282e-07, 2.512671945e-05, 3.186661051e-01,
  559. 9.988650664e-01, 9.999848769e-01])
  560. x_test = np.array([-7, -5, 0, 8, 15])
  561. vals_cdf = stats.norminvgauss.cdf(x_test, a=1, b=0.5)
  562. assert_allclose(vals_cdf, r_cdf, atol=1e-9)
  563. def test_pdf_R(self):
  564. # values from R as defined in test_cdf_R
  565. r_pdf = np.array([1.359600783e-06, 4.413878805e-05, 4.555014266e-01,
  566. 7.450485342e-04, 8.917889931e-06])
  567. x_test = np.array([-7, -5, 0, 8, 15])
  568. vals_pdf = stats.norminvgauss.pdf(x_test, a=1, b=0.5)
  569. assert_allclose(vals_pdf, r_pdf, atol=1e-9)
  570. @pytest.mark.parametrize('x, a, b, sf, rtol',
  571. [(-1, 1, 0, 0.8759652211005315, 1e-13),
  572. (25, 1, 0, 1.1318690184042579e-13, 1e-4),
  573. (1, 5, -1.5, 0.002066711134653577, 1e-12),
  574. (10, 5, -1.5, 2.308435233930669e-29, 1e-9)])
  575. def test_sf_isf_mpmath(self, x, a, b, sf, rtol):
  576. # The data in this test is based on this code that uses mpmath:
  577. #
  578. # -----
  579. # import mpmath
  580. #
  581. # mpmath.mp.dps = 50
  582. #
  583. # def pdf(x, a, b):
  584. # x = mpmath.mpf(x)
  585. # a = mpmath.mpf(a)
  586. # b = mpmath.mpf(b)
  587. # g = mpmath.sqrt(a**2 - b**2)
  588. # t = mpmath.sqrt(1 + x**2)
  589. # return (a * mpmath.besselk(1, a*t) * mpmath.exp(g + b*x)
  590. # / (mpmath.pi * t))
  591. #
  592. # def sf(x, a, b):
  593. # return mpmath.quad(lambda x: pdf(x, a, b), [x, mpmath.inf])
  594. #
  595. # -----
  596. #
  597. # In particular,
  598. #
  599. # >>> float(sf(-1, 1, 0))
  600. # 0.8759652211005315
  601. # >>> float(sf(25, 1, 0))
  602. # 1.1318690184042579e-13
  603. # >>> float(sf(1, 5, -1.5))
  604. # 0.002066711134653577
  605. # >>> float(sf(10, 5, -1.5))
  606. # 2.308435233930669e-29
  607. s = stats.norminvgauss.sf(x, a, b)
  608. assert_allclose(s, sf, rtol=rtol)
  609. i = stats.norminvgauss.isf(sf, a, b)
  610. assert_allclose(i, x, rtol=rtol)
  611. def test_sf_isf_mpmath_vectorized(self):
  612. x = [-1, 25]
  613. a = [1, 1]
  614. b = 0
  615. sf = [0.8759652211005315, 1.1318690184042579e-13] # see previous test
  616. s = stats.norminvgauss.sf(x, a, b)
  617. assert_allclose(s, sf, rtol=1e-13, atol=1e-16)
  618. i = stats.norminvgauss.isf(sf, a, b)
  619. # Not perfect, but better than it was. See gh-13338.
  620. assert_allclose(i, x, rtol=1e-6)
  621. def test_gh8718(self):
  622. # Add test that gh-13338 resolved gh-8718
  623. dst = stats.norminvgauss(1, 0)
  624. x = np.arange(0, 20, 2)
  625. sf = dst.sf(x)
  626. isf = dst.isf(sf)
  627. assert_allclose(isf, x)
  628. def test_stats(self):
  629. a, b = 1, 0.5
  630. gamma = np.sqrt(a**2 - b**2)
  631. v_stats = (b / gamma, a**2 / gamma**3, 3.0 * b / (a * np.sqrt(gamma)),
  632. 3.0 * (1 + 4 * b**2 / a**2) / gamma)
  633. assert_equal(v_stats, stats.norminvgauss.stats(a, b, moments='mvsk'))
  634. def test_ppf(self):
  635. a, b = 1, 0.5
  636. x_test = np.array([0.001, 0.5, 0.999])
  637. vals = stats.norminvgauss.ppf(x_test, a, b)
  638. assert_allclose(x_test, stats.norminvgauss.cdf(vals, a, b))
  639. class TestGeom:
  640. def setup_method(self):
  641. np.random.seed(1234)
  642. def test_rvs(self):
  643. vals = stats.geom.rvs(0.75, size=(2, 50))
  644. assert_(numpy.all(vals >= 0))
  645. assert_(numpy.shape(vals) == (2, 50))
  646. assert_(vals.dtype.char in typecodes['AllInteger'])
  647. val = stats.geom.rvs(0.75)
  648. assert_(isinstance(val, int))
  649. val = stats.geom(0.75).rvs(3)
  650. assert_(isinstance(val, numpy.ndarray))
  651. assert_(val.dtype.char in typecodes['AllInteger'])
  652. def test_rvs_9313(self):
  653. # previously, RVS were converted to `np.int32` on some platforms,
  654. # causing overflow for moderately large integer output (gh-9313).
  655. # Check that this is resolved to the extent possible w/ `np.int64`.
  656. rng = np.random.default_rng(649496242618848)
  657. rvs = stats.geom.rvs(np.exp(-35), size=5, random_state=rng)
  658. assert rvs.dtype == np.int64
  659. assert np.all(rvs > np.iinfo(np.int32).max)
  660. def test_pmf(self):
  661. vals = stats.geom.pmf([1, 2, 3], 0.5)
  662. assert_array_almost_equal(vals, [0.5, 0.25, 0.125])
  663. def test_logpmf(self):
  664. # regression test for ticket 1793
  665. vals1 = np.log(stats.geom.pmf([1, 2, 3], 0.5))
  666. vals2 = stats.geom.logpmf([1, 2, 3], 0.5)
  667. assert_allclose(vals1, vals2, rtol=1e-15, atol=0)
  668. # regression test for gh-4028
  669. val = stats.geom.logpmf(1, 1)
  670. assert_equal(val, 0.0)
  671. def test_cdf_sf(self):
  672. vals = stats.geom.cdf([1, 2, 3], 0.5)
  673. vals_sf = stats.geom.sf([1, 2, 3], 0.5)
  674. expected = array([0.5, 0.75, 0.875])
  675. assert_array_almost_equal(vals, expected)
  676. assert_array_almost_equal(vals_sf, 1-expected)
  677. def test_logcdf_logsf(self):
  678. vals = stats.geom.logcdf([1, 2, 3], 0.5)
  679. vals_sf = stats.geom.logsf([1, 2, 3], 0.5)
  680. expected = array([0.5, 0.75, 0.875])
  681. assert_array_almost_equal(vals, np.log(expected))
  682. assert_array_almost_equal(vals_sf, np.log1p(-expected))
  683. def test_ppf(self):
  684. vals = stats.geom.ppf([0.5, 0.75, 0.875], 0.5)
  685. expected = array([1.0, 2.0, 3.0])
  686. assert_array_almost_equal(vals, expected)
  687. def test_ppf_underflow(self):
  688. # this should not underflow
  689. assert_allclose(stats.geom.ppf(1e-20, 1e-20), 1.0, atol=1e-14)
  690. class TestPlanck:
  691. def setup_method(self):
  692. np.random.seed(1234)
  693. def test_sf(self):
  694. vals = stats.planck.sf([1, 2, 3], 5.)
  695. expected = array([4.5399929762484854e-05,
  696. 3.0590232050182579e-07,
  697. 2.0611536224385579e-09])
  698. assert_array_almost_equal(vals, expected)
  699. def test_logsf(self):
  700. vals = stats.planck.logsf([1000., 2000., 3000.], 1000.)
  701. expected = array([-1001000., -2001000., -3001000.])
  702. assert_array_almost_equal(vals, expected)
  703. class TestGennorm:
  704. def test_laplace(self):
  705. # test against Laplace (special case for beta=1)
  706. points = [1, 2, 3]
  707. pdf1 = stats.gennorm.pdf(points, 1)
  708. pdf2 = stats.laplace.pdf(points)
  709. assert_almost_equal(pdf1, pdf2)
  710. def test_norm(self):
  711. # test against normal (special case for beta=2)
  712. points = [1, 2, 3]
  713. pdf1 = stats.gennorm.pdf(points, 2)
  714. pdf2 = stats.norm.pdf(points, scale=2**-.5)
  715. assert_almost_equal(pdf1, pdf2)
  716. def test_rvs(self):
  717. np.random.seed(0)
  718. # 0 < beta < 1
  719. dist = stats.gennorm(0.5)
  720. rvs = dist.rvs(size=1000)
  721. assert stats.kstest(rvs, dist.cdf).pvalue > 0.1
  722. # beta = 1
  723. dist = stats.gennorm(1)
  724. rvs = dist.rvs(size=1000)
  725. rvs_laplace = stats.laplace.rvs(size=1000)
  726. assert stats.ks_2samp(rvs, rvs_laplace).pvalue > 0.1
  727. # beta = 2
  728. dist = stats.gennorm(2)
  729. rvs = dist.rvs(size=1000)
  730. rvs_norm = stats.norm.rvs(scale=1/2**0.5, size=1000)
  731. assert stats.ks_2samp(rvs, rvs_norm).pvalue > 0.1
  732. def test_rvs_broadcasting(self):
  733. np.random.seed(0)
  734. dist = stats.gennorm([[0.5, 1.], [2., 5.]])
  735. rvs = dist.rvs(size=[1000, 2, 2])
  736. assert stats.kstest(rvs[:, 0, 0], stats.gennorm(0.5).cdf)[1] > 0.1
  737. assert stats.kstest(rvs[:, 0, 1], stats.gennorm(1.0).cdf)[1] > 0.1
  738. assert stats.kstest(rvs[:, 1, 0], stats.gennorm(2.0).cdf)[1] > 0.1
  739. assert stats.kstest(rvs[:, 1, 1], stats.gennorm(5.0).cdf)[1] > 0.1
  740. class TestHalfgennorm:
  741. def test_expon(self):
  742. # test against exponential (special case for beta=1)
  743. points = [1, 2, 3]
  744. pdf1 = stats.halfgennorm.pdf(points, 1)
  745. pdf2 = stats.expon.pdf(points)
  746. assert_almost_equal(pdf1, pdf2)
  747. def test_halfnorm(self):
  748. # test against half normal (special case for beta=2)
  749. points = [1, 2, 3]
  750. pdf1 = stats.halfgennorm.pdf(points, 2)
  751. pdf2 = stats.halfnorm.pdf(points, scale=2**-.5)
  752. assert_almost_equal(pdf1, pdf2)
  753. def test_gennorm(self):
  754. # test against generalized normal
  755. points = [1, 2, 3]
  756. pdf1 = stats.halfgennorm.pdf(points, .497324)
  757. pdf2 = stats.gennorm.pdf(points, .497324)
  758. assert_almost_equal(pdf1, 2*pdf2)
  759. class TestLaplaceasymmetric:
  760. def test_laplace(self):
  761. # test against Laplace (special case for kappa=1)
  762. points = np.array([1, 2, 3])
  763. pdf1 = stats.laplace_asymmetric.pdf(points, 1)
  764. pdf2 = stats.laplace.pdf(points)
  765. assert_allclose(pdf1, pdf2)
  766. def test_asymmetric_laplace_pdf(self):
  767. # test assymetric Laplace
  768. points = np.array([1, 2, 3])
  769. kappa = 2
  770. kapinv = 1/kappa
  771. pdf1 = stats.laplace_asymmetric.pdf(points, kappa)
  772. pdf2 = stats.laplace_asymmetric.pdf(points*(kappa**2), kapinv)
  773. assert_allclose(pdf1, pdf2)
  774. def test_asymmetric_laplace_log_10_16(self):
  775. # test assymetric Laplace
  776. points = np.array([-np.log(16), np.log(10)])
  777. kappa = 2
  778. pdf1 = stats.laplace_asymmetric.pdf(points, kappa)
  779. cdf1 = stats.laplace_asymmetric.cdf(points, kappa)
  780. sf1 = stats.laplace_asymmetric.sf(points, kappa)
  781. pdf2 = np.array([1/10, 1/250])
  782. cdf2 = np.array([1/5, 1 - 1/500])
  783. sf2 = np.array([4/5, 1/500])
  784. ppf1 = stats.laplace_asymmetric.ppf(cdf2, kappa)
  785. ppf2 = points
  786. isf1 = stats.laplace_asymmetric.isf(sf2, kappa)
  787. isf2 = points
  788. assert_allclose(np.concatenate((pdf1, cdf1, sf1, ppf1, isf1)),
  789. np.concatenate((pdf2, cdf2, sf2, ppf2, isf2)))
  790. class TestTruncnorm:
  791. def setup_method(self):
  792. np.random.seed(1234)
  793. def test_ppf_ticket1131(self):
  794. vals = stats.truncnorm.ppf([-0.5, 0, 1e-4, 0.5, 1-1e-4, 1, 2], -1., 1.,
  795. loc=[3]*7, scale=2)
  796. expected = np.array([np.nan, 1, 1.00056419, 3, 4.99943581, 5, np.nan])
  797. assert_array_almost_equal(vals, expected)
  798. def test_isf_ticket1131(self):
  799. vals = stats.truncnorm.isf([-0.5, 0, 1e-4, 0.5, 1-1e-4, 1, 2], -1., 1.,
  800. loc=[3]*7, scale=2)
  801. expected = np.array([np.nan, 5, 4.99943581, 3, 1.00056419, 1, np.nan])
  802. assert_array_almost_equal(vals, expected)
  803. def test_gh_2477_small_values(self):
  804. # Check a case that worked in the original issue.
  805. low, high = -11, -10
  806. x = stats.truncnorm.rvs(low, high, 0, 1, size=10)
  807. assert_(low < x.min() < x.max() < high)
  808. # Check a case that failed in the original issue.
  809. low, high = 10, 11
  810. x = stats.truncnorm.rvs(low, high, 0, 1, size=10)
  811. assert_(low < x.min() < x.max() < high)
  812. def test_gh_2477_large_values(self):
  813. # Check a case that used to fail because of extreme tailness.
  814. low, high = 100, 101
  815. x = stats.truncnorm.rvs(low, high, 0, 1, size=10)
  816. assert_(low <= x.min() <= x.max() <= high), str([low, high, x])
  817. # Check some additional extreme tails
  818. low, high = 1000, 1001
  819. x = stats.truncnorm.rvs(low, high, 0, 1, size=10)
  820. assert_(low < x.min() < x.max() < high)
  821. low, high = 10000, 10001
  822. x = stats.truncnorm.rvs(low, high, 0, 1, size=10)
  823. assert_(low < x.min() < x.max() < high)
  824. low, high = -10001, -10000
  825. x = stats.truncnorm.rvs(low, high, 0, 1, size=10)
  826. assert_(low < x.min() < x.max() < high)
  827. def test_gh_9403_nontail_values(self):
  828. for low, high in [[3, 4], [-4, -3]]:
  829. xvals = np.array([-np.inf, low, high, np.inf])
  830. xmid = (high+low)/2.0
  831. cdfs = stats.truncnorm.cdf(xvals, low, high)
  832. sfs = stats.truncnorm.sf(xvals, low, high)
  833. pdfs = stats.truncnorm.pdf(xvals, low, high)
  834. expected_cdfs = np.array([0, 0, 1, 1])
  835. expected_sfs = np.array([1.0, 1.0, 0.0, 0.0])
  836. expected_pdfs = np.array([0, 3.3619772, 0.1015229, 0])
  837. if low < 0:
  838. expected_pdfs = np.array([0, 0.1015229, 3.3619772, 0])
  839. assert_almost_equal(cdfs, expected_cdfs)
  840. assert_almost_equal(sfs, expected_sfs)
  841. assert_almost_equal(pdfs, expected_pdfs)
  842. assert_almost_equal(np.log(expected_pdfs[1]/expected_pdfs[2]),
  843. low + 0.5)
  844. pvals = np.array([0, 0.5, 1.0])
  845. ppfs = stats.truncnorm.ppf(pvals, low, high)
  846. expected_ppfs = np.array([low, np.sign(low)*3.1984741, high])
  847. assert_almost_equal(ppfs, expected_ppfs)
  848. if low < 0:
  849. assert_almost_equal(stats.truncnorm.sf(xmid, low, high),
  850. 0.8475544278436675)
  851. assert_almost_equal(stats.truncnorm.cdf(xmid, low, high),
  852. 0.1524455721563326)
  853. else:
  854. assert_almost_equal(stats.truncnorm.cdf(xmid, low, high),
  855. 0.8475544278436675)
  856. assert_almost_equal(stats.truncnorm.sf(xmid, low, high),
  857. 0.1524455721563326)
  858. pdf = stats.truncnorm.pdf(xmid, low, high)
  859. assert_almost_equal(np.log(pdf/expected_pdfs[2]), (xmid+0.25)/2)
  860. def test_gh_9403_medium_tail_values(self):
  861. for low, high in [[39, 40], [-40, -39]]:
  862. xvals = np.array([-np.inf, low, high, np.inf])
  863. xmid = (high+low)/2.0
  864. cdfs = stats.truncnorm.cdf(xvals, low, high)
  865. sfs = stats.truncnorm.sf(xvals, low, high)
  866. pdfs = stats.truncnorm.pdf(xvals, low, high)
  867. expected_cdfs = np.array([0, 0, 1, 1])
  868. expected_sfs = np.array([1.0, 1.0, 0.0, 0.0])
  869. expected_pdfs = np.array([0, 3.90256074e+01, 2.73349092e-16, 0])
  870. if low < 0:
  871. expected_pdfs = np.array([0, 2.73349092e-16,
  872. 3.90256074e+01, 0])
  873. assert_almost_equal(cdfs, expected_cdfs)
  874. assert_almost_equal(sfs, expected_sfs)
  875. assert_almost_equal(pdfs, expected_pdfs)
  876. assert_almost_equal(np.log(expected_pdfs[1]/expected_pdfs[2]),
  877. low + 0.5)
  878. pvals = np.array([0, 0.5, 1.0])
  879. ppfs = stats.truncnorm.ppf(pvals, low, high)
  880. expected_ppfs = np.array([low, np.sign(low)*39.01775731, high])
  881. assert_almost_equal(ppfs, expected_ppfs)
  882. cdfs = stats.truncnorm.cdf(ppfs, low, high)
  883. assert_almost_equal(cdfs, pvals)
  884. if low < 0:
  885. assert_almost_equal(stats.truncnorm.sf(xmid, low, high),
  886. 0.9999999970389126)
  887. assert_almost_equal(stats.truncnorm.cdf(xmid, low, high),
  888. 2.961048103554866e-09)
  889. else:
  890. assert_almost_equal(stats.truncnorm.cdf(xmid, low, high),
  891. 0.9999999970389126)
  892. assert_almost_equal(stats.truncnorm.sf(xmid, low, high),
  893. 2.961048103554866e-09)
  894. pdf = stats.truncnorm.pdf(xmid, low, high)
  895. assert_almost_equal(np.log(pdf/expected_pdfs[2]), (xmid+0.25)/2)
  896. xvals = np.linspace(low, high, 11)
  897. xvals2 = -xvals[::-1]
  898. assert_almost_equal(stats.truncnorm.cdf(xvals, low, high),
  899. stats.truncnorm.sf(xvals2, -high, -low)[::-1])
  900. assert_almost_equal(stats.truncnorm.sf(xvals, low, high),
  901. stats.truncnorm.cdf(xvals2, -high, -low)[::-1])
  902. assert_almost_equal(stats.truncnorm.pdf(xvals, low, high),
  903. stats.truncnorm.pdf(xvals2, -high, -low)[::-1])
  904. def test_cdf_tail_15110_14753(self):
  905. # Check accuracy issues reported in gh-14753 and gh-155110
  906. # Ground truth values calculated using Wolfram Alpha, e.g.
  907. # (CDF[NormalDistribution[0,1],83/10]-CDF[NormalDistribution[0,1],8])/
  908. # (1 - CDF[NormalDistribution[0,1],8])
  909. assert_allclose(stats.truncnorm(13., 15.).cdf(14.),
  910. 0.9999987259565643)
  911. assert_allclose(stats.truncnorm(8, np.inf).cdf(8.3),
  912. 0.9163220907327540)
  913. def _test_moments_one_range(self, a, b, expected, rtol=1e-7):
  914. m0, v0, s0, k0 = expected[:4]
  915. m, v, s, k = stats.truncnorm.stats(a, b, moments='mvsk')
  916. assert_allclose(m, m0)
  917. assert_allclose(v, v0)
  918. assert_allclose(s, s0, rtol=rtol)
  919. assert_allclose(k, k0, rtol=rtol)
  920. # Test data for the truncnorm stats() method.
  921. # The data in each row is:
  922. # a, b, mean, variance, skewness, excess kurtosis. Generated using
  923. # https://gist.github.com/WarrenWeckesser/636b537ee889679227d53543d333a720
  924. _truncnorm_stats_data = [
  925. [-30, 30,
  926. 0.0, 1.0, 0.0, 0.0],
  927. [-10, 10,
  928. 0.0, 1.0, 0.0, -1.4927521335810455e-19],
  929. [-3, 3,
  930. 0.0, 0.9733369246625415, 0.0, -0.17111443639774404],
  931. [-2, 2,
  932. 0.0, 0.7737413035499232, 0.0, -0.6344632828703505],
  933. [0, np.inf,
  934. 0.7978845608028654,
  935. 0.3633802276324187,
  936. 0.995271746431156,
  937. 0.8691773036059741],
  938. [-np.inf, 0,
  939. -0.7978845608028654,
  940. 0.3633802276324187,
  941. -0.995271746431156,
  942. 0.8691773036059741],
  943. [-1, 3,
  944. 0.282786110727154,
  945. 0.6161417353578293,
  946. 0.5393018494027877,
  947. -0.20582065135274694],
  948. [-3, 1,
  949. -0.282786110727154,
  950. 0.6161417353578293,
  951. -0.5393018494027877,
  952. -0.20582065135274694],
  953. [-10, -9,
  954. -9.108456288012409,
  955. 0.011448805821636248,
  956. -1.8985607290949496,
  957. 5.0733461105025075],
  958. ]
  959. _truncnorm_stats_data = np.array(_truncnorm_stats_data)
  960. @pytest.mark.parametrize("case", _truncnorm_stats_data)
  961. def test_moments(self, case):
  962. a, b, m0, v0, s0, k0 = case
  963. m, v, s, k = stats.truncnorm.stats(a, b, moments='mvsk')
  964. assert_allclose([m, v, s, k], [m0, v0, s0, k0], atol=1e-17)
  965. def test_9902_moments(self):
  966. m, v = stats.truncnorm.stats(0, np.inf, moments='mv')
  967. assert_almost_equal(m, 0.79788456)
  968. assert_almost_equal(v, 0.36338023)
  969. def test_gh_1489_trac_962_rvs(self):
  970. # Check the original example.
  971. low, high = 10, 15
  972. x = stats.truncnorm.rvs(low, high, 0, 1, size=10)
  973. assert_(low < x.min() < x.max() < high)
  974. def test_gh_11299_rvs(self):
  975. # Arose from investigating gh-11299
  976. # Test multiple shape parameters simultaneously.
  977. low = [-10, 10, -np.inf, -5, -np.inf, -np.inf, -45, -45, 40, -10, 40]
  978. high = [-5, 11, 5, np.inf, 40, -40, 40, -40, 45, np.inf, np.inf]
  979. x = stats.truncnorm.rvs(low, high, size=(5, len(low)))
  980. assert np.shape(x) == (5, len(low))
  981. assert_(np.all(low <= x.min(axis=0)))
  982. assert_(np.all(x.max(axis=0) <= high))
  983. def test_rvs_Generator(self):
  984. # check that rvs can use a Generator
  985. if hasattr(np.random, "default_rng"):
  986. stats.truncnorm.rvs(-10, -5, size=5,
  987. random_state=np.random.default_rng())
  988. def test_logcdf_gh17064(self):
  989. # regression test for gh-17064 - avoid roundoff error for logcdfs ~0
  990. a = np.array([-np.inf, -np.inf, -8, -np.inf, 10])
  991. b = np.array([np.inf, np.inf, 8, 10, np.inf])
  992. x = np.array([10, 7.5, 7.5, 9, 20])
  993. expected = [-7.619853024160525e-24, -3.190891672910947e-14,
  994. -3.128682067168231e-14, -1.1285122074235991e-19,
  995. -3.61374964828753e-66]
  996. assert_allclose(stats.truncnorm(a, b).logcdf(x), expected)
  997. assert_allclose(stats.truncnorm(-b, -a).logsf(-x), expected)
  998. class TestGenLogistic:
  999. # Expected values computed with mpmath with 50 digits of precision.
  1000. @pytest.mark.parametrize('x, expected', [(-1000, -1499.5945348918917),
  1001. (-125, -187.09453489189184),
  1002. (0, -1.3274028432916989),
  1003. (100, -99.59453489189184),
  1004. (1000, -999.5945348918918)])
  1005. def test_logpdf(self, x, expected):
  1006. c = 1.5
  1007. logp = stats.genlogistic.logpdf(x, c)
  1008. assert_allclose(logp, expected, rtol=1e-13)
  1009. class TestHypergeom:
  1010. def setup_method(self):
  1011. np.random.seed(1234)
  1012. def test_rvs(self):
  1013. vals = stats.hypergeom.rvs(20, 10, 3, size=(2, 50))
  1014. assert_(numpy.all(vals >= 0) &
  1015. numpy.all(vals <= 3))
  1016. assert_(numpy.shape(vals) == (2, 50))
  1017. assert_(vals.dtype.char in typecodes['AllInteger'])
  1018. val = stats.hypergeom.rvs(20, 3, 10)
  1019. assert_(isinstance(val, int))
  1020. val = stats.hypergeom(20, 3, 10).rvs(3)
  1021. assert_(isinstance(val, numpy.ndarray))
  1022. assert_(val.dtype.char in typecodes['AllInteger'])
  1023. def test_precision(self):
  1024. # comparison number from mpmath
  1025. M = 2500
  1026. n = 50
  1027. N = 500
  1028. tot = M
  1029. good = n
  1030. hgpmf = stats.hypergeom.pmf(2, tot, good, N)
  1031. assert_almost_equal(hgpmf, 0.0010114963068932233, 11)
  1032. def test_args(self):
  1033. # test correct output for corner cases of arguments
  1034. # see gh-2325
  1035. assert_almost_equal(stats.hypergeom.pmf(0, 2, 1, 0), 1.0, 11)
  1036. assert_almost_equal(stats.hypergeom.pmf(1, 2, 1, 0), 0.0, 11)
  1037. assert_almost_equal(stats.hypergeom.pmf(0, 2, 0, 2), 1.0, 11)
  1038. assert_almost_equal(stats.hypergeom.pmf(1, 2, 1, 0), 0.0, 11)
  1039. def test_cdf_above_one(self):
  1040. # for some values of parameters, hypergeom cdf was >1, see gh-2238
  1041. assert_(0 <= stats.hypergeom.cdf(30, 13397950, 4363, 12390) <= 1.0)
  1042. def test_precision2(self):
  1043. # Test hypergeom precision for large numbers. See #1218.
  1044. # Results compared with those from R.
  1045. oranges = 9.9e4
  1046. pears = 1.1e5
  1047. fruits_eaten = np.array([3, 3.8, 3.9, 4, 4.1, 4.2, 5]) * 1e4
  1048. quantile = 2e4
  1049. res = [stats.hypergeom.sf(quantile, oranges + pears, oranges, eaten)
  1050. for eaten in fruits_eaten]
  1051. expected = np.array([0, 1.904153e-114, 2.752693e-66, 4.931217e-32,
  1052. 8.265601e-11, 0.1237904, 1])
  1053. assert_allclose(res, expected, atol=0, rtol=5e-7)
  1054. # Test with array_like first argument
  1055. quantiles = [1.9e4, 2e4, 2.1e4, 2.15e4]
  1056. res2 = stats.hypergeom.sf(quantiles, oranges + pears, oranges, 4.2e4)
  1057. expected2 = [1, 0.1237904, 6.511452e-34, 3.277667e-69]
  1058. assert_allclose(res2, expected2, atol=0, rtol=5e-7)
  1059. def test_entropy(self):
  1060. # Simple tests of entropy.
  1061. hg = stats.hypergeom(4, 1, 1)
  1062. h = hg.entropy()
  1063. expected_p = np.array([0.75, 0.25])
  1064. expected_h = -np.sum(xlogy(expected_p, expected_p))
  1065. assert_allclose(h, expected_h)
  1066. hg = stats.hypergeom(1, 1, 1)
  1067. h = hg.entropy()
  1068. assert_equal(h, 0.0)
  1069. def test_logsf(self):
  1070. # Test logsf for very large numbers. See issue #4982
  1071. # Results compare with those from R (v3.2.0):
  1072. # phyper(k, n, M-n, N, lower.tail=FALSE, log.p=TRUE)
  1073. # -2239.771
  1074. k = 1e4
  1075. M = 1e7
  1076. n = 1e6
  1077. N = 5e4
  1078. result = stats.hypergeom.logsf(k, M, n, N)
  1079. expected = -2239.771 # From R
  1080. assert_almost_equal(result, expected, decimal=3)
  1081. k = 1
  1082. M = 1600
  1083. n = 600
  1084. N = 300
  1085. result = stats.hypergeom.logsf(k, M, n, N)
  1086. expected = -2.566567e-68 # From R
  1087. assert_almost_equal(result, expected, decimal=15)
  1088. def test_logcdf(self):
  1089. # Test logcdf for very large numbers. See issue #8692
  1090. # Results compare with those from R (v3.3.2):
  1091. # phyper(k, n, M-n, N, lower.tail=TRUE, log.p=TRUE)
  1092. # -5273.335
  1093. k = 1
  1094. M = 1e7
  1095. n = 1e6
  1096. N = 5e4
  1097. result = stats.hypergeom.logcdf(k, M, n, N)
  1098. expected = -5273.335 # From R
  1099. assert_almost_equal(result, expected, decimal=3)
  1100. # Same example as in issue #8692
  1101. k = 40
  1102. M = 1600
  1103. n = 50
  1104. N = 300
  1105. result = stats.hypergeom.logcdf(k, M, n, N)
  1106. expected = -7.565148879229e-23 # From R
  1107. assert_almost_equal(result, expected, decimal=15)
  1108. k = 125
  1109. M = 1600
  1110. n = 250
  1111. N = 500
  1112. result = stats.hypergeom.logcdf(k, M, n, N)
  1113. expected = -4.242688e-12 # From R
  1114. assert_almost_equal(result, expected, decimal=15)
  1115. # test broadcasting robustness based on reviewer
  1116. # concerns in PR 9603; using an array version of
  1117. # the example from issue #8692
  1118. k = np.array([40, 40, 40])
  1119. M = 1600
  1120. n = 50
  1121. N = 300
  1122. result = stats.hypergeom.logcdf(k, M, n, N)
  1123. expected = np.full(3, -7.565148879229e-23) # filled from R result
  1124. assert_almost_equal(result, expected, decimal=15)
  1125. class TestLoggamma:
  1126. # Expected sf values were computed with mpmath. For given x and c,
  1127. # x = mpmath.mpf(x)
  1128. # c = mpmath.mpf(c)
  1129. # sf = mpmath.gammainc(c, mpmath.exp(x), mpmath.inf,
  1130. # regularized=True)
  1131. @pytest.mark.parametrize('x, c, sf', [(4, 1.5, 1.6341528919488565e-23),
  1132. (6, 100, 8.23836829202024e-74)])
  1133. def test_sf_isf(self, x, c, sf):
  1134. s = stats.loggamma.sf(x, c)
  1135. assert_allclose(s, sf, rtol=1e-12)
  1136. y = stats.loggamma.isf(s, c)
  1137. assert_allclose(y, x, rtol=1e-12)
  1138. def test_logpdf(self):
  1139. # Test logpdf with x=-500, c=2. ln(gamma(2)) = 0, and
  1140. # exp(-500) ~= 7e-218, which is far smaller than the ULP
  1141. # of c*x=-1000, so logpdf(-500, 2) = c*x - exp(x) - ln(gamma(2))
  1142. # should give -1000.0.
  1143. lp = stats.loggamma.logpdf(-500, 2)
  1144. assert_allclose(lp, -1000.0, rtol=1e-14)
  1145. def test_stats(self):
  1146. # The following precomputed values are from the table in section 2.2
  1147. # of "A Statistical Study of Log-Gamma Distribution", by Ping Shing
  1148. # Chan (thesis, McMaster University, 1993).
  1149. table = np.array([
  1150. # c, mean, var, skew, exc. kurt.
  1151. 0.5, -1.9635, 4.9348, -1.5351, 4.0000,
  1152. 1.0, -0.5772, 1.6449, -1.1395, 2.4000,
  1153. 12.0, 2.4427, 0.0869, -0.2946, 0.1735,
  1154. ]).reshape(-1, 5)
  1155. for c, mean, var, skew, kurt in table:
  1156. computed = stats.loggamma.stats(c, moments='msvk')
  1157. assert_array_almost_equal(computed, [mean, var, skew, kurt],
  1158. decimal=4)
  1159. @pytest.mark.parametrize('c', [0.1, 0.001])
  1160. def test_rvs(self, c):
  1161. # Regression test for gh-11094.
  1162. x = stats.loggamma.rvs(c, size=100000)
  1163. # Before gh-11094 was fixed, the case with c=0.001 would
  1164. # generate many -inf values.
  1165. assert np.isfinite(x).all()
  1166. # Crude statistical test. About half the values should be
  1167. # less than the median and half greater than the median.
  1168. med = stats.loggamma.median(c)
  1169. btest = stats.binomtest(np.count_nonzero(x < med), len(x))
  1170. ci = btest.proportion_ci(confidence_level=0.999)
  1171. assert ci.low < 0.5 < ci.high
  1172. class TestLogistic:
  1173. # gh-6226
  1174. def test_cdf_ppf(self):
  1175. x = np.linspace(-20, 20)
  1176. y = stats.logistic.cdf(x)
  1177. xx = stats.logistic.ppf(y)
  1178. assert_allclose(x, xx)
  1179. def test_sf_isf(self):
  1180. x = np.linspace(-20, 20)
  1181. y = stats.logistic.sf(x)
  1182. xx = stats.logistic.isf(y)
  1183. assert_allclose(x, xx)
  1184. def test_extreme_values(self):
  1185. # p is chosen so that 1 - (1 - p) == p in double precision
  1186. p = 9.992007221626409e-16
  1187. desired = 34.53957599234088
  1188. assert_allclose(stats.logistic.ppf(1 - p), desired)
  1189. assert_allclose(stats.logistic.isf(p), desired)
  1190. def test_logpdf_basic(self):
  1191. logp = stats.logistic.logpdf([-15, 0, 10])
  1192. # Expected values computed with mpmath with 50 digits of precision.
  1193. expected = [-15.000000611804547,
  1194. -1.3862943611198906,
  1195. -10.000090797798434]
  1196. assert_allclose(logp, expected, rtol=1e-13)
  1197. def test_logpdf_extreme_values(self):
  1198. logp = stats.logistic.logpdf([800, -800])
  1199. # For such large arguments, logpdf(x) = -abs(x) when computed
  1200. # with 64 bit floating point.
  1201. assert_equal(logp, [-800, -800])
  1202. @pytest.mark.parametrize("loc_rvs,scale_rvs", [(0.4484955, 0.10216821),
  1203. (0.62918191, 0.74367064)])
  1204. def test_fit(self, loc_rvs, scale_rvs):
  1205. data = stats.logistic.rvs(size=100, loc=loc_rvs, scale=scale_rvs)
  1206. # test that result of fit method is the same as optimization
  1207. def func(input, data):
  1208. a, b = input
  1209. n = len(data)
  1210. x1 = np.sum(np.exp((data - a) / b) /
  1211. (1 + np.exp((data - a) / b))) - n / 2
  1212. x2 = np.sum(((data - a) / b) *
  1213. ((np.exp((data - a) / b) - 1) /
  1214. (np.exp((data - a) / b) + 1))) - n
  1215. return x1, x2
  1216. expected_solution = root(func, stats.logistic._fitstart(data), args=(
  1217. data,)).x
  1218. fit_method = stats.logistic.fit(data)
  1219. # other than computational variances, the fit method and the solution
  1220. # to this system of equations are equal
  1221. assert_allclose(fit_method, expected_solution, atol=1e-30)
  1222. def test_fit_comp_optimizer(self):
  1223. data = stats.logistic.rvs(size=100, loc=0.5, scale=2)
  1224. # obtain objective function to compare results of the fit methods
  1225. args = [data, (stats.logistic._fitstart(data),)]
  1226. func = stats.logistic._reduce_func(args, {})[1]
  1227. _assert_less_or_close_loglike(stats.logistic, data, func)
  1228. _assert_less_or_close_loglike(stats.logistic, data, func, floc=1)
  1229. _assert_less_or_close_loglike(stats.logistic, data, func, fscale=1)
  1230. @pytest.mark.parametrize('testlogcdf', [True, False])
  1231. def test_logcdfsf_tails(self, testlogcdf):
  1232. # Test either logcdf or logsf. By symmetry, we can use the same
  1233. # expected values for both by switching the sign of x for logsf.
  1234. x = np.array([-10000, -800, 17, 50, 500])
  1235. if testlogcdf:
  1236. y = stats.logistic.logcdf(x)
  1237. else:
  1238. y = stats.logistic.logsf(-x)
  1239. # The expected values were computed with mpmath.
  1240. expected = [-10000.0, -800.0, -4.139937633089748e-08,
  1241. -1.9287498479639178e-22, -7.124576406741286e-218]
  1242. assert_allclose(y, expected, rtol=2e-15)
  1243. class TestLogser:
  1244. def setup_method(self):
  1245. np.random.seed(1234)
  1246. def test_rvs(self):
  1247. vals = stats.logser.rvs(0.75, size=(2, 50))
  1248. assert_(numpy.all(vals >= 1))
  1249. assert_(numpy.shape(vals) == (2, 50))
  1250. assert_(vals.dtype.char in typecodes['AllInteger'])
  1251. val = stats.logser.rvs(0.75)
  1252. assert_(isinstance(val, int))
  1253. val = stats.logser(0.75).rvs(3)
  1254. assert_(isinstance(val, numpy.ndarray))
  1255. assert_(val.dtype.char in typecodes['AllInteger'])
  1256. def test_pmf_small_p(self):
  1257. m = stats.logser.pmf(4, 1e-20)
  1258. # The expected value was computed using mpmath:
  1259. # >>> import mpmath
  1260. # >>> mpmath.mp.dps = 64
  1261. # >>> k = 4
  1262. # >>> p = mpmath.mpf('1e-20')
  1263. # >>> float(-(p**k)/k/mpmath.log(1-p))
  1264. # 2.5e-61
  1265. # It is also clear from noticing that for very small p,
  1266. # log(1-p) is approximately -p, and the formula becomes
  1267. # p**(k-1) / k
  1268. assert_allclose(m, 2.5e-61)
  1269. def test_mean_small_p(self):
  1270. m = stats.logser.mean(1e-8)
  1271. # The expected mean was computed using mpmath:
  1272. # >>> import mpmath
  1273. # >>> mpmath.dps = 60
  1274. # >>> p = mpmath.mpf('1e-8')
  1275. # >>> float(-p / ((1 - p)*mpmath.log(1 - p)))
  1276. # 1.000000005
  1277. assert_allclose(m, 1.000000005)
  1278. class TestGumbel_r_l:
  1279. @pytest.fixture(scope='function')
  1280. def rng(self):
  1281. return np.random.default_rng(1234)
  1282. @pytest.mark.parametrize("dist", [stats.gumbel_r, stats.gumbel_l])
  1283. @pytest.mark.parametrize("loc_rvs", [-1, 0, 1])
  1284. @pytest.mark.parametrize("scale_rvs", [.1, 1, 5])
  1285. @pytest.mark.parametrize('fix_loc, fix_scale',
  1286. ([True, False], [False, True]))
  1287. def test_fit_comp_optimizer(self, dist, loc_rvs, scale_rvs,
  1288. fix_loc, fix_scale, rng):
  1289. data = dist.rvs(size=100, loc=loc_rvs, scale=scale_rvs,
  1290. random_state=rng)
  1291. # obtain objective function to compare results of the fit methods
  1292. args = [data, (dist._fitstart(data),)]
  1293. func = dist._reduce_func(args, {})[1]
  1294. kwds = dict()
  1295. # the fixed location and scales are arbitrarily modified to not be
  1296. # close to the true value.
  1297. if fix_loc:
  1298. kwds['floc'] = loc_rvs * 2
  1299. if fix_scale:
  1300. kwds['fscale'] = scale_rvs * 2
  1301. # test that the gumbel_* fit method is better than super method
  1302. _assert_less_or_close_loglike(dist, data, func, **kwds)
  1303. @pytest.mark.parametrize("dist, sgn", [(stats.gumbel_r, 1),
  1304. (stats.gumbel_l, -1)])
  1305. def test_fit(self, dist, sgn):
  1306. z = sgn*np.array([3, 3, 3, 3, 3, 3, 3, 3.00000001])
  1307. loc, scale = dist.fit(z)
  1308. # The expected values were computed with mpmath with 60 digits
  1309. # of precision.
  1310. assert_allclose(loc, sgn*3.0000000001667906)
  1311. assert_allclose(scale, 1.2495222465145514e-09, rtol=1e-6)
  1312. class TestPareto:
  1313. def test_stats(self):
  1314. # Check the stats() method with some simple values. Also check
  1315. # that the calculations do not trigger RuntimeWarnings.
  1316. with warnings.catch_warnings():
  1317. warnings.simplefilter("error", RuntimeWarning)
  1318. m, v, s, k = stats.pareto.stats(0.5, moments='mvsk')
  1319. assert_equal(m, np.inf)
  1320. assert_equal(v, np.inf)
  1321. assert_equal(s, np.nan)
  1322. assert_equal(k, np.nan)
  1323. m, v, s, k = stats.pareto.stats(1.0, moments='mvsk')
  1324. assert_equal(m, np.inf)
  1325. assert_equal(v, np.inf)
  1326. assert_equal(s, np.nan)
  1327. assert_equal(k, np.nan)
  1328. m, v, s, k = stats.pareto.stats(1.5, moments='mvsk')
  1329. assert_equal(m, 3.0)
  1330. assert_equal(v, np.inf)
  1331. assert_equal(s, np.nan)
  1332. assert_equal(k, np.nan)
  1333. m, v, s, k = stats.pareto.stats(2.0, moments='mvsk')
  1334. assert_equal(m, 2.0)
  1335. assert_equal(v, np.inf)
  1336. assert_equal(s, np.nan)
  1337. assert_equal(k, np.nan)
  1338. m, v, s, k = stats.pareto.stats(2.5, moments='mvsk')
  1339. assert_allclose(m, 2.5 / 1.5)
  1340. assert_allclose(v, 2.5 / (1.5*1.5*0.5))
  1341. assert_equal(s, np.nan)
  1342. assert_equal(k, np.nan)
  1343. m, v, s, k = stats.pareto.stats(3.0, moments='mvsk')
  1344. assert_allclose(m, 1.5)
  1345. assert_allclose(v, 0.75)
  1346. assert_equal(s, np.nan)
  1347. assert_equal(k, np.nan)
  1348. m, v, s, k = stats.pareto.stats(3.5, moments='mvsk')
  1349. assert_allclose(m, 3.5 / 2.5)
  1350. assert_allclose(v, 3.5 / (2.5*2.5*1.5))
  1351. assert_allclose(s, (2*4.5/0.5)*np.sqrt(1.5/3.5))
  1352. assert_equal(k, np.nan)
  1353. m, v, s, k = stats.pareto.stats(4.0, moments='mvsk')
  1354. assert_allclose(m, 4.0 / 3.0)
  1355. assert_allclose(v, 4.0 / 18.0)
  1356. assert_allclose(s, 2*(1+4.0)/(4.0-3) * np.sqrt((4.0-2)/4.0))
  1357. assert_equal(k, np.nan)
  1358. m, v, s, k = stats.pareto.stats(4.5, moments='mvsk')
  1359. assert_allclose(m, 4.5 / 3.5)
  1360. assert_allclose(v, 4.5 / (3.5*3.5*2.5))
  1361. assert_allclose(s, (2*5.5/1.5) * np.sqrt(2.5/4.5))
  1362. assert_allclose(k, 6*(4.5**3 + 4.5**2 - 6*4.5 - 2)/(4.5*1.5*0.5))
  1363. def test_sf(self):
  1364. x = 1e9
  1365. b = 2
  1366. scale = 1.5
  1367. p = stats.pareto.sf(x, b, loc=0, scale=scale)
  1368. expected = (scale/x)**b # 2.25e-18
  1369. assert_allclose(p, expected)
  1370. @pytest.fixture(scope='function')
  1371. def rng(self):
  1372. return np.random.default_rng(1234)
  1373. @pytest.mark.filterwarnings("ignore:invalid value encountered in "
  1374. "double_scalars")
  1375. @pytest.mark.parametrize("rvs_shape", [1, 2])
  1376. @pytest.mark.parametrize("rvs_loc", [0, 2])
  1377. @pytest.mark.parametrize("rvs_scale", [1, 5])
  1378. def test_fit(self, rvs_shape, rvs_loc, rvs_scale, rng):
  1379. data = stats.pareto.rvs(size=100, b=rvs_shape, scale=rvs_scale,
  1380. loc=rvs_loc, random_state=rng)
  1381. # shape can still be fixed with multiple names
  1382. shape_mle_analytical1 = stats.pareto.fit(data, floc=0, f0=1.04)[0]
  1383. shape_mle_analytical2 = stats.pareto.fit(data, floc=0, fix_b=1.04)[0]
  1384. shape_mle_analytical3 = stats.pareto.fit(data, floc=0, fb=1.04)[0]
  1385. assert (shape_mle_analytical1 == shape_mle_analytical2 ==
  1386. shape_mle_analytical3 == 1.04)
  1387. # data can be shifted with changes to `loc`
  1388. data = stats.pareto.rvs(size=100, b=rvs_shape, scale=rvs_scale,
  1389. loc=(rvs_loc + 2), random_state=rng)
  1390. shape_mle_a, loc_mle_a, scale_mle_a = stats.pareto.fit(data, floc=2)
  1391. assert_equal(scale_mle_a + 2, data.min())
  1392. data_shift = data - 2
  1393. ndata = data_shift.shape[0]
  1394. assert_equal(shape_mle_a,
  1395. ndata / np.sum(np.log(data_shift/data_shift.min())))
  1396. assert_equal(loc_mle_a, 2)
  1397. @pytest.mark.parametrize("rvs_shape", [.1, 2])
  1398. @pytest.mark.parametrize("rvs_loc", [0, 2])
  1399. @pytest.mark.parametrize("rvs_scale", [1, 5])
  1400. @pytest.mark.parametrize('fix_shape, fix_loc, fix_scale',
  1401. [p for p in product([True, False], repeat=3)
  1402. if False in p])
  1403. @np.errstate(invalid="ignore")
  1404. def test_fit_MLE_comp_optimizer(self, rvs_shape, rvs_loc, rvs_scale,
  1405. fix_shape, fix_loc, fix_scale, rng):
  1406. data = stats.pareto.rvs(size=100, b=rvs_shape, scale=rvs_scale,
  1407. loc=rvs_loc, random_state=rng)
  1408. args = [data, (stats.pareto._fitstart(data), )]
  1409. func = stats.pareto._reduce_func(args, {})[1]
  1410. kwds = {}
  1411. if fix_shape:
  1412. kwds['f0'] = rvs_shape
  1413. if fix_loc:
  1414. kwds['floc'] = rvs_loc
  1415. if fix_scale:
  1416. kwds['fscale'] = rvs_scale
  1417. _assert_less_or_close_loglike(stats.pareto, data, func, **kwds)
  1418. @np.errstate(invalid="ignore")
  1419. def test_fit_known_bad_seed(self):
  1420. # Tests a known seed and set of parameters that would produce a result
  1421. # would violate the support of Pareto if the fit method did not check
  1422. # the constraint `fscale + floc < min(data)`.
  1423. shape, location, scale = 1, 0, 1
  1424. data = stats.pareto.rvs(shape, location, scale, size=100,
  1425. random_state=np.random.default_rng(2535619))
  1426. args = [data, (stats.pareto._fitstart(data), )]
  1427. func = stats.pareto._reduce_func(args, {})[1]
  1428. _assert_less_or_close_loglike(stats.pareto, data, func)
  1429. def test_fit_warnings(self):
  1430. assert_fit_warnings(stats.pareto)
  1431. # `floc` that causes invalid negative data
  1432. assert_raises(FitDataError, stats.pareto.fit, [1, 2, 3], floc=2)
  1433. # `floc` and `fscale` combination causes invalid data
  1434. assert_raises(FitDataError, stats.pareto.fit, [5, 2, 3], floc=1,
  1435. fscale=3)
  1436. def test_negative_data(self, rng):
  1437. data = stats.pareto.rvs(loc=-130, b=1, size=100, random_state=rng)
  1438. assert_array_less(data, 0)
  1439. # The purpose of this test is to make sure that no runtime warnings are
  1440. # raised for all negative data, not the output of the fit method. Other
  1441. # methods test the output but have to silence warnings from the super
  1442. # method.
  1443. _ = stats.pareto.fit(data)
  1444. class TestGenpareto:
  1445. def test_ab(self):
  1446. # c >= 0: a, b = [0, inf]
  1447. for c in [1., 0.]:
  1448. c = np.asarray(c)
  1449. a, b = stats.genpareto._get_support(c)
  1450. assert_equal(a, 0.)
  1451. assert_(np.isposinf(b))
  1452. # c < 0: a=0, b=1/|c|
  1453. c = np.asarray(-2.)
  1454. a, b = stats.genpareto._get_support(c)
  1455. assert_allclose([a, b], [0., 0.5])
  1456. def test_c0(self):
  1457. # with c=0, genpareto reduces to the exponential distribution
  1458. # rv = stats.genpareto(c=0.)
  1459. rv = stats.genpareto(c=0.)
  1460. x = np.linspace(0, 10., 30)
  1461. assert_allclose(rv.pdf(x), stats.expon.pdf(x))
  1462. assert_allclose(rv.cdf(x), stats.expon.cdf(x))
  1463. assert_allclose(rv.sf(x), stats.expon.sf(x))
  1464. q = np.linspace(0., 1., 10)
  1465. assert_allclose(rv.ppf(q), stats.expon.ppf(q))
  1466. def test_cm1(self):
  1467. # with c=-1, genpareto reduces to the uniform distr on [0, 1]
  1468. rv = stats.genpareto(c=-1.)
  1469. x = np.linspace(0, 10., 30)
  1470. assert_allclose(rv.pdf(x), stats.uniform.pdf(x))
  1471. assert_allclose(rv.cdf(x), stats.uniform.cdf(x))
  1472. assert_allclose(rv.sf(x), stats.uniform.sf(x))
  1473. q = np.linspace(0., 1., 10)
  1474. assert_allclose(rv.ppf(q), stats.uniform.ppf(q))
  1475. # logpdf(1., c=-1) should be zero
  1476. assert_allclose(rv.logpdf(1), 0)
  1477. def test_x_inf(self):
  1478. # make sure x=inf is handled gracefully
  1479. rv = stats.genpareto(c=0.1)
  1480. assert_allclose([rv.pdf(np.inf), rv.cdf(np.inf)], [0., 1.])
  1481. assert_(np.isneginf(rv.logpdf(np.inf)))
  1482. rv = stats.genpareto(c=0.)
  1483. assert_allclose([rv.pdf(np.inf), rv.cdf(np.inf)], [0., 1.])
  1484. assert_(np.isneginf(rv.logpdf(np.inf)))
  1485. rv = stats.genpareto(c=-1.)
  1486. assert_allclose([rv.pdf(np.inf), rv.cdf(np.inf)], [0., 1.])
  1487. assert_(np.isneginf(rv.logpdf(np.inf)))
  1488. def test_c_continuity(self):
  1489. # pdf is continuous at c=0, -1
  1490. x = np.linspace(0, 10, 30)
  1491. for c in [0, -1]:
  1492. pdf0 = stats.genpareto.pdf(x, c)
  1493. for dc in [1e-14, -1e-14]:
  1494. pdfc = stats.genpareto.pdf(x, c + dc)
  1495. assert_allclose(pdf0, pdfc, atol=1e-12)
  1496. cdf0 = stats.genpareto.cdf(x, c)
  1497. for dc in [1e-14, 1e-14]:
  1498. cdfc = stats.genpareto.cdf(x, c + dc)
  1499. assert_allclose(cdf0, cdfc, atol=1e-12)
  1500. def test_c_continuity_ppf(self):
  1501. q = np.r_[np.logspace(1e-12, 0.01, base=0.1),
  1502. np.linspace(0.01, 1, 30, endpoint=False),
  1503. 1. - np.logspace(1e-12, 0.01, base=0.1)]
  1504. for c in [0., -1.]:
  1505. ppf0 = stats.genpareto.ppf(q, c)
  1506. for dc in [1e-14, -1e-14]:
  1507. ppfc = stats.genpareto.ppf(q, c + dc)
  1508. assert_allclose(ppf0, ppfc, atol=1e-12)
  1509. def test_c_continuity_isf(self):
  1510. q = np.r_[np.logspace(1e-12, 0.01, base=0.1),
  1511. np.linspace(0.01, 1, 30, endpoint=False),
  1512. 1. - np.logspace(1e-12, 0.01, base=0.1)]
  1513. for c in [0., -1.]:
  1514. isf0 = stats.genpareto.isf(q, c)
  1515. for dc in [1e-14, -1e-14]:
  1516. isfc = stats.genpareto.isf(q, c + dc)
  1517. assert_allclose(isf0, isfc, atol=1e-12)
  1518. def test_cdf_ppf_roundtrip(self):
  1519. # this should pass with machine precision. hat tip @pbrod
  1520. q = np.r_[np.logspace(1e-12, 0.01, base=0.1),
  1521. np.linspace(0.01, 1, 30, endpoint=False),
  1522. 1. - np.logspace(1e-12, 0.01, base=0.1)]
  1523. for c in [1e-8, -1e-18, 1e-15, -1e-15]:
  1524. assert_allclose(stats.genpareto.cdf(stats.genpareto.ppf(q, c), c),
  1525. q, atol=1e-15)
  1526. def test_logsf(self):
  1527. logp = stats.genpareto.logsf(1e10, .01, 0, 1)
  1528. assert_allclose(logp, -1842.0680753952365)
  1529. # Values in 'expected_stats' are
  1530. # [mean, variance, skewness, excess kurtosis].
  1531. @pytest.mark.parametrize(
  1532. 'c, expected_stats',
  1533. [(0, [1, 1, 2, 6]),
  1534. (1/4, [4/3, 32/9, 10/np.sqrt(2), np.nan]),
  1535. (1/9, [9/8, (81/64)*(9/7), (10/9)*np.sqrt(7), 754/45]),
  1536. (-1, [1/2, 1/12, 0, -6/5])])
  1537. def test_stats(self, c, expected_stats):
  1538. result = stats.genpareto.stats(c, moments='mvsk')
  1539. assert_allclose(result, expected_stats, rtol=1e-13, atol=1e-15)
  1540. def test_var(self):
  1541. # Regression test for gh-11168.
  1542. v = stats.genpareto.var(1e-8)
  1543. assert_allclose(v, 1.000000040000001, rtol=1e-13)
  1544. class TestPearson3:
  1545. def setup_method(self):
  1546. np.random.seed(1234)
  1547. def test_rvs(self):
  1548. vals = stats.pearson3.rvs(0.1, size=(2, 50))
  1549. assert_(numpy.shape(vals) == (2, 50))
  1550. assert_(vals.dtype.char in typecodes['AllFloat'])
  1551. val = stats.pearson3.rvs(0.5)
  1552. assert_(isinstance(val, float))
  1553. val = stats.pearson3(0.5).rvs(3)
  1554. assert_(isinstance(val, numpy.ndarray))
  1555. assert_(val.dtype.char in typecodes['AllFloat'])
  1556. assert_(len(val) == 3)
  1557. def test_pdf(self):
  1558. vals = stats.pearson3.pdf(2, [0.0, 0.1, 0.2])
  1559. assert_allclose(vals, np.array([0.05399097, 0.05555481, 0.05670246]),
  1560. atol=1e-6)
  1561. vals = stats.pearson3.pdf(-3, 0.1)
  1562. assert_allclose(vals, np.array([0.00313791]), atol=1e-6)
  1563. vals = stats.pearson3.pdf([-3, -2, -1, 0, 1], 0.1)
  1564. assert_allclose(vals, np.array([0.00313791, 0.05192304, 0.25028092,
  1565. 0.39885918, 0.23413173]), atol=1e-6)
  1566. def test_cdf(self):
  1567. vals = stats.pearson3.cdf(2, [0.0, 0.1, 0.2])
  1568. assert_allclose(vals, np.array([0.97724987, 0.97462004, 0.97213626]),
  1569. atol=1e-6)
  1570. vals = stats.pearson3.cdf(-3, 0.1)
  1571. assert_allclose(vals, [0.00082256], atol=1e-6)
  1572. vals = stats.pearson3.cdf([-3, -2, -1, 0, 1], 0.1)
  1573. assert_allclose(vals, [8.22563821e-04, 1.99860448e-02, 1.58550710e-01,
  1574. 5.06649130e-01, 8.41442111e-01], atol=1e-6)
  1575. def test_negative_cdf_bug_11186(self):
  1576. # incorrect CDFs for negative skews in gh-11186; fixed in gh-12640
  1577. # Also check vectorization w/ negative, zero, and positive skews
  1578. skews = [-3, -1, 0, 0.5]
  1579. x_eval = 0.5
  1580. neg_inf = -30 # avoid RuntimeWarning caused by np.log(0)
  1581. cdfs = stats.pearson3.cdf(x_eval, skews)
  1582. int_pdfs = [quad(stats.pearson3(skew).pdf, neg_inf, x_eval)[0]
  1583. for skew in skews]
  1584. assert_allclose(cdfs, int_pdfs)
  1585. def test_return_array_bug_11746(self):
  1586. # pearson3.moment was returning size 0 or 1 array instead of float
  1587. # The first moment is equal to the loc, which defaults to zero
  1588. moment = stats.pearson3.moment(1, 2)
  1589. assert_equal(moment, 0)
  1590. assert isinstance(moment, np.number)
  1591. moment = stats.pearson3.moment(1, 0.000001)
  1592. assert_equal(moment, 0)
  1593. assert isinstance(moment, np.number)
  1594. def test_ppf_bug_17050(self):
  1595. # incorrect PPF for negative skews were reported in gh-17050
  1596. # Check that this is fixed (even in the array case)
  1597. skews = [-3, -1, 0, 0.5]
  1598. x_eval = 0.5
  1599. res = stats.pearson3.ppf(stats.pearson3.cdf(x_eval, skews), skews)
  1600. assert_allclose(res, x_eval)
  1601. # Negation of the skew flips the distribution about the origin, so
  1602. # the following should hold
  1603. skew = np.array([[-0.5], [1.5]])
  1604. x = np.linspace(-2, 2)
  1605. assert_allclose(stats.pearson3.pdf(x, skew),
  1606. stats.pearson3.pdf(-x, -skew))
  1607. assert_allclose(stats.pearson3.cdf(x, skew),
  1608. stats.pearson3.sf(-x, -skew))
  1609. assert_allclose(stats.pearson3.ppf(x, skew),
  1610. -stats.pearson3.isf(x, -skew))
  1611. class TestKappa4:
  1612. def test_cdf_genpareto(self):
  1613. # h = 1 and k != 0 is generalized Pareto
  1614. x = [0.0, 0.1, 0.2, 0.5]
  1615. h = 1.0
  1616. for k in [-1.9, -1.0, -0.5, -0.2, -0.1, 0.1, 0.2, 0.5, 1.0,
  1617. 1.9]:
  1618. vals = stats.kappa4.cdf(x, h, k)
  1619. # shape parameter is opposite what is expected
  1620. vals_comp = stats.genpareto.cdf(x, -k)
  1621. assert_allclose(vals, vals_comp)
  1622. def test_cdf_genextreme(self):
  1623. # h = 0 and k != 0 is generalized extreme value
  1624. x = np.linspace(-5, 5, 10)
  1625. h = 0.0
  1626. k = np.linspace(-3, 3, 10)
  1627. vals = stats.kappa4.cdf(x, h, k)
  1628. vals_comp = stats.genextreme.cdf(x, k)
  1629. assert_allclose(vals, vals_comp)
  1630. def test_cdf_expon(self):
  1631. # h = 1 and k = 0 is exponential
  1632. x = np.linspace(0, 10, 10)
  1633. h = 1.0
  1634. k = 0.0
  1635. vals = stats.kappa4.cdf(x, h, k)
  1636. vals_comp = stats.expon.cdf(x)
  1637. assert_allclose(vals, vals_comp)
  1638. def test_cdf_gumbel_r(self):
  1639. # h = 0 and k = 0 is gumbel_r
  1640. x = np.linspace(-5, 5, 10)
  1641. h = 0.0
  1642. k = 0.0
  1643. vals = stats.kappa4.cdf(x, h, k)
  1644. vals_comp = stats.gumbel_r.cdf(x)
  1645. assert_allclose(vals, vals_comp)
  1646. def test_cdf_logistic(self):
  1647. # h = -1 and k = 0 is logistic
  1648. x = np.linspace(-5, 5, 10)
  1649. h = -1.0
  1650. k = 0.0
  1651. vals = stats.kappa4.cdf(x, h, k)
  1652. vals_comp = stats.logistic.cdf(x)
  1653. assert_allclose(vals, vals_comp)
  1654. def test_cdf_uniform(self):
  1655. # h = 1 and k = 1 is uniform
  1656. x = np.linspace(-5, 5, 10)
  1657. h = 1.0
  1658. k = 1.0
  1659. vals = stats.kappa4.cdf(x, h, k)
  1660. vals_comp = stats.uniform.cdf(x)
  1661. assert_allclose(vals, vals_comp)
  1662. def test_integers_ctor(self):
  1663. # regression test for gh-7416: _argcheck fails for integer h and k
  1664. # in numpy 1.12
  1665. stats.kappa4(1, 2)
  1666. class TestPoisson:
  1667. def setup_method(self):
  1668. np.random.seed(1234)
  1669. def test_pmf_basic(self):
  1670. # Basic case
  1671. ln2 = np.log(2)
  1672. vals = stats.poisson.pmf([0, 1, 2], ln2)
  1673. expected = [0.5, ln2/2, ln2**2/4]
  1674. assert_allclose(vals, expected)
  1675. def test_mu0(self):
  1676. # Edge case: mu=0
  1677. vals = stats.poisson.pmf([0, 1, 2], 0)
  1678. expected = [1, 0, 0]
  1679. assert_array_equal(vals, expected)
  1680. interval = stats.poisson.interval(0.95, 0)
  1681. assert_equal(interval, (0, 0))
  1682. def test_rvs(self):
  1683. vals = stats.poisson.rvs(0.5, size=(2, 50))
  1684. assert_(numpy.all(vals >= 0))
  1685. assert_(numpy.shape(vals) == (2, 50))
  1686. assert_(vals.dtype.char in typecodes['AllInteger'])
  1687. val = stats.poisson.rvs(0.5)
  1688. assert_(isinstance(val, int))
  1689. val = stats.poisson(0.5).rvs(3)
  1690. assert_(isinstance(val, numpy.ndarray))
  1691. assert_(val.dtype.char in typecodes['AllInteger'])
  1692. def test_stats(self):
  1693. mu = 16.0
  1694. result = stats.poisson.stats(mu, moments='mvsk')
  1695. assert_allclose(result, [mu, mu, np.sqrt(1.0/mu), 1.0/mu])
  1696. mu = np.array([0.0, 1.0, 2.0])
  1697. result = stats.poisson.stats(mu, moments='mvsk')
  1698. expected = (mu, mu, [np.inf, 1, 1/np.sqrt(2)], [np.inf, 1, 0.5])
  1699. assert_allclose(result, expected)
  1700. class TestKSTwo:
  1701. def setup_method(self):
  1702. np.random.seed(1234)
  1703. def test_cdf(self):
  1704. for n in [1, 2, 3, 10, 100, 1000]:
  1705. # Test x-values:
  1706. # 0, 1/2n, where the cdf should be 0
  1707. # 1/n, where the cdf should be n!/n^n
  1708. # 0.5, where the cdf should match ksone.cdf
  1709. # 1-1/n, where cdf = 1-2/n^n
  1710. # 1, where cdf == 1
  1711. # (E.g. Exact values given by Eqn 1 in Simard / L'Ecuyer)
  1712. x = np.array([0, 0.5/n, 1/n, 0.5, 1-1.0/n, 1])
  1713. v1 = (1.0/n)**n
  1714. lg = scipy.special.gammaln(n+1)
  1715. elg = (np.exp(lg) if v1 != 0 else 0)
  1716. expected = np.array([0, 0, v1 * elg,
  1717. 1 - 2*stats.ksone.sf(0.5, n),
  1718. max(1 - 2*v1, 0.0),
  1719. 1.0])
  1720. vals_cdf = stats.kstwo.cdf(x, n)
  1721. assert_allclose(vals_cdf, expected)
  1722. def test_sf(self):
  1723. x = np.linspace(0, 1, 11)
  1724. for n in [1, 2, 3, 10, 100, 1000]:
  1725. # Same x values as in test_cdf, and use sf = 1 - cdf
  1726. x = np.array([0, 0.5/n, 1/n, 0.5, 1-1.0/n, 1])
  1727. v1 = (1.0/n)**n
  1728. lg = scipy.special.gammaln(n+1)
  1729. elg = (np.exp(lg) if v1 != 0 else 0)
  1730. expected = np.array([1.0, 1.0,
  1731. 1 - v1 * elg,
  1732. 2*stats.ksone.sf(0.5, n),
  1733. min(2*v1, 1.0), 0])
  1734. vals_sf = stats.kstwo.sf(x, n)
  1735. assert_allclose(vals_sf, expected)
  1736. def test_cdf_sqrtn(self):
  1737. # For fixed a, cdf(a/sqrt(n), n) -> kstwobign(a) as n->infinity
  1738. # cdf(a/sqrt(n), n) is an increasing function of n (and a)
  1739. # Check that the function is indeed increasing (allowing for some
  1740. # small floating point and algorithm differences.)
  1741. x = np.linspace(0, 2, 11)[1:]
  1742. ns = [50, 100, 200, 400, 1000, 2000]
  1743. for _x in x:
  1744. xn = _x / np.sqrt(ns)
  1745. probs = stats.kstwo.cdf(xn, ns)
  1746. diffs = np.diff(probs)
  1747. assert_array_less(diffs, 1e-8)
  1748. def test_cdf_sf(self):
  1749. x = np.linspace(0, 1, 11)
  1750. for n in [1, 2, 3, 10, 100, 1000]:
  1751. vals_cdf = stats.kstwo.cdf(x, n)
  1752. vals_sf = stats.kstwo.sf(x, n)
  1753. assert_array_almost_equal(vals_cdf, 1 - vals_sf)
  1754. def test_cdf_sf_sqrtn(self):
  1755. x = np.linspace(0, 1, 11)
  1756. for n in [1, 2, 3, 10, 100, 1000]:
  1757. xn = x / np.sqrt(n)
  1758. vals_cdf = stats.kstwo.cdf(xn, n)
  1759. vals_sf = stats.kstwo.sf(xn, n)
  1760. assert_array_almost_equal(vals_cdf, 1 - vals_sf)
  1761. def test_ppf_of_cdf(self):
  1762. x = np.linspace(0, 1, 11)
  1763. for n in [1, 2, 3, 10, 100, 1000]:
  1764. xn = x[x > 0.5/n]
  1765. vals_cdf = stats.kstwo.cdf(xn, n)
  1766. # CDFs close to 1 are better dealt with using the SF
  1767. cond = (0 < vals_cdf) & (vals_cdf < 0.99)
  1768. vals = stats.kstwo.ppf(vals_cdf, n)
  1769. assert_allclose(vals[cond], xn[cond], rtol=1e-4)
  1770. def test_isf_of_sf(self):
  1771. x = np.linspace(0, 1, 11)
  1772. for n in [1, 2, 3, 10, 100, 1000]:
  1773. xn = x[x > 0.5/n]
  1774. vals_isf = stats.kstwo.isf(xn, n)
  1775. cond = (0 < vals_isf) & (vals_isf < 1.0)
  1776. vals = stats.kstwo.sf(vals_isf, n)
  1777. assert_allclose(vals[cond], xn[cond], rtol=1e-4)
  1778. def test_ppf_of_cdf_sqrtn(self):
  1779. x = np.linspace(0, 1, 11)
  1780. for n in [1, 2, 3, 10, 100, 1000]:
  1781. xn = (x / np.sqrt(n))[x > 0.5/n]
  1782. vals_cdf = stats.kstwo.cdf(xn, n)
  1783. cond = (0 < vals_cdf) & (vals_cdf < 1.0)
  1784. vals = stats.kstwo.ppf(vals_cdf, n)
  1785. assert_allclose(vals[cond], xn[cond])
  1786. def test_isf_of_sf_sqrtn(self):
  1787. x = np.linspace(0, 1, 11)
  1788. for n in [1, 2, 3, 10, 100, 1000]:
  1789. xn = (x / np.sqrt(n))[x > 0.5/n]
  1790. vals_sf = stats.kstwo.sf(xn, n)
  1791. # SFs close to 1 are better dealt with using the CDF
  1792. cond = (0 < vals_sf) & (vals_sf < 0.95)
  1793. vals = stats.kstwo.isf(vals_sf, n)
  1794. assert_allclose(vals[cond], xn[cond])
  1795. def test_ppf(self):
  1796. probs = np.linspace(0, 1, 11)[1:]
  1797. for n in [1, 2, 3, 10, 100, 1000]:
  1798. xn = stats.kstwo.ppf(probs, n)
  1799. vals_cdf = stats.kstwo.cdf(xn, n)
  1800. assert_allclose(vals_cdf, probs)
  1801. def test_simard_lecuyer_table1(self):
  1802. # Compute the cdf for values near the mean of the distribution.
  1803. # The mean u ~ log(2)*sqrt(pi/(2n))
  1804. # Compute for x in [u/4, u/3, u/2, u, 2u, 3u]
  1805. # This is the computation of Table 1 of Simard, R., L'Ecuyer, P. (2011)
  1806. # "Computing the Two-Sided Kolmogorov-Smirnov Distribution".
  1807. # Except that the values below are not from the published table, but
  1808. # were generated using an independent SageMath implementation of
  1809. # Durbin's algorithm (with the exponentiation and scaling of
  1810. # Marsaglia/Tsang/Wang's version) using 500 bit arithmetic.
  1811. # Some of the values in the published table have relative
  1812. # errors greater than 1e-4.
  1813. ns = [10, 50, 100, 200, 500, 1000]
  1814. ratios = np.array([1.0/4, 1.0/3, 1.0/2, 1, 2, 3])
  1815. expected = np.array([
  1816. [1.92155292e-08, 5.72933228e-05, 2.15233226e-02, 6.31566589e-01,
  1817. 9.97685592e-01, 9.99999942e-01],
  1818. [2.28096224e-09, 1.99142563e-05, 1.42617934e-02, 5.95345542e-01,
  1819. 9.96177701e-01, 9.99998662e-01],
  1820. [1.00201886e-09, 1.32673079e-05, 1.24608594e-02, 5.86163220e-01,
  1821. 9.95866877e-01, 9.99998240e-01],
  1822. [4.93313022e-10, 9.52658029e-06, 1.12123138e-02, 5.79486872e-01,
  1823. 9.95661824e-01, 9.99997964e-01],
  1824. [2.37049293e-10, 6.85002458e-06, 1.01309221e-02, 5.73427224e-01,
  1825. 9.95491207e-01, 9.99997750e-01],
  1826. [1.56990874e-10, 5.71738276e-06, 9.59725430e-03, 5.70322692e-01,
  1827. 9.95409545e-01, 9.99997657e-01]
  1828. ])
  1829. for idx, n in enumerate(ns):
  1830. x = ratios * np.log(2) * np.sqrt(np.pi/2/n)
  1831. vals_cdf = stats.kstwo.cdf(x, n)
  1832. assert_allclose(vals_cdf, expected[idx], rtol=1e-5)
  1833. class TestZipf:
  1834. def setup_method(self):
  1835. np.random.seed(1234)
  1836. def test_rvs(self):
  1837. vals = stats.zipf.rvs(1.5, size=(2, 50))
  1838. assert_(numpy.all(vals >= 1))
  1839. assert_(numpy.shape(vals) == (2, 50))
  1840. assert_(vals.dtype.char in typecodes['AllInteger'])
  1841. val = stats.zipf.rvs(1.5)
  1842. assert_(isinstance(val, int))
  1843. val = stats.zipf(1.5).rvs(3)
  1844. assert_(isinstance(val, numpy.ndarray))
  1845. assert_(val.dtype.char in typecodes['AllInteger'])
  1846. def test_moments(self):
  1847. # n-th moment is finite iff a > n + 1
  1848. m, v = stats.zipf.stats(a=2.8)
  1849. assert_(np.isfinite(m))
  1850. assert_equal(v, np.inf)
  1851. s, k = stats.zipf.stats(a=4.8, moments='sk')
  1852. assert_(not np.isfinite([s, k]).all())
  1853. class TestDLaplace:
  1854. def setup_method(self):
  1855. np.random.seed(1234)
  1856. def test_rvs(self):
  1857. vals = stats.dlaplace.rvs(1.5, size=(2, 50))
  1858. assert_(numpy.shape(vals) == (2, 50))
  1859. assert_(vals.dtype.char in typecodes['AllInteger'])
  1860. val = stats.dlaplace.rvs(1.5)
  1861. assert_(isinstance(val, int))
  1862. val = stats.dlaplace(1.5).rvs(3)
  1863. assert_(isinstance(val, numpy.ndarray))
  1864. assert_(val.dtype.char in typecodes['AllInteger'])
  1865. assert_(stats.dlaplace.rvs(0.8) is not None)
  1866. def test_stats(self):
  1867. # compare the explicit formulas w/ direct summation using pmf
  1868. a = 1.
  1869. dl = stats.dlaplace(a)
  1870. m, v, s, k = dl.stats('mvsk')
  1871. N = 37
  1872. xx = np.arange(-N, N+1)
  1873. pp = dl.pmf(xx)
  1874. m2, m4 = np.sum(pp*xx**2), np.sum(pp*xx**4)
  1875. assert_equal((m, s), (0, 0))
  1876. assert_allclose((v, k), (m2, m4/m2**2 - 3.), atol=1e-14, rtol=1e-8)
  1877. def test_stats2(self):
  1878. a = np.log(2.)
  1879. dl = stats.dlaplace(a)
  1880. m, v, s, k = dl.stats('mvsk')
  1881. assert_equal((m, s), (0., 0.))
  1882. assert_allclose((v, k), (4., 3.25))
  1883. class TestInvgauss:
  1884. def setup_method(self):
  1885. np.random.seed(1234)
  1886. @pytest.mark.parametrize("rvs_mu,rvs_loc,rvs_scale",
  1887. [(2, 0, 1), (4.635, 4.362, 6.303)])
  1888. def test_fit(self, rvs_mu, rvs_loc, rvs_scale):
  1889. data = stats.invgauss.rvs(size=100, mu=rvs_mu,
  1890. loc=rvs_loc, scale=rvs_scale)
  1891. # Analytical MLEs are calculated with formula when `floc` is fixed
  1892. mu, loc, scale = stats.invgauss.fit(data, floc=rvs_loc)
  1893. data = data - rvs_loc
  1894. mu_temp = np.mean(data)
  1895. scale_mle = len(data) / (np.sum(data**(-1) - mu_temp**(-1)))
  1896. mu_mle = mu_temp/scale_mle
  1897. # `mu` and `scale` match analytical formula
  1898. assert_allclose(mu_mle, mu, atol=1e-15, rtol=1e-15)
  1899. assert_allclose(scale_mle, scale, atol=1e-15, rtol=1e-15)
  1900. assert_equal(loc, rvs_loc)
  1901. data = stats.invgauss.rvs(size=100, mu=rvs_mu,
  1902. loc=rvs_loc, scale=rvs_scale)
  1903. # fixed parameters are returned
  1904. mu, loc, scale = stats.invgauss.fit(data, floc=rvs_loc - 1,
  1905. fscale=rvs_scale + 1)
  1906. assert_equal(rvs_scale + 1, scale)
  1907. assert_equal(rvs_loc - 1, loc)
  1908. # shape can still be fixed with multiple names
  1909. shape_mle1 = stats.invgauss.fit(data, fmu=1.04)[0]
  1910. shape_mle2 = stats.invgauss.fit(data, fix_mu=1.04)[0]
  1911. shape_mle3 = stats.invgauss.fit(data, f0=1.04)[0]
  1912. assert shape_mle1 == shape_mle2 == shape_mle3 == 1.04
  1913. @pytest.mark.parametrize("rvs_mu,rvs_loc,rvs_scale",
  1914. [(2, 0, 1), (6.311, 3.225, 4.520)])
  1915. def test_fit_MLE_comp_optimizer(self, rvs_mu, rvs_loc, rvs_scale):
  1916. data = stats.invgauss.rvs(size=100, mu=rvs_mu,
  1917. loc=rvs_loc, scale=rvs_scale)
  1918. super_fit = super(type(stats.invgauss), stats.invgauss).fit
  1919. # fitting without `floc` uses superclass fit method
  1920. super_fitted = super_fit(data)
  1921. invgauss_fit = stats.invgauss.fit(data)
  1922. assert_equal(super_fitted, invgauss_fit)
  1923. # fitting with `fmu` is uses superclass fit method
  1924. super_fitted = super_fit(data, floc=0, fmu=2)
  1925. invgauss_fit = stats.invgauss.fit(data, floc=0, fmu=2)
  1926. assert_equal(super_fitted, invgauss_fit)
  1927. # obtain log-likelihood objective function to compare results
  1928. args = [data, (stats.invgauss._fitstart(data), )]
  1929. func = stats.invgauss._reduce_func(args, {})[1]
  1930. # fixed `floc` uses analytical formula and provides better fit than
  1931. # super method
  1932. _assert_less_or_close_loglike(stats.invgauss, data, func, floc=rvs_loc)
  1933. # fixed `floc` not resulting in invalid data < 0 uses analytical
  1934. # formulas and provides a better fit than the super method
  1935. assert np.all((data - (rvs_loc - 1)) > 0)
  1936. _assert_less_or_close_loglike(stats.invgauss, data, func,
  1937. floc=rvs_loc - 1)
  1938. # fixed `floc` to an arbitrary number, 0, still provides a better fit
  1939. # than the super method
  1940. _assert_less_or_close_loglike(stats.invgauss, data, func, floc=0)
  1941. # fixed `fscale` to an arbitrary number still provides a better fit
  1942. # than the super method
  1943. _assert_less_or_close_loglike(stats.invgauss, data, func, floc=rvs_loc,
  1944. fscale=np.random.rand(1)[0])
  1945. def test_fit_raise_errors(self):
  1946. assert_fit_warnings(stats.invgauss)
  1947. # FitDataError is raised when negative invalid data
  1948. with pytest.raises(FitDataError):
  1949. stats.invgauss.fit([1, 2, 3], floc=2)
  1950. def test_cdf_sf(self):
  1951. # Regression tests for gh-13614.
  1952. # Ground truth from R's statmod library (pinvgauss), e.g.
  1953. # library(statmod)
  1954. # options(digits=15)
  1955. # mu = c(4.17022005e-04, 7.20324493e-03, 1.14374817e-06,
  1956. # 3.02332573e-03, 1.46755891e-03)
  1957. # print(pinvgauss(5, mu, 1))
  1958. # make sure a finite value is returned when mu is very small. see
  1959. # GH-13614
  1960. mu = [4.17022005e-04, 7.20324493e-03, 1.14374817e-06,
  1961. 3.02332573e-03, 1.46755891e-03]
  1962. expected = [1, 1, 1, 1, 1]
  1963. actual = stats.invgauss.cdf(0.4, mu=mu)
  1964. assert_equal(expected, actual)
  1965. # test if the function can distinguish small left/right tail
  1966. # probabilities from zero.
  1967. cdf_actual = stats.invgauss.cdf(0.001, mu=1.05)
  1968. assert_allclose(cdf_actual, 4.65246506892667e-219)
  1969. sf_actual = stats.invgauss.sf(110, mu=1.05)
  1970. assert_allclose(sf_actual, 4.12851625944048e-25)
  1971. # test if x does not cause numerical issues when mu is very small
  1972. # and x is close to mu in value.
  1973. # slightly smaller than mu
  1974. actual = stats.invgauss.cdf(0.00009, 0.0001)
  1975. assert_allclose(actual, 2.9458022894924e-26)
  1976. # slightly bigger than mu
  1977. actual = stats.invgauss.cdf(0.000102, 0.0001)
  1978. assert_allclose(actual, 0.976445540507925)
  1979. def test_logcdf_logsf(self):
  1980. # Regression tests for improvements made in gh-13616.
  1981. # Ground truth from R's statmod library (pinvgauss), e.g.
  1982. # library(statmod)
  1983. # options(digits=15)
  1984. # print(pinvgauss(0.001, 1.05, 1, log.p=TRUE, lower.tail=FALSE))
  1985. # test if logcdf and logsf can compute values too small to
  1986. # be represented on the unlogged scale. See: gh-13616
  1987. logcdf = stats.invgauss.logcdf(0.0001, mu=1.05)
  1988. assert_allclose(logcdf, -5003.87872590367)
  1989. logcdf = stats.invgauss.logcdf(110, 1.05)
  1990. assert_allclose(logcdf, -4.12851625944087e-25)
  1991. logsf = stats.invgauss.logsf(0.001, mu=1.05)
  1992. assert_allclose(logsf, -4.65246506892676e-219)
  1993. logsf = stats.invgauss.logsf(110, 1.05)
  1994. assert_allclose(logsf, -56.1467092416426)
  1995. class TestLaplace:
  1996. @pytest.mark.parametrize("rvs_loc", [-5, 0, 1, 2])
  1997. @pytest.mark.parametrize("rvs_scale", [1, 2, 3, 10])
  1998. def test_fit(self, rvs_loc, rvs_scale):
  1999. # tests that various inputs follow expected behavior
  2000. # for a variety of `loc` and `scale`.
  2001. data = stats.laplace.rvs(size=100, loc=rvs_loc, scale=rvs_scale)
  2002. # MLE estimates are given by
  2003. loc_mle = np.median(data)
  2004. scale_mle = np.sum(np.abs(data - loc_mle)) / len(data)
  2005. # standard outputs should match analytical MLE formulas
  2006. loc, scale = stats.laplace.fit(data)
  2007. assert_allclose(loc, loc_mle, atol=1e-15, rtol=1e-15)
  2008. assert_allclose(scale, scale_mle, atol=1e-15, rtol=1e-15)
  2009. # fixed parameter should use analytical formula for other
  2010. loc, scale = stats.laplace.fit(data, floc=loc_mle)
  2011. assert_allclose(scale, scale_mle, atol=1e-15, rtol=1e-15)
  2012. loc, scale = stats.laplace.fit(data, fscale=scale_mle)
  2013. assert_allclose(loc, loc_mle)
  2014. # test with non-mle fixed parameter
  2015. # create scale with non-median loc
  2016. loc = rvs_loc * 2
  2017. scale_mle = np.sum(np.abs(data - loc)) / len(data)
  2018. # fixed loc to non median, scale should match
  2019. # scale calculation with modified loc
  2020. loc, scale = stats.laplace.fit(data, floc=loc)
  2021. assert_equal(scale_mle, scale)
  2022. # fixed scale created with non median loc,
  2023. # loc output should still be the data median.
  2024. loc, scale = stats.laplace.fit(data, fscale=scale_mle)
  2025. assert_equal(loc_mle, loc)
  2026. # error raised when both `floc` and `fscale` are fixed
  2027. assert_raises(RuntimeError, stats.laplace.fit, data, floc=loc_mle,
  2028. fscale=scale_mle)
  2029. # error is raised with non-finite values
  2030. assert_raises(ValueError, stats.laplace.fit, [np.nan])
  2031. assert_raises(ValueError, stats.laplace.fit, [np.inf])
  2032. @pytest.mark.parametrize("rvs_scale,rvs_loc", [(10, -5),
  2033. (5, 10),
  2034. (.2, .5)])
  2035. def test_fit_MLE_comp_optimizer(self, rvs_loc, rvs_scale):
  2036. data = stats.laplace.rvs(size=1000, loc=rvs_loc, scale=rvs_scale)
  2037. # the log-likelihood function for laplace is given by
  2038. def ll(loc, scale, data):
  2039. return -1 * (- (len(data)) * np.log(2*scale) -
  2040. (1/scale)*np.sum(np.abs(data - loc)))
  2041. # test that the objective function result of the analytical MLEs is
  2042. # less than or equal to that of the numerically optimized estimate
  2043. loc, scale = stats.laplace.fit(data)
  2044. loc_opt, scale_opt = super(type(stats.laplace),
  2045. stats.laplace).fit(data)
  2046. ll_mle = ll(loc, scale, data)
  2047. ll_opt = ll(loc_opt, scale_opt, data)
  2048. assert ll_mle < ll_opt or np.allclose(ll_mle, ll_opt,
  2049. atol=1e-15, rtol=1e-15)
  2050. def test_fit_simple_non_random_data(self):
  2051. data = np.array([1.0, 1.0, 3.0, 5.0, 8.0, 14.0])
  2052. # with `floc` fixed to 6, scale should be 4.
  2053. loc, scale = stats.laplace.fit(data, floc=6)
  2054. assert_allclose(scale, 4, atol=1e-15, rtol=1e-15)
  2055. # with `fscale` fixed to 6, loc should be 4.
  2056. loc, scale = stats.laplace.fit(data, fscale=6)
  2057. assert_allclose(loc, 4, atol=1e-15, rtol=1e-15)
  2058. def test_sf_cdf_extremes(self):
  2059. # These calculations should not generate warnings.
  2060. x = 1000
  2061. p0 = stats.laplace.cdf(-x)
  2062. # The exact value is smaller than can be represented with
  2063. # 64 bit floating point, so the exected result is 0.
  2064. assert p0 == 0.0
  2065. # The closest 64 bit floating point representation of the
  2066. # exact value is 1.0.
  2067. p1 = stats.laplace.cdf(x)
  2068. assert p1 == 1.0
  2069. p0 = stats.laplace.sf(x)
  2070. # The exact value is smaller than can be represented with
  2071. # 64 bit floating point, so the exected result is 0.
  2072. assert p0 == 0.0
  2073. # The closest 64 bit floating point representation of the
  2074. # exact value is 1.0.
  2075. p1 = stats.laplace.sf(-x)
  2076. assert p1 == 1.0
  2077. def test_sf(self):
  2078. x = 200
  2079. p = stats.laplace.sf(x)
  2080. assert_allclose(p, np.exp(-x)/2, rtol=1e-13)
  2081. def test_isf(self):
  2082. p = 1e-25
  2083. x = stats.laplace.isf(p)
  2084. assert_allclose(x, -np.log(2*p), rtol=1e-13)
  2085. class TestPowerlaw(object):
  2086. @pytest.fixture(scope='function')
  2087. def rng(self):
  2088. return np.random.default_rng(1234)
  2089. @pytest.mark.parametrize("rvs_shape", [.1, .5, .75, 1, 2])
  2090. @pytest.mark.parametrize("rvs_loc", [-1, 0, 1])
  2091. @pytest.mark.parametrize("rvs_scale", [.1, 1, 5])
  2092. @pytest.mark.parametrize('fix_shape, fix_loc, fix_scale',
  2093. [p for p in product([True, False], repeat=3)
  2094. if False in p])
  2095. def test_fit_MLE_comp_optimizer(self, rvs_shape, rvs_loc, rvs_scale,
  2096. fix_shape, fix_loc, fix_scale, rng):
  2097. data = stats.powerlaw.rvs(size=250, a=rvs_shape, loc=rvs_loc,
  2098. scale=rvs_scale, random_state=rng)
  2099. args = [data, (stats.powerlaw._fitstart(data), )]
  2100. func = stats.powerlaw._reduce_func(args, {})[1]
  2101. kwds = dict()
  2102. if fix_shape:
  2103. kwds['f0'] = rvs_shape
  2104. if fix_loc:
  2105. kwds['floc'] = np.nextafter(data.min(), -np.inf)
  2106. if fix_scale:
  2107. kwds['fscale'] = rvs_scale
  2108. _assert_less_or_close_loglike(stats.powerlaw, data, func, **kwds)
  2109. def test_problem_case(self):
  2110. # An observed problem with the test method indicated that some fixed
  2111. # scale values could cause bad results, this is now corrected.
  2112. a = 2.50002862645130604506
  2113. location = 0.0
  2114. scale = 35.249023299873095
  2115. data = stats.powerlaw.rvs(a=a, loc=location, scale=scale, size=100,
  2116. random_state=np.random.default_rng(5))
  2117. kwds = {'fscale': data.ptp() * 2}
  2118. args = [data, (stats.powerlaw._fitstart(data), )]
  2119. func = stats.powerlaw._reduce_func(args, {})[1]
  2120. _assert_less_or_close_loglike(stats.powerlaw, data, func, **kwds)
  2121. def test_fit_warnings(self):
  2122. assert_fit_warnings(stats.powerlaw)
  2123. # test for error when `fscale + floc <= np.max(data)` is not satisfied
  2124. msg = r" Maximum likelihood estimation with 'powerlaw' requires"
  2125. with assert_raises(FitDataError, match=msg):
  2126. stats.powerlaw.fit([1, 2, 4], floc=0, fscale=3)
  2127. # test for error when `data - floc >= 0` is not satisfied
  2128. msg = r" Maximum likelihood estimation with 'powerlaw' requires"
  2129. with assert_raises(FitDataError, match=msg):
  2130. stats.powerlaw.fit([1, 2, 4], floc=2)
  2131. # test for fixed location not less than `min(data)`.
  2132. msg = r" Maximum likelihood estimation with 'powerlaw' requires"
  2133. with assert_raises(FitDataError, match=msg):
  2134. stats.powerlaw.fit([1, 2, 4], floc=1)
  2135. # test for when fixed scale is less than or equal to range of data
  2136. msg = r"Negative or zero `fscale` is outside"
  2137. with assert_raises(ValueError, match=msg):
  2138. stats.powerlaw.fit([1, 2, 4], fscale=-3)
  2139. # test for when fixed scale is less than or equal to range of data
  2140. msg = r"`fscale` must be greater than the range of data."
  2141. with assert_raises(ValueError, match=msg):
  2142. stats.powerlaw.fit([1, 2, 4], fscale=3)
  2143. def test_minimum_data_zero_gh17801(self):
  2144. # gh-17801 reported an overflow error when the minimum value of the
  2145. # data is zero. Check that this problem is resolved.
  2146. data = [0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 5, 6]
  2147. dist = stats.powerlaw
  2148. with np.errstate(over='ignore'):
  2149. _assert_less_or_close_loglike(dist, data, dist.nnlf)
  2150. class TestInvGamma:
  2151. def test_invgamma_inf_gh_1866(self):
  2152. # invgamma's moments are only finite for a>n
  2153. # specific numbers checked w/ boost 1.54
  2154. with warnings.catch_warnings():
  2155. warnings.simplefilter('error', RuntimeWarning)
  2156. mvsk = stats.invgamma.stats(a=19.31, moments='mvsk')
  2157. expected = [0.05461496450, 0.0001723162534, 1.020362676,
  2158. 2.055616582]
  2159. assert_allclose(mvsk, expected)
  2160. a = [1.1, 3.1, 5.6]
  2161. mvsk = stats.invgamma.stats(a=a, moments='mvsk')
  2162. expected = ([10., 0.476190476, 0.2173913043], # mmm
  2163. [np.inf, 0.2061430632, 0.01312749422], # vvv
  2164. [np.nan, 41.95235392, 2.919025532], # sss
  2165. [np.nan, np.nan, 24.51923076]) # kkk
  2166. for x, y in zip(mvsk, expected):
  2167. assert_almost_equal(x, y)
  2168. def test_cdf_ppf(self):
  2169. # gh-6245
  2170. x = np.logspace(-2.6, 0)
  2171. y = stats.invgamma.cdf(x, 1)
  2172. xx = stats.invgamma.ppf(y, 1)
  2173. assert_allclose(x, xx)
  2174. def test_sf_isf(self):
  2175. # gh-6245
  2176. if sys.maxsize > 2**32:
  2177. x = np.logspace(2, 100)
  2178. else:
  2179. # Invgamme roundtrip on 32-bit systems has relative accuracy
  2180. # ~1e-15 until x=1e+15, and becomes inf above x=1e+18
  2181. x = np.logspace(2, 18)
  2182. y = stats.invgamma.sf(x, 1)
  2183. xx = stats.invgamma.isf(y, 1)
  2184. assert_allclose(x, xx, rtol=1.0)
  2185. class TestF:
  2186. def test_endpoints(self):
  2187. # Compute the pdf at the left endpoint dst.a.
  2188. data = [[stats.f, (2, 1), 1.0]]
  2189. for _f, _args, _correct in data:
  2190. ans = _f.pdf(_f.a, *_args)
  2191. ans = [_f.pdf(_f.a, *_args) for _f, _args, _ in data]
  2192. correct = [_correct_ for _f, _args, _correct_ in data]
  2193. assert_array_almost_equal(ans, correct)
  2194. def test_f_moments(self):
  2195. # n-th moment of F distributions is only finite for n < dfd / 2
  2196. m, v, s, k = stats.f.stats(11, 6.5, moments='mvsk')
  2197. assert_(np.isfinite(m))
  2198. assert_(np.isfinite(v))
  2199. assert_(np.isfinite(s))
  2200. assert_(not np.isfinite(k))
  2201. def test_moments_warnings(self):
  2202. # no warnings should be generated for dfd = 2, 4, 6, 8 (div by zero)
  2203. with warnings.catch_warnings():
  2204. warnings.simplefilter('error', RuntimeWarning)
  2205. stats.f.stats(dfn=[11]*4, dfd=[2, 4, 6, 8], moments='mvsk')
  2206. def test_stats_broadcast(self):
  2207. dfn = np.array([[3], [11]])
  2208. dfd = np.array([11, 12])
  2209. m, v, s, k = stats.f.stats(dfn=dfn, dfd=dfd, moments='mvsk')
  2210. m2 = [dfd / (dfd - 2)]*2
  2211. assert_allclose(m, m2)
  2212. v2 = 2 * dfd**2 * (dfn + dfd - 2) / dfn / (dfd - 2)**2 / (dfd - 4)
  2213. assert_allclose(v, v2)
  2214. s2 = ((2*dfn + dfd - 2) * np.sqrt(8*(dfd - 4)) /
  2215. ((dfd - 6) * np.sqrt(dfn*(dfn + dfd - 2))))
  2216. assert_allclose(s, s2)
  2217. k2num = 12 * (dfn * (5*dfd - 22) * (dfn + dfd - 2) +
  2218. (dfd - 4) * (dfd - 2)**2)
  2219. k2den = dfn * (dfd - 6) * (dfd - 8) * (dfn + dfd - 2)
  2220. k2 = k2num / k2den
  2221. assert_allclose(k, k2)
  2222. def test_rvgeneric_std():
  2223. # Regression test for #1191
  2224. assert_array_almost_equal(stats.t.std([5, 6]), [1.29099445, 1.22474487])
  2225. def test_moments_t():
  2226. # regression test for #8786
  2227. assert_equal(stats.t.stats(df=1, moments='mvsk'),
  2228. (np.inf, np.nan, np.nan, np.nan))
  2229. assert_equal(stats.t.stats(df=1.01, moments='mvsk'),
  2230. (0.0, np.inf, np.nan, np.nan))
  2231. assert_equal(stats.t.stats(df=2, moments='mvsk'),
  2232. (0.0, np.inf, np.nan, np.nan))
  2233. assert_equal(stats.t.stats(df=2.01, moments='mvsk'),
  2234. (0.0, 2.01/(2.01-2.0), np.nan, np.inf))
  2235. assert_equal(stats.t.stats(df=3, moments='sk'), (np.nan, np.inf))
  2236. assert_equal(stats.t.stats(df=3.01, moments='sk'), (0.0, np.inf))
  2237. assert_equal(stats.t.stats(df=4, moments='sk'), (0.0, np.inf))
  2238. assert_equal(stats.t.stats(df=4.01, moments='sk'), (0.0, 6.0/(4.01 - 4.0)))
  2239. def test_t_entropy():
  2240. df = [1, 2, 25, 100]
  2241. # Expected values were computed with mpmath.
  2242. expected = [2.5310242469692907, 1.9602792291600821,
  2243. 1.459327578078393, 1.4289633653182439]
  2244. assert_allclose(stats.t.entropy(df), expected, rtol=1e-13)
  2245. @pytest.mark.parametrize("methname", ["pdf", "logpdf", "cdf",
  2246. "ppf", "sf", "isf"])
  2247. @pytest.mark.parametrize("df_infmask", [[0, 0], [1, 1], [0, 1],
  2248. [[0, 1, 0], [1, 1, 1]],
  2249. [[1, 0], [0, 1]],
  2250. [[0], [1]]])
  2251. def test_t_inf_df(methname, df_infmask):
  2252. np.random.seed(0)
  2253. df_infmask = np.asarray(df_infmask, dtype=bool)
  2254. df = np.random.uniform(0, 10, size=df_infmask.shape)
  2255. x = np.random.randn(*df_infmask.shape)
  2256. df[df_infmask] = np.inf
  2257. t_dist = stats.t(df=df, loc=3, scale=1)
  2258. t_dist_ref = stats.t(df=df[~df_infmask], loc=3, scale=1)
  2259. norm_dist = stats.norm(loc=3, scale=1)
  2260. t_meth = getattr(t_dist, methname)
  2261. t_meth_ref = getattr(t_dist_ref, methname)
  2262. norm_meth = getattr(norm_dist, methname)
  2263. res = t_meth(x)
  2264. assert_equal(res[df_infmask], norm_meth(x[df_infmask]))
  2265. assert_equal(res[~df_infmask], t_meth_ref(x[~df_infmask]))
  2266. @pytest.mark.parametrize("df_infmask", [[0, 0], [1, 1], [0, 1],
  2267. [[0, 1, 0], [1, 1, 1]],
  2268. [[1, 0], [0, 1]],
  2269. [[0], [1]]])
  2270. def test_t_inf_df_stats_entropy(df_infmask):
  2271. np.random.seed(0)
  2272. df_infmask = np.asarray(df_infmask, dtype=bool)
  2273. df = np.random.uniform(0, 10, size=df_infmask.shape)
  2274. df[df_infmask] = np.inf
  2275. res = stats.t.stats(df=df, loc=3, scale=1, moments='mvsk')
  2276. res_ex_inf = stats.norm.stats(loc=3, scale=1, moments='mvsk')
  2277. res_ex_noinf = stats.t.stats(df=df[~df_infmask], loc=3, scale=1,
  2278. moments='mvsk')
  2279. for i in range(4):
  2280. assert_equal(res[i][df_infmask], res_ex_inf[i])
  2281. assert_equal(res[i][~df_infmask], res_ex_noinf[i])
  2282. res = stats.t.entropy(df=df, loc=3, scale=1)
  2283. res_ex_inf = stats.norm.entropy(loc=3, scale=1)
  2284. res_ex_noinf = stats.t.entropy(df=df[~df_infmask], loc=3, scale=1)
  2285. assert_equal(res[df_infmask], res_ex_inf)
  2286. assert_equal(res[~df_infmask], res_ex_noinf)
  2287. class TestRvDiscrete:
  2288. def setup_method(self):
  2289. np.random.seed(1234)
  2290. def test_rvs(self):
  2291. states = [-1, 0, 1, 2, 3, 4]
  2292. probability = [0.0, 0.3, 0.4, 0.0, 0.3, 0.0]
  2293. samples = 1000
  2294. r = stats.rv_discrete(name='sample', values=(states, probability))
  2295. x = r.rvs(size=samples)
  2296. assert_(isinstance(x, numpy.ndarray))
  2297. for s, p in zip(states, probability):
  2298. assert_(abs(sum(x == s)/float(samples) - p) < 0.05)
  2299. x = r.rvs()
  2300. assert np.issubdtype(type(x), np.integer)
  2301. def test_entropy(self):
  2302. # Basic tests of entropy.
  2303. pvals = np.array([0.25, 0.45, 0.3])
  2304. p = stats.rv_discrete(values=([0, 1, 2], pvals))
  2305. expected_h = -sum(xlogy(pvals, pvals))
  2306. h = p.entropy()
  2307. assert_allclose(h, expected_h)
  2308. p = stats.rv_discrete(values=([0, 1, 2], [1.0, 0, 0]))
  2309. h = p.entropy()
  2310. assert_equal(h, 0.0)
  2311. def test_pmf(self):
  2312. xk = [1, 2, 4]
  2313. pk = [0.5, 0.3, 0.2]
  2314. rv = stats.rv_discrete(values=(xk, pk))
  2315. x = [[1., 4.],
  2316. [3., 2]]
  2317. assert_allclose(rv.pmf(x),
  2318. [[0.5, 0.2],
  2319. [0., 0.3]], atol=1e-14)
  2320. def test_cdf(self):
  2321. xk = [1, 2, 4]
  2322. pk = [0.5, 0.3, 0.2]
  2323. rv = stats.rv_discrete(values=(xk, pk))
  2324. x_values = [-2, 1., 1.1, 1.5, 2.0, 3.0, 4, 5]
  2325. expected = [0, 0.5, 0.5, 0.5, 0.8, 0.8, 1, 1]
  2326. assert_allclose(rv.cdf(x_values), expected, atol=1e-14)
  2327. # also check scalar arguments
  2328. assert_allclose([rv.cdf(xx) for xx in x_values],
  2329. expected, atol=1e-14)
  2330. def test_ppf(self):
  2331. xk = [1, 2, 4]
  2332. pk = [0.5, 0.3, 0.2]
  2333. rv = stats.rv_discrete(values=(xk, pk))
  2334. q_values = [0.1, 0.5, 0.6, 0.8, 0.9, 1.]
  2335. expected = [1, 1, 2, 2, 4, 4]
  2336. assert_allclose(rv.ppf(q_values), expected, atol=1e-14)
  2337. # also check scalar arguments
  2338. assert_allclose([rv.ppf(q) for q in q_values],
  2339. expected, atol=1e-14)
  2340. def test_cdf_ppf_next(self):
  2341. # copied and special cased from test_discrete_basic
  2342. vals = ([1, 2, 4, 7, 8], [0.1, 0.2, 0.3, 0.3, 0.1])
  2343. rv = stats.rv_discrete(values=vals)
  2344. assert_array_equal(rv.ppf(rv.cdf(rv.xk[:-1]) + 1e-8),
  2345. rv.xk[1:])
  2346. def test_multidimension(self):
  2347. xk = np.arange(12).reshape((3, 4))
  2348. pk = np.array([[0.1, 0.1, 0.15, 0.05],
  2349. [0.1, 0.1, 0.05, 0.05],
  2350. [0.1, 0.1, 0.05, 0.05]])
  2351. rv = stats.rv_discrete(values=(xk, pk))
  2352. assert_allclose(rv.expect(), np.sum(rv.xk * rv.pk), atol=1e-14)
  2353. def test_bad_input(self):
  2354. xk = [1, 2, 3]
  2355. pk = [0.5, 0.5]
  2356. assert_raises(ValueError, stats.rv_discrete, **dict(values=(xk, pk)))
  2357. pk = [1, 2, 3]
  2358. assert_raises(ValueError, stats.rv_discrete, **dict(values=(xk, pk)))
  2359. xk = [1, 2, 3]
  2360. pk = [0.5, 1.2, -0.7]
  2361. assert_raises(ValueError, stats.rv_discrete, **dict(values=(xk, pk)))
  2362. xk = [1, 2, 3, 4, 5]
  2363. pk = [0.3, 0.3, 0.3, 0.3, -0.2]
  2364. assert_raises(ValueError, stats.rv_discrete, **dict(values=(xk, pk)))
  2365. def test_shape_rv_sample(self):
  2366. # tests added for gh-9565
  2367. # mismatch of 2d inputs
  2368. xk, pk = np.arange(4).reshape((2, 2)), np.full((2, 3), 1/6)
  2369. assert_raises(ValueError, stats.rv_discrete, **dict(values=(xk, pk)))
  2370. # same number of elements, but shapes not compatible
  2371. xk, pk = np.arange(6).reshape((3, 2)), np.full((2, 3), 1/6)
  2372. assert_raises(ValueError, stats.rv_discrete, **dict(values=(xk, pk)))
  2373. # same shapes => no error
  2374. xk, pk = np.arange(6).reshape((3, 2)), np.full((3, 2), 1/6)
  2375. assert_equal(stats.rv_discrete(values=(xk, pk)).pmf(0), 1/6)
  2376. def test_expect1(self):
  2377. xk = [1, 2, 4, 6, 7, 11]
  2378. pk = [0.1, 0.2, 0.2, 0.2, 0.2, 0.1]
  2379. rv = stats.rv_discrete(values=(xk, pk))
  2380. assert_allclose(rv.expect(), np.sum(rv.xk * rv.pk), atol=1e-14)
  2381. def test_expect2(self):
  2382. # rv_sample should override _expect. Bug report from
  2383. # https://stackoverflow.com/questions/63199792
  2384. y = [200.0, 300.0, 400.0, 500.0, 600.0, 700.0, 800.0, 900.0, 1000.0,
  2385. 1100.0, 1200.0, 1300.0, 1400.0, 1500.0, 1600.0, 1700.0, 1800.0,
  2386. 1900.0, 2000.0, 2100.0, 2200.0, 2300.0, 2400.0, 2500.0, 2600.0,
  2387. 2700.0, 2800.0, 2900.0, 3000.0, 3100.0, 3200.0, 3300.0, 3400.0,
  2388. 3500.0, 3600.0, 3700.0, 3800.0, 3900.0, 4000.0, 4100.0, 4200.0,
  2389. 4300.0, 4400.0, 4500.0, 4600.0, 4700.0, 4800.0]
  2390. py = [0.0004, 0.0, 0.0033, 0.006500000000000001, 0.0, 0.0,
  2391. 0.004399999999999999, 0.6862, 0.0, 0.0, 0.0,
  2392. 0.00019999999999997797, 0.0006000000000000449,
  2393. 0.024499999999999966, 0.006400000000000072,
  2394. 0.0043999999999999595, 0.019499999999999962,
  2395. 0.03770000000000007, 0.01759999999999995, 0.015199999999999991,
  2396. 0.018100000000000005, 0.04500000000000004, 0.0025999999999999357,
  2397. 0.0, 0.0041000000000001036, 0.005999999999999894,
  2398. 0.0042000000000000925, 0.0050000000000000044,
  2399. 0.0041999999999999815, 0.0004999999999999449,
  2400. 0.009199999999999986, 0.008200000000000096,
  2401. 0.0, 0.0, 0.0046999999999999265, 0.0019000000000000128,
  2402. 0.0006000000000000449, 0.02510000000000001, 0.0,
  2403. 0.007199999999999984, 0.0, 0.012699999999999934, 0.0, 0.0,
  2404. 0.008199999999999985, 0.005600000000000049, 0.0]
  2405. rv = stats.rv_discrete(values=(y, py))
  2406. # check the mean
  2407. assert_allclose(rv.expect(), rv.mean(), atol=1e-14)
  2408. assert_allclose(rv.expect(),
  2409. sum(v * w for v, w in zip(y, py)), atol=1e-14)
  2410. # also check the second moment
  2411. assert_allclose(rv.expect(lambda x: x**2),
  2412. sum(v**2 * w for v, w in zip(y, py)), atol=1e-14)
  2413. class TestSkewCauchy:
  2414. def test_cauchy(self):
  2415. x = np.linspace(-5, 5, 100)
  2416. assert_array_almost_equal(stats.skewcauchy.pdf(x, a=0),
  2417. stats.cauchy.pdf(x))
  2418. assert_array_almost_equal(stats.skewcauchy.cdf(x, a=0),
  2419. stats.cauchy.cdf(x))
  2420. assert_array_almost_equal(stats.skewcauchy.ppf(x, a=0),
  2421. stats.cauchy.ppf(x))
  2422. def test_skewcauchy_R(self):
  2423. # options(digits=16)
  2424. # library(sgt)
  2425. # # lmbda, x contain the values generated for a, x below
  2426. # lmbda <- c(0.0976270078546495, 0.430378732744839, 0.2055267521432877,
  2427. # 0.0897663659937937, -0.15269040132219, 0.2917882261333122,
  2428. # -0.12482557747462, 0.7835460015641595, 0.9273255210020589,
  2429. # -0.2331169623484446)
  2430. # x <- c(2.917250380826646, 0.2889491975290444, 0.6804456109393229,
  2431. # 4.25596638292661, -4.289639418021131, -4.1287070029845925,
  2432. # -4.797816025596743, 3.32619845547938, 2.7815675094985046,
  2433. # 3.700121482468191)
  2434. # pdf = dsgt(x, mu=0, lambda=lambda, sigma=1, q=1/2, mean.cent=FALSE,
  2435. # var.adj = sqrt(2))
  2436. # cdf = psgt(x, mu=0, lambda=lambda, sigma=1, q=1/2, mean.cent=FALSE,
  2437. # var.adj = sqrt(2))
  2438. # qsgt(cdf, mu=0, lambda=lambda, sigma=1, q=1/2, mean.cent=FALSE,
  2439. # var.adj = sqrt(2))
  2440. np.random.seed(0)
  2441. a = np.random.rand(10) * 2 - 1
  2442. x = np.random.rand(10) * 10 - 5
  2443. pdf = [0.039473975217333909, 0.305829714049903223, 0.24140158118994162,
  2444. 0.019585772402693054, 0.021436553695989482, 0.00909817103867518,
  2445. 0.01658423410016873, 0.071083288030394126, 0.103250045941454524,
  2446. 0.013110230778426242]
  2447. cdf = [0.87426677718213752, 0.37556468910780882, 0.59442096496538066,
  2448. 0.91304659850890202, 0.09631964100300605, 0.03829624330921733,
  2449. 0.08245240578402535, 0.72057062945510386, 0.62826415852515449,
  2450. 0.95011308463898292]
  2451. assert_allclose(stats.skewcauchy.pdf(x, a), pdf)
  2452. assert_allclose(stats.skewcauchy.cdf(x, a), cdf)
  2453. assert_allclose(stats.skewcauchy.ppf(cdf, a), x)
  2454. # Test data for TestSkewNorm.test_noncentral_moments()
  2455. # The expected noncentral moments were computed by Wolfram Alpha.
  2456. # In Wolfram Alpha, enter
  2457. # SkewNormalDistribution[0, 1, a] moment
  2458. # with `a` replaced by the desired shape parameter. In the results, there
  2459. # should be a table of the first four moments. Click on "More" to get more
  2460. # moments. The expected moments start with the first moment (order = 1).
  2461. _skewnorm_noncentral_moments = [
  2462. (2, [2*np.sqrt(2/(5*np.pi)),
  2463. 1,
  2464. 22/5*np.sqrt(2/(5*np.pi)),
  2465. 3,
  2466. 446/25*np.sqrt(2/(5*np.pi)),
  2467. 15,
  2468. 2682/25*np.sqrt(2/(5*np.pi)),
  2469. 105,
  2470. 107322/125*np.sqrt(2/(5*np.pi))]),
  2471. (0.1, [np.sqrt(2/(101*np.pi)),
  2472. 1,
  2473. 302/101*np.sqrt(2/(101*np.pi)),
  2474. 3,
  2475. (152008*np.sqrt(2/(101*np.pi)))/10201,
  2476. 15,
  2477. (107116848*np.sqrt(2/(101*np.pi)))/1030301,
  2478. 105,
  2479. (97050413184*np.sqrt(2/(101*np.pi)))/104060401]),
  2480. (-3, [-3/np.sqrt(5*np.pi),
  2481. 1,
  2482. -63/(10*np.sqrt(5*np.pi)),
  2483. 3,
  2484. -2529/(100*np.sqrt(5*np.pi)),
  2485. 15,
  2486. -30357/(200*np.sqrt(5*np.pi)),
  2487. 105,
  2488. -2428623/(2000*np.sqrt(5*np.pi)),
  2489. 945,
  2490. -242862867/(20000*np.sqrt(5*np.pi)),
  2491. 10395,
  2492. -29143550277/(200000*np.sqrt(5*np.pi)),
  2493. 135135]),
  2494. ]
  2495. class TestSkewNorm:
  2496. def setup_method(self):
  2497. self.rng = check_random_state(1234)
  2498. def test_normal(self):
  2499. # When the skewness is 0 the distribution is normal
  2500. x = np.linspace(-5, 5, 100)
  2501. assert_array_almost_equal(stats.skewnorm.pdf(x, a=0),
  2502. stats.norm.pdf(x))
  2503. def test_rvs(self):
  2504. shape = (3, 4, 5)
  2505. x = stats.skewnorm.rvs(a=0.75, size=shape, random_state=self.rng)
  2506. assert_equal(shape, x.shape)
  2507. x = stats.skewnorm.rvs(a=-3, size=shape, random_state=self.rng)
  2508. assert_equal(shape, x.shape)
  2509. def test_moments(self):
  2510. X = stats.skewnorm.rvs(a=4, size=int(1e6), loc=5, scale=2,
  2511. random_state=self.rng)
  2512. expected = [np.mean(X), np.var(X), stats.skew(X), stats.kurtosis(X)]
  2513. computed = stats.skewnorm.stats(a=4, loc=5, scale=2, moments='mvsk')
  2514. assert_array_almost_equal(computed, expected, decimal=2)
  2515. X = stats.skewnorm.rvs(a=-4, size=int(1e6), loc=5, scale=2,
  2516. random_state=self.rng)
  2517. expected = [np.mean(X), np.var(X), stats.skew(X), stats.kurtosis(X)]
  2518. computed = stats.skewnorm.stats(a=-4, loc=5, scale=2, moments='mvsk')
  2519. assert_array_almost_equal(computed, expected, decimal=2)
  2520. def test_cdf_large_x(self):
  2521. # Regression test for gh-7746.
  2522. # The x values are large enough that the closest 64 bit floating
  2523. # point representation of the exact CDF is 1.0.
  2524. p = stats.skewnorm.cdf([10, 20, 30], -1)
  2525. assert_allclose(p, np.ones(3), rtol=1e-14)
  2526. p = stats.skewnorm.cdf(25, 2.5)
  2527. assert_allclose(p, 1.0, rtol=1e-14)
  2528. def test_cdf_sf_small_values(self):
  2529. # Triples are [x, a, cdf(x, a)]. These values were computed
  2530. # using CDF[SkewNormDistribution[0, 1, a], x] in Wolfram Alpha.
  2531. cdfvals = [
  2532. [-8, 1, 3.870035046664392611e-31],
  2533. [-4, 2, 8.1298399188811398e-21],
  2534. [-2, 5, 1.55326826787106273e-26],
  2535. [-9, -1, 2.257176811907681295e-19],
  2536. [-10, -4, 1.523970604832105213e-23],
  2537. ]
  2538. for x, a, cdfval in cdfvals:
  2539. p = stats.skewnorm.cdf(x, a)
  2540. assert_allclose(p, cdfval, rtol=1e-8)
  2541. # For the skew normal distribution, sf(-x, -a) = cdf(x, a).
  2542. p = stats.skewnorm.sf(-x, -a)
  2543. assert_allclose(p, cdfval, rtol=1e-8)
  2544. @pytest.mark.parametrize('a, moments', _skewnorm_noncentral_moments)
  2545. def test_noncentral_moments(self, a, moments):
  2546. for order, expected in enumerate(moments, start=1):
  2547. mom = stats.skewnorm.moment(order, a)
  2548. assert_allclose(mom, expected, rtol=1e-14)
  2549. def test_fit(self):
  2550. rng = np.random.default_rng(4609813989115202851)
  2551. a, loc, scale = -2, 3.5, 0.5 # arbitrary, valid parameters
  2552. dist = stats.skewnorm(a, loc, scale)
  2553. rvs = dist.rvs(size=100, random_state=rng)
  2554. # test that MLE still honors guesses and fixed parameters
  2555. a2, loc2, scale2 = stats.skewnorm.fit(rvs, -1.5, floc=3)
  2556. a3, loc3, scale3 = stats.skewnorm.fit(rvs, -1.6, floc=3)
  2557. assert loc2 == loc3 == 3 # fixed parameter is respected
  2558. assert a2 != a3 # different guess -> (slightly) different outcome
  2559. # quality of fit is tested elsewhere
  2560. # test that MoM honors fixed parameters, accepts (but ignores) guesses
  2561. a4, loc4, scale4 = stats.skewnorm.fit(rvs, 3, fscale=3, method='mm')
  2562. assert scale4 == 3
  2563. # because scale was fixed, only the mean and skewness will be matched
  2564. dist4 = stats.skewnorm(a4, loc4, scale4)
  2565. res = dist4.stats(moments='ms')
  2566. ref = np.mean(rvs), stats.skew(rvs)
  2567. assert_allclose(res, ref)
  2568. # Test behavior when skew of data is beyond maximum of skewnorm
  2569. rvs = stats.pareto.rvs(1, size=100, random_state=rng)
  2570. # MLE still works
  2571. res = stats.skewnorm.fit(rvs)
  2572. assert np.all(np.isfinite(res))
  2573. # MoM fits variance and skewness
  2574. a5, loc5, scale5 = stats.skewnorm.fit(rvs, method='mm')
  2575. assert np.isinf(a5)
  2576. # distribution infrastruction doesn't allow infinite shape parameters
  2577. # into _stats; it just bypasses it and produces NaNs. Calculate
  2578. # moments manually.
  2579. m, v = np.mean(rvs), np.var(rvs)
  2580. assert_allclose(m, loc5 + scale5 * np.sqrt(2/np.pi))
  2581. assert_allclose(v, scale5**2 * (1 - 2 / np.pi))
  2582. class TestExpon:
  2583. def test_zero(self):
  2584. assert_equal(stats.expon.pdf(0), 1)
  2585. def test_tail(self): # Regression test for ticket 807
  2586. assert_equal(stats.expon.cdf(1e-18), 1e-18)
  2587. assert_equal(stats.expon.isf(stats.expon.sf(40)), 40)
  2588. def test_nan_raises_error(self):
  2589. # see gh-issue 10300
  2590. x = np.array([1.6483, 2.7169, 2.4667, 1.1791, 3.5433, np.nan])
  2591. assert_raises(ValueError, stats.expon.fit, x)
  2592. def test_inf_raises_error(self):
  2593. # see gh-issue 10300
  2594. x = np.array([1.6483, 2.7169, 2.4667, 1.1791, 3.5433, np.inf])
  2595. assert_raises(ValueError, stats.expon.fit, x)
  2596. class TestNorm:
  2597. def test_nan_raises_error(self):
  2598. # see gh-issue 10300
  2599. x = np.array([1.6483, 2.7169, 2.4667, 1.1791, 3.5433, np.nan])
  2600. assert_raises(ValueError, stats.norm.fit, x)
  2601. def test_inf_raises_error(self):
  2602. # see gh-issue 10300
  2603. x = np.array([1.6483, 2.7169, 2.4667, 1.1791, 3.5433, np.inf])
  2604. assert_raises(ValueError, stats.norm.fit, x)
  2605. def test_bad_keyword_arg(self):
  2606. x = [1, 2, 3]
  2607. assert_raises(TypeError, stats.norm.fit, x, plate="shrimp")
  2608. class TestUniform:
  2609. """gh-10300"""
  2610. def test_nan_raises_error(self):
  2611. # see gh-issue 10300
  2612. x = np.array([1.6483, 2.7169, 2.4667, 1.1791, 3.5433, np.nan])
  2613. assert_raises(ValueError, stats.uniform.fit, x)
  2614. def test_inf_raises_error(self):
  2615. # see gh-issue 10300
  2616. x = np.array([1.6483, 2.7169, 2.4667, 1.1791, 3.5433, np.inf])
  2617. assert_raises(ValueError, stats.uniform.fit, x)
  2618. class TestExponNorm:
  2619. def test_moments(self):
  2620. # Some moment test cases based on non-loc/scaled formula
  2621. def get_moms(lam, sig, mu):
  2622. # See wikipedia for these formulae
  2623. # where it is listed as an exponentially modified gaussian
  2624. opK2 = 1.0 + 1 / (lam*sig)**2
  2625. exp_skew = 2 / (lam * sig)**3 * opK2**(-1.5)
  2626. exp_kurt = 6.0 * (1 + (lam * sig)**2)**(-2)
  2627. return [mu + 1/lam, sig*sig + 1.0/(lam*lam), exp_skew, exp_kurt]
  2628. mu, sig, lam = 0, 1, 1
  2629. K = 1.0 / (lam * sig)
  2630. sts = stats.exponnorm.stats(K, loc=mu, scale=sig, moments='mvsk')
  2631. assert_almost_equal(sts, get_moms(lam, sig, mu))
  2632. mu, sig, lam = -3, 2, 0.1
  2633. K = 1.0 / (lam * sig)
  2634. sts = stats.exponnorm.stats(K, loc=mu, scale=sig, moments='mvsk')
  2635. assert_almost_equal(sts, get_moms(lam, sig, mu))
  2636. mu, sig, lam = 0, 3, 1
  2637. K = 1.0 / (lam * sig)
  2638. sts = stats.exponnorm.stats(K, loc=mu, scale=sig, moments='mvsk')
  2639. assert_almost_equal(sts, get_moms(lam, sig, mu))
  2640. mu, sig, lam = -5, 11, 3.5
  2641. K = 1.0 / (lam * sig)
  2642. sts = stats.exponnorm.stats(K, loc=mu, scale=sig, moments='mvsk')
  2643. assert_almost_equal(sts, get_moms(lam, sig, mu))
  2644. def test_nan_raises_error(self):
  2645. # see gh-issue 10300
  2646. x = np.array([1.6483, 2.7169, 2.4667, 1.1791, 3.5433, np.nan])
  2647. assert_raises(ValueError, stats.exponnorm.fit, x, floc=0, fscale=1)
  2648. def test_inf_raises_error(self):
  2649. # see gh-issue 10300
  2650. x = np.array([1.6483, 2.7169, 2.4667, 1.1791, 3.5433, np.inf])
  2651. assert_raises(ValueError, stats.exponnorm.fit, x, floc=0, fscale=1)
  2652. def test_extremes_x(self):
  2653. # Test for extreme values against overflows
  2654. assert_almost_equal(stats.exponnorm.pdf(-900, 1), 0.0)
  2655. assert_almost_equal(stats.exponnorm.pdf(+900, 1), 0.0)
  2656. assert_almost_equal(stats.exponnorm.pdf(-900, 0.01), 0.0)
  2657. assert_almost_equal(stats.exponnorm.pdf(+900, 0.01), 0.0)
  2658. # Expected values for the PDF were computed with mpmath, with
  2659. # the following function, and with mpmath.mp.dps = 50.
  2660. #
  2661. # def exponnorm_stdpdf(x, K):
  2662. # x = mpmath.mpf(x)
  2663. # K = mpmath.mpf(K)
  2664. # t1 = mpmath.exp(1/(2*K**2) - x/K)
  2665. # erfcarg = -(x - 1/K)/mpmath.sqrt(2)
  2666. # t2 = mpmath.erfc(erfcarg)
  2667. # return t1 * t2 / (2*K)
  2668. #
  2669. @pytest.mark.parametrize('x, K, expected',
  2670. [(20, 0.01, 6.90010764753618e-88),
  2671. (1, 0.01, 0.24438994313247364),
  2672. (-1, 0.01, 0.23955149623472075),
  2673. (-20, 0.01, 4.6004708690125477e-88),
  2674. (10, 1, 7.48518298877006e-05),
  2675. (10, 10000, 9.990005048283775e-05)])
  2676. def test_std_pdf(self, x, K, expected):
  2677. assert_allclose(stats.exponnorm.pdf(x, K), expected, rtol=5e-12)
  2678. # Expected values for the CDF were computed with mpmath using
  2679. # the following function and with mpmath.mp.dps = 60:
  2680. #
  2681. # def mp_exponnorm_cdf(x, K, loc=0, scale=1):
  2682. # x = mpmath.mpf(x)
  2683. # K = mpmath.mpf(K)
  2684. # loc = mpmath.mpf(loc)
  2685. # scale = mpmath.mpf(scale)
  2686. # z = (x - loc)/scale
  2687. # return (mpmath.ncdf(z)
  2688. # - mpmath.exp((1/(2*K) - z)/K)*mpmath.ncdf(z - 1/K))
  2689. #
  2690. @pytest.mark.parametrize('x, K, scale, expected',
  2691. [[0, 0.01, 1, 0.4960109760186432],
  2692. [-5, 0.005, 1, 2.7939945412195734e-07],
  2693. [-1e4, 0.01, 100, 0.0],
  2694. [-1e4, 0.01, 1000, 6.920401854427357e-24],
  2695. [5, 0.001, 1, 0.9999997118542392]])
  2696. def test_cdf_small_K(self, x, K, scale, expected):
  2697. p = stats.exponnorm.cdf(x, K, scale=scale)
  2698. if expected == 0.0:
  2699. assert p == 0.0
  2700. else:
  2701. assert_allclose(p, expected, rtol=1e-13)
  2702. # Expected values for the SF were computed with mpmath using
  2703. # the following function and with mpmath.mp.dps = 60:
  2704. #
  2705. # def mp_exponnorm_sf(x, K, loc=0, scale=1):
  2706. # x = mpmath.mpf(x)
  2707. # K = mpmath.mpf(K)
  2708. # loc = mpmath.mpf(loc)
  2709. # scale = mpmath.mpf(scale)
  2710. # z = (x - loc)/scale
  2711. # return (mpmath.ncdf(-z)
  2712. # + mpmath.exp((1/(2*K) - z)/K)*mpmath.ncdf(z - 1/K))
  2713. #
  2714. @pytest.mark.parametrize('x, K, scale, expected',
  2715. [[10, 0.01, 1, 8.474702916146657e-24],
  2716. [2, 0.005, 1, 0.02302280664231312],
  2717. [5, 0.005, 0.5, 8.024820681931086e-24],
  2718. [10, 0.005, 0.5, 3.0603340062892486e-89],
  2719. [20, 0.005, 0.5, 0.0],
  2720. [-3, 0.001, 1, 0.9986545205566117]])
  2721. def test_sf_small_K(self, x, K, scale, expected):
  2722. p = stats.exponnorm.sf(x, K, scale=scale)
  2723. if expected == 0.0:
  2724. assert p == 0.0
  2725. else:
  2726. assert_allclose(p, expected, rtol=5e-13)
  2727. class TestGenExpon:
  2728. def test_pdf_unity_area(self):
  2729. from scipy.integrate import simps
  2730. # PDF should integrate to one
  2731. p = stats.genexpon.pdf(numpy.arange(0, 10, 0.01), 0.5, 0.5, 2.0)
  2732. assert_almost_equal(simps(p, dx=0.01), 1, 1)
  2733. def test_cdf_bounds(self):
  2734. # CDF should always be positive
  2735. cdf = stats.genexpon.cdf(numpy.arange(0, 10, 0.01), 0.5, 0.5, 2.0)
  2736. assert_(numpy.all((0 <= cdf) & (cdf <= 1)))
  2737. def test_sf_tail(self):
  2738. # Expected value computed with mpmath. This script
  2739. # import mpmath
  2740. # mpmath.mp.dps = 80
  2741. # x = mpmath.mpf('15.0')
  2742. # a = mpmath.mpf('1.0')
  2743. # b = mpmath.mpf('2.0')
  2744. # c = mpmath.mpf('1.5')
  2745. # print(float(mpmath.exp((-a-b)*x + (b/c)*-mpmath.expm1(-c*x))))
  2746. # prints
  2747. # 1.0859444834514553e-19
  2748. s = stats.genexpon.sf(15, 1, 2, 1.5)
  2749. assert_allclose(s, 1.0859444834514553e-19, rtol=1e-13)
  2750. class TestExponpow:
  2751. def test_tail(self):
  2752. assert_almost_equal(stats.exponpow.cdf(1e-10, 2.), 1e-20)
  2753. assert_almost_equal(stats.exponpow.isf(stats.exponpow.sf(5, .8), .8),
  2754. 5)
  2755. class TestSkellam:
  2756. def test_pmf(self):
  2757. # comparison to R
  2758. k = numpy.arange(-10, 15)
  2759. mu1, mu2 = 10, 5
  2760. skpmfR = numpy.array(
  2761. [4.2254582961926893e-005, 1.1404838449648488e-004,
  2762. 2.8979625801752660e-004, 6.9177078182101231e-004,
  2763. 1.5480716105844708e-003, 3.2412274963433889e-003,
  2764. 6.3373707175123292e-003, 1.1552351566696643e-002,
  2765. 1.9606152375042644e-002, 3.0947164083410337e-002,
  2766. 4.5401737566767360e-002, 6.1894328166820688e-002,
  2767. 7.8424609500170578e-002, 9.2418812533573133e-002,
  2768. 1.0139793148019728e-001, 1.0371927988298846e-001,
  2769. 9.9076583077406091e-002, 8.8546660073089561e-002,
  2770. 7.4187842052486810e-002, 5.8392772862200251e-002,
  2771. 4.3268692953013159e-002, 3.0248159818374226e-002,
  2772. 1.9991434305603021e-002, 1.2516877303301180e-002,
  2773. 7.4389876226229707e-003])
  2774. assert_almost_equal(stats.skellam.pmf(k, mu1, mu2), skpmfR, decimal=15)
  2775. @pytest.mark.filterwarnings('ignore::RuntimeWarning')
  2776. def test_cdf(self):
  2777. # comparison to R, only 5 decimals
  2778. k = numpy.arange(-10, 15)
  2779. mu1, mu2 = 10, 5
  2780. skcdfR = numpy.array(
  2781. [6.4061475386192104e-005, 1.7810985988267694e-004,
  2782. 4.6790611790020336e-004, 1.1596768997212152e-003,
  2783. 2.7077485103056847e-003, 5.9489760066490718e-003,
  2784. 1.2286346724161398e-002, 2.3838698290858034e-002,
  2785. 4.3444850665900668e-002, 7.4392014749310995e-002,
  2786. 1.1979375231607835e-001, 1.8168808048289900e-001,
  2787. 2.6011268998306952e-001, 3.5253150251664261e-001,
  2788. 4.5392943399683988e-001, 5.5764871387982828e-001,
  2789. 6.5672529695723436e-001, 7.4527195703032389e-001,
  2790. 8.1945979908281064e-001, 8.7785257194501087e-001,
  2791. 9.2112126489802404e-001, 9.5136942471639818e-001,
  2792. 9.7136085902200120e-001, 9.8387773632530240e-001,
  2793. 9.9131672394792536e-001])
  2794. assert_almost_equal(stats.skellam.cdf(k, mu1, mu2), skcdfR, decimal=5)
  2795. class TestLognorm:
  2796. def test_pdf(self):
  2797. # Regression test for Ticket #1471: avoid nan with 0/0 situation
  2798. # Also make sure there are no warnings at x=0, cf gh-5202
  2799. with warnings.catch_warnings():
  2800. warnings.simplefilter('error', RuntimeWarning)
  2801. pdf = stats.lognorm.pdf([0, 0.5, 1], 1)
  2802. assert_array_almost_equal(pdf, [0.0, 0.62749608, 0.39894228])
  2803. def test_logcdf(self):
  2804. # Regression test for gh-5940: sf et al would underflow too early
  2805. x2, mu, sigma = 201.68, 195, 0.149
  2806. assert_allclose(stats.lognorm.sf(x2-mu, s=sigma),
  2807. stats.norm.sf(np.log(x2-mu)/sigma))
  2808. assert_allclose(stats.lognorm.logsf(x2-mu, s=sigma),
  2809. stats.norm.logsf(np.log(x2-mu)/sigma))
  2810. class TestBeta:
  2811. def test_logpdf(self):
  2812. # Regression test for Ticket #1326: avoid nan with 0*log(0) situation
  2813. logpdf = stats.beta.logpdf(0, 1, 0.5)
  2814. assert_almost_equal(logpdf, -0.69314718056)
  2815. logpdf = stats.beta.logpdf(0, 0.5, 1)
  2816. assert_almost_equal(logpdf, np.inf)
  2817. def test_logpdf_ticket_1866(self):
  2818. alpha, beta = 267, 1472
  2819. x = np.array([0.2, 0.5, 0.6])
  2820. b = stats.beta(alpha, beta)
  2821. assert_allclose(b.logpdf(x).sum(), -1201.699061824062)
  2822. assert_allclose(b.pdf(x), np.exp(b.logpdf(x)))
  2823. def test_fit_bad_keyword_args(self):
  2824. x = [0.1, 0.5, 0.6]
  2825. assert_raises(TypeError, stats.beta.fit, x, floc=0, fscale=1,
  2826. plate="shrimp")
  2827. def test_fit_duplicated_fixed_parameter(self):
  2828. # At most one of 'f0', 'fa' or 'fix_a' can be given to the fit method.
  2829. # More than one raises a ValueError.
  2830. x = [0.1, 0.5, 0.6]
  2831. assert_raises(ValueError, stats.beta.fit, x, fa=0.5, fix_a=0.5)
  2832. @pytest.mark.skipif(MACOS_INTEL, reason="Overflow, see gh-14901")
  2833. def test_issue_12635(self):
  2834. # Confirm that Boost's beta distribution resolves gh-12635.
  2835. # Check against R:
  2836. # options(digits=16)
  2837. # p = 0.9999999999997369
  2838. # a = 75.0
  2839. # b = 66334470.0
  2840. # print(qbeta(p, a, b))
  2841. p, a, b = 0.9999999999997369, 75.0, 66334470.0
  2842. assert_allclose(stats.beta.ppf(p, a, b), 2.343620802982393e-06)
  2843. @pytest.mark.skipif(MACOS_INTEL, reason="Overflow, see gh-14901")
  2844. def test_issue_12794(self):
  2845. # Confirm that Boost's beta distribution resolves gh-12794.
  2846. # Check against R.
  2847. # options(digits=16)
  2848. # p = 1e-11
  2849. # count_list = c(10,100,1000)
  2850. # print(qbeta(1-p, count_list + 1, 100000 - count_list))
  2851. inv_R = np.array([0.0004944464889611935,
  2852. 0.0018360586912635726,
  2853. 0.0122663919942518351])
  2854. count_list = np.array([10, 100, 1000])
  2855. p = 1e-11
  2856. inv = stats.beta.isf(p, count_list + 1, 100000 - count_list)
  2857. assert_allclose(inv, inv_R)
  2858. res = stats.beta.sf(inv, count_list + 1, 100000 - count_list)
  2859. assert_allclose(res, p)
  2860. @pytest.mark.skipif(MACOS_INTEL, reason="Overflow, see gh-14901")
  2861. def test_issue_12796(self):
  2862. # Confirm that Boost's beta distribution succeeds in the case
  2863. # of gh-12796
  2864. alpha_2 = 5e-6
  2865. count_ = np.arange(1, 20)
  2866. nobs = 100000
  2867. q, a, b = 1 - alpha_2, count_ + 1, nobs - count_
  2868. inv = stats.beta.ppf(q, a, b)
  2869. res = stats.beta.cdf(inv, a, b)
  2870. assert_allclose(res, 1 - alpha_2)
  2871. def test_endpoints(self):
  2872. # Confirm that boost's beta distribution returns inf at x=1
  2873. # when b<1
  2874. a, b = 1, 0.5
  2875. assert_equal(stats.beta.pdf(1, a, b), np.inf)
  2876. # Confirm that boost's beta distribution returns inf at x=0
  2877. # when a<1
  2878. a, b = 0.2, 3
  2879. assert_equal(stats.beta.pdf(0, a, b), np.inf)
  2880. @pytest.mark.xfail(IS_PYPY, reason="Does not convert boost warning")
  2881. def test_boost_eval_issue_14606(self):
  2882. q, a, b = 0.995, 1.0e11, 1.0e13
  2883. with pytest.warns(RuntimeWarning):
  2884. stats.beta.ppf(q, a, b)
  2885. @pytest.mark.parametrize('method', [stats.beta.ppf, stats.beta.isf])
  2886. @pytest.mark.parametrize('a, b', [(1e-310, 12.5), (12.5, 1e-310)])
  2887. def test_beta_ppf_with_subnormal_a_b(self, method, a, b):
  2888. # Regression test for gh-17444: beta.ppf(p, a, b) and beta.isf(p, a, b)
  2889. # would result in a segmentation fault if either a or b was subnormal.
  2890. p = 0.9
  2891. # Depending on the version of Boost that we have vendored and
  2892. # our setting of the Boost double promotion policy, the call
  2893. # `stats.beta.ppf(p, a, b)` might raise an OverflowError or
  2894. # return a value. We'll accept either behavior (and not care about
  2895. # the value), because our goal here is to verify that the call does
  2896. # not trigger a segmentation fault.
  2897. try:
  2898. method(p, a, b)
  2899. except OverflowError:
  2900. # The OverflowError exception occurs with Boost 1.80 or earlier
  2901. # when Boost's double promotion policy is false; see
  2902. # https://github.com/boostorg/math/issues/882
  2903. # and
  2904. # https://github.com/boostorg/math/pull/883
  2905. # Once we have vendored the fixed version of Boost, we can drop
  2906. # this try-except wrapper and just call the function.
  2907. pass
  2908. class TestBetaPrime:
  2909. def test_logpdf(self):
  2910. alpha, beta = 267, 1472
  2911. x = np.array([0.2, 0.5, 0.6])
  2912. b = stats.betaprime(alpha, beta)
  2913. assert_(np.isfinite(b.logpdf(x)).all())
  2914. assert_allclose(b.pdf(x), np.exp(b.logpdf(x)))
  2915. def test_cdf(self):
  2916. # regression test for gh-4030: Implementation of
  2917. # scipy.stats.betaprime.cdf()
  2918. x = stats.betaprime.cdf(0, 0.2, 0.3)
  2919. assert_equal(x, 0.0)
  2920. alpha, beta = 267, 1472
  2921. x = np.array([0.2, 0.5, 0.6])
  2922. cdfs = stats.betaprime.cdf(x, alpha, beta)
  2923. assert_(np.isfinite(cdfs).all())
  2924. # check the new cdf implementation vs generic one:
  2925. gen_cdf = stats.rv_continuous._cdf_single
  2926. cdfs_g = [gen_cdf(stats.betaprime, val, alpha, beta) for val in x]
  2927. assert_allclose(cdfs, cdfs_g, atol=0, rtol=2e-12)
  2928. class TestGamma:
  2929. def test_pdf(self):
  2930. # a few test cases to compare with R
  2931. pdf = stats.gamma.pdf(90, 394, scale=1./5)
  2932. assert_almost_equal(pdf, 0.002312341)
  2933. pdf = stats.gamma.pdf(3, 10, scale=1./5)
  2934. assert_almost_equal(pdf, 0.1620358)
  2935. def test_logpdf(self):
  2936. # Regression test for Ticket #1326: cornercase avoid nan with 0*log(0)
  2937. # situation
  2938. logpdf = stats.gamma.logpdf(0, 1)
  2939. assert_almost_equal(logpdf, 0)
  2940. def test_fit_bad_keyword_args(self):
  2941. x = [0.1, 0.5, 0.6]
  2942. assert_raises(TypeError, stats.gamma.fit, x, floc=0, plate="shrimp")
  2943. def test_isf(self):
  2944. # Test cases for when the probability is very small. See gh-13664.
  2945. # The expected values can be checked with mpmath. With mpmath,
  2946. # the survival function sf(x, k) can be computed as
  2947. #
  2948. # mpmath.gammainc(k, x, mpmath.inf, regularized=True)
  2949. #
  2950. # Here we have:
  2951. #
  2952. # >>> mpmath.mp.dps = 60
  2953. # >>> float(mpmath.gammainc(1, 39.14394658089878, mpmath.inf,
  2954. # ... regularized=True))
  2955. # 9.99999999999999e-18
  2956. # >>> float(mpmath.gammainc(100, 330.6557590436547, mpmath.inf,
  2957. # regularized=True))
  2958. # 1.000000000000028e-50
  2959. #
  2960. assert np.isclose(stats.gamma.isf(1e-17, 1),
  2961. 39.14394658089878, atol=1e-14)
  2962. assert np.isclose(stats.gamma.isf(1e-50, 100),
  2963. 330.6557590436547, atol=1e-13)
  2964. class TestChi2:
  2965. # regression tests after precision improvements, ticket:1041, not verified
  2966. def test_precision(self):
  2967. assert_almost_equal(stats.chi2.pdf(1000, 1000), 8.919133934753128e-003,
  2968. decimal=14)
  2969. assert_almost_equal(stats.chi2.pdf(100, 100), 0.028162503162596778,
  2970. decimal=14)
  2971. def test_ppf(self):
  2972. # Expected values computed with mpmath.
  2973. df = 4.8
  2974. x = stats.chi2.ppf(2e-47, df)
  2975. assert_allclose(x, 1.098472479575179840604902808e-19, rtol=1e-10)
  2976. x = stats.chi2.ppf(0.5, df)
  2977. assert_allclose(x, 4.15231407598589358660093156, rtol=1e-10)
  2978. df = 13
  2979. x = stats.chi2.ppf(2e-77, df)
  2980. assert_allclose(x, 1.0106330688195199050507943e-11, rtol=1e-10)
  2981. x = stats.chi2.ppf(0.1, df)
  2982. assert_allclose(x, 7.041504580095461859307179763, rtol=1e-10)
  2983. class TestGumbelL:
  2984. # gh-6228
  2985. def test_cdf_ppf(self):
  2986. x = np.linspace(-100, -4)
  2987. y = stats.gumbel_l.cdf(x)
  2988. xx = stats.gumbel_l.ppf(y)
  2989. assert_allclose(x, xx)
  2990. def test_logcdf_logsf(self):
  2991. x = np.linspace(-100, -4)
  2992. y = stats.gumbel_l.logcdf(x)
  2993. z = stats.gumbel_l.logsf(x)
  2994. u = np.exp(y)
  2995. v = -special.expm1(z)
  2996. assert_allclose(u, v)
  2997. def test_sf_isf(self):
  2998. x = np.linspace(-20, 5)
  2999. y = stats.gumbel_l.sf(x)
  3000. xx = stats.gumbel_l.isf(y)
  3001. assert_allclose(x, xx)
  3002. @pytest.mark.parametrize('loc', [-1, 1])
  3003. def test_fit_fixed_param(self, loc):
  3004. # ensure fixed location is correctly reflected from `gumbel_r.fit`
  3005. # See comments at end of gh-12737.
  3006. data = stats.gumbel_l.rvs(size=100, loc=loc)
  3007. fitted_loc, _ = stats.gumbel_l.fit(data, floc=loc)
  3008. assert_equal(fitted_loc, loc)
  3009. class TestGumbelR:
  3010. def test_sf(self):
  3011. # Expected value computed with mpmath:
  3012. # >>> import mpmath
  3013. # >>> mpmath.mp.dps = 40
  3014. # >>> float(mpmath.mp.one - mpmath.exp(-mpmath.exp(-50)))
  3015. # 1.9287498479639178e-22
  3016. assert_allclose(stats.gumbel_r.sf(50), 1.9287498479639178e-22,
  3017. rtol=1e-14)
  3018. def test_isf(self):
  3019. # Expected value computed with mpmath:
  3020. # >>> import mpmath
  3021. # >>> mpmath.mp.dps = 40
  3022. # >>> float(-mpmath.log(-mpmath.log(mpmath.mp.one - 1e-17)))
  3023. # 39.14394658089878
  3024. assert_allclose(stats.gumbel_r.isf(1e-17), 39.14394658089878,
  3025. rtol=1e-14)
  3026. class TestLevyStable:
  3027. @pytest.fixture
  3028. def nolan_pdf_sample_data(self):
  3029. """Sample data points for pdf computed with Nolan's stablec
  3030. See - http://fs2.american.edu/jpnolan/www/stable/stable.html
  3031. There's a known limitation of Nolan's executable for alpha < 0.2.
  3032. The data table loaded below is generated from Nolan's stablec
  3033. with the following parameter space:
  3034. alpha = 0.1, 0.2, ..., 2.0
  3035. beta = -1.0, -0.9, ..., 1.0
  3036. p = 0.01, 0.05, 0.1, 0.25, 0.35, 0.5,
  3037. and the equivalent for the right tail
  3038. Typically inputs for stablec:
  3039. stablec.exe <<
  3040. 1 # pdf
  3041. 1 # Nolan S equivalent to S0 in scipy
  3042. .25,2,.25 # alpha
  3043. -1,-1,0 # beta
  3044. -10,10,1 # x
  3045. 1,0 # gamma, delta
  3046. 2 # output file
  3047. """
  3048. data = np.load(
  3049. Path(__file__).parent /
  3050. 'data/levy_stable/stable-Z1-pdf-sample-data.npy'
  3051. )
  3052. data = np.core.records.fromarrays(data.T, names='x,p,alpha,beta,pct')
  3053. return data
  3054. @pytest.fixture
  3055. def nolan_cdf_sample_data(self):
  3056. """Sample data points for cdf computed with Nolan's stablec
  3057. See - http://fs2.american.edu/jpnolan/www/stable/stable.html
  3058. There's a known limitation of Nolan's executable for alpha < 0.2.
  3059. The data table loaded below is generated from Nolan's stablec
  3060. with the following parameter space:
  3061. alpha = 0.1, 0.2, ..., 2.0
  3062. beta = -1.0, -0.9, ..., 1.0
  3063. p = 0.01, 0.05, 0.1, 0.25, 0.35, 0.5,
  3064. and the equivalent for the right tail
  3065. Ideally, Nolan's output for CDF values should match the percentile
  3066. from where they have been sampled from. Even more so as we extract
  3067. percentile x positions from stablec too. However, we note at places
  3068. Nolan's stablec will produce absolute errors in order of 1e-5. We
  3069. compare against his calculations here. In future, once we less
  3070. reliant on Nolan's paper we might switch to comparing directly at
  3071. percentiles (those x values being produced from some alternative
  3072. means).
  3073. Typically inputs for stablec:
  3074. stablec.exe <<
  3075. 2 # cdf
  3076. 1 # Nolan S equivalent to S0 in scipy
  3077. .25,2,.25 # alpha
  3078. -1,-1,0 # beta
  3079. -10,10,1 # x
  3080. 1,0 # gamma, delta
  3081. 2 # output file
  3082. """
  3083. data = np.load(
  3084. Path(__file__).parent /
  3085. 'data/levy_stable/stable-Z1-cdf-sample-data.npy'
  3086. )
  3087. data = np.core.records.fromarrays(data.T, names='x,p,alpha,beta,pct')
  3088. return data
  3089. @pytest.fixture
  3090. def nolan_loc_scale_sample_data(self):
  3091. """Sample data where loc, scale are different from 0, 1
  3092. Data extracted in similar way to pdf/cdf above using
  3093. Nolan's stablec but set to an arbitrary location scale of
  3094. (2, 3) for various important parameters alpha, beta and for
  3095. parameterisations S0 and S1.
  3096. """
  3097. data = np.load(
  3098. Path(__file__).parent /
  3099. 'data/levy_stable/stable-loc-scale-sample-data.npy'
  3100. )
  3101. return data
  3102. @pytest.mark.parametrize(
  3103. "sample_size", [
  3104. pytest.param(50), pytest.param(1500, marks=pytest.mark.slow)
  3105. ]
  3106. )
  3107. @pytest.mark.parametrize("parameterization", ["S0", "S1"])
  3108. @pytest.mark.parametrize(
  3109. "alpha,beta", [(1.0, 0), (1.0, -0.5), (1.5, 0), (1.9, 0.5)]
  3110. )
  3111. @pytest.mark.parametrize("gamma,delta", [(1, 0), (3, 2)])
  3112. def test_rvs(
  3113. self,
  3114. parameterization,
  3115. alpha,
  3116. beta,
  3117. gamma,
  3118. delta,
  3119. sample_size,
  3120. ):
  3121. stats.levy_stable.parameterization = parameterization
  3122. ls = stats.levy_stable(
  3123. alpha=alpha, beta=beta, scale=gamma, loc=delta
  3124. )
  3125. _, p = stats.kstest(
  3126. ls.rvs(size=sample_size, random_state=1234), ls.cdf
  3127. )
  3128. assert p > 0.05
  3129. @pytest.mark.slow
  3130. @pytest.mark.parametrize('beta', [0.5, 1])
  3131. def test_rvs_alpha1(self, beta):
  3132. """Additional test cases for rvs for alpha equal to 1."""
  3133. np.random.seed(987654321)
  3134. alpha = 1.0
  3135. loc = 0.5
  3136. scale = 1.5
  3137. x = stats.levy_stable.rvs(alpha, beta, loc=loc, scale=scale,
  3138. size=5000)
  3139. stat, p = stats.kstest(x, 'levy_stable',
  3140. args=(alpha, beta, loc, scale))
  3141. assert p > 0.01
  3142. def test_fit(self):
  3143. # construct data to have percentiles that match
  3144. # example in McCulloch 1986.
  3145. x = [
  3146. -.05413, -.05413, 0., 0., 0., 0., .00533, .00533, .00533, .00533,
  3147. .00533, .03354, .03354, .03354, .03354, .03354, .05309, .05309,
  3148. .05309, .05309, .05309
  3149. ]
  3150. alpha1, beta1, loc1, scale1 = stats.levy_stable._fitstart(x)
  3151. assert_allclose(alpha1, 1.48, rtol=0, atol=0.01)
  3152. assert_almost_equal(beta1, -.22, 2)
  3153. assert_almost_equal(scale1, 0.01717, 4)
  3154. assert_almost_equal(
  3155. loc1, 0.00233, 2
  3156. ) # to 2 dps due to rounding error in McCulloch86
  3157. # cover alpha=2 scenario
  3158. x2 = x + [.05309, .05309, .05309, .05309, .05309]
  3159. alpha2, beta2, loc2, scale2 = stats.levy_stable._fitstart(x2)
  3160. assert_equal(alpha2, 2)
  3161. assert_equal(beta2, -1)
  3162. assert_almost_equal(scale2, .02503, 4)
  3163. assert_almost_equal(loc2, .03354, 4)
  3164. @pytest.mark.xfail(reason="Unknown problem with fitstart.")
  3165. @pytest.mark.parametrize(
  3166. "alpha,beta,delta,gamma",
  3167. [
  3168. (1.5, 0.4, 2, 3),
  3169. (1.0, 0.4, 2, 3),
  3170. ]
  3171. )
  3172. @pytest.mark.parametrize(
  3173. "parametrization", ["S0", "S1"]
  3174. )
  3175. def test_fit_rvs(self, alpha, beta, delta, gamma, parametrization):
  3176. """Test that fit agrees with rvs for each parametrization."""
  3177. stats.levy_stable.parametrization = parametrization
  3178. data = stats.levy_stable.rvs(
  3179. alpha, beta, loc=delta, scale=gamma, size=10000, random_state=1234
  3180. )
  3181. fit = stats.levy_stable._fitstart(data)
  3182. alpha_obs, beta_obs, delta_obs, gamma_obs = fit
  3183. assert_allclose(
  3184. [alpha, beta, delta, gamma],
  3185. [alpha_obs, beta_obs, delta_obs, gamma_obs],
  3186. rtol=0.01,
  3187. )
  3188. def test_fit_beta_flip(self):
  3189. # Confirm that sign of beta affects loc, not alpha or scale.
  3190. x = np.array([1, 1, 3, 3, 10, 10, 10, 30, 30, 100, 100])
  3191. alpha1, beta1, loc1, scale1 = stats.levy_stable._fitstart(x)
  3192. alpha2, beta2, loc2, scale2 = stats.levy_stable._fitstart(-x)
  3193. assert_equal(beta1, 1)
  3194. assert loc1 != 0
  3195. assert_almost_equal(alpha2, alpha1)
  3196. assert_almost_equal(beta2, -beta1)
  3197. assert_almost_equal(loc2, -loc1)
  3198. assert_almost_equal(scale2, scale1)
  3199. def test_fit_delta_shift(self):
  3200. # Confirm that loc slides up and down if data shifts.
  3201. SHIFT = 1
  3202. x = np.array([1, 1, 3, 3, 10, 10, 10, 30, 30, 100, 100])
  3203. alpha1, beta1, loc1, scale1 = stats.levy_stable._fitstart(-x)
  3204. alpha2, beta2, loc2, scale2 = stats.levy_stable._fitstart(-x + SHIFT)
  3205. assert_almost_equal(alpha2, alpha1)
  3206. assert_almost_equal(beta2, beta1)
  3207. assert_almost_equal(loc2, loc1 + SHIFT)
  3208. assert_almost_equal(scale2, scale1)
  3209. def test_fit_loc_extrap(self):
  3210. # Confirm that loc goes out of sample for alpha close to 1.
  3211. x = [1, 1, 3, 3, 10, 10, 10, 30, 30, 140, 140]
  3212. alpha1, beta1, loc1, scale1 = stats.levy_stable._fitstart(x)
  3213. assert alpha1 < 1, f"Expected alpha < 1, got {alpha1}"
  3214. assert loc1 < min(x), f"Expected loc < {min(x)}, got {loc1}"
  3215. x2 = [1, 1, 3, 3, 10, 10, 10, 30, 30, 130, 130]
  3216. alpha2, beta2, loc2, scale2 = stats.levy_stable._fitstart(x2)
  3217. assert alpha2 > 1, f"Expected alpha > 1, got {alpha2}"
  3218. assert loc2 > max(x2), f"Expected loc > {max(x2)}, got {loc2}"
  3219. @pytest.mark.parametrize(
  3220. "pct_range,alpha_range,beta_range", [
  3221. pytest.param(
  3222. [.01, .5, .99],
  3223. [.1, 1, 2],
  3224. [-1, 0, .8],
  3225. ),
  3226. pytest.param(
  3227. [.01, .05, .5, .95, .99],
  3228. [.1, .5, 1, 1.5, 2],
  3229. [-.9, -.5, 0, .3, .6, 1],
  3230. marks=pytest.mark.slow
  3231. ),
  3232. pytest.param(
  3233. [.01, .05, .1, .25, .35, .5, .65, .75, .9, .95, .99],
  3234. np.linspace(0.1, 2, 20),
  3235. np.linspace(-1, 1, 21),
  3236. marks=pytest.mark.xslow,
  3237. ),
  3238. ]
  3239. )
  3240. def test_pdf_nolan_samples(
  3241. self, nolan_pdf_sample_data, pct_range, alpha_range, beta_range
  3242. ):
  3243. """Test pdf values against Nolan's stablec.exe output"""
  3244. data = nolan_pdf_sample_data
  3245. # some tests break on linux 32 bit
  3246. uname = platform.uname()
  3247. is_linux_32 = uname.system == 'Linux' and uname.machine == 'i686'
  3248. platform_desc = "/".join(
  3249. [uname.system, uname.machine, uname.processor])
  3250. # fmt: off
  3251. # There are a number of cases which fail on some but not all platforms.
  3252. # These are excluded by the filters below. TODO: Rewrite tests so that
  3253. # the now filtered out test cases are still run but marked in pytest as
  3254. # expected to fail.
  3255. tests = [
  3256. [
  3257. 'dni', 1e-7, lambda r: (
  3258. np.isin(r['pct'], pct_range) &
  3259. np.isin(r['alpha'], alpha_range) &
  3260. np.isin(r['beta'], beta_range) &
  3261. ~(
  3262. (
  3263. (r['beta'] == 0) &
  3264. (r['pct'] == 0.5)
  3265. ) |
  3266. (
  3267. (r['beta'] >= 0.9) &
  3268. (r['alpha'] >= 1.6) &
  3269. (r['pct'] == 0.5)
  3270. ) |
  3271. (
  3272. (r['alpha'] <= 0.4) &
  3273. np.isin(r['pct'], [.01, .99])
  3274. ) |
  3275. (
  3276. (r['alpha'] <= 0.3) &
  3277. np.isin(r['pct'], [.05, .95])
  3278. ) |
  3279. (
  3280. (r['alpha'] <= 0.2) &
  3281. np.isin(r['pct'], [.1, .9])
  3282. ) |
  3283. (
  3284. (r['alpha'] == 0.1) &
  3285. np.isin(r['pct'], [.25, .75]) &
  3286. np.isin(np.abs(r['beta']), [.5, .6, .7])
  3287. ) |
  3288. (
  3289. (r['alpha'] == 0.1) &
  3290. np.isin(r['pct'], [.5]) &
  3291. np.isin(np.abs(r['beta']), [.1])
  3292. ) |
  3293. (
  3294. (r['alpha'] == 0.1) &
  3295. np.isin(r['pct'], [.35, .65]) &
  3296. np.isin(np.abs(r['beta']), [-.4, -.3, .3, .4, .5])
  3297. ) |
  3298. (
  3299. (r['alpha'] == 0.2) &
  3300. (r['beta'] == 0.5) &
  3301. (r['pct'] == 0.25)
  3302. ) |
  3303. (
  3304. (r['alpha'] == 0.2) &
  3305. (r['beta'] == -0.3) &
  3306. (r['pct'] == 0.65)
  3307. ) |
  3308. (
  3309. (r['alpha'] == 0.2) &
  3310. (r['beta'] == 0.3) &
  3311. (r['pct'] == 0.35)
  3312. ) |
  3313. (
  3314. (r['alpha'] == 1.) &
  3315. np.isin(r['pct'], [.5]) &
  3316. np.isin(np.abs(r['beta']), [.1, .2, .3, .4])
  3317. ) |
  3318. (
  3319. (r['alpha'] == 1.) &
  3320. np.isin(r['pct'], [.35, .65]) &
  3321. np.isin(np.abs(r['beta']), [.8, .9, 1.])
  3322. ) |
  3323. (
  3324. (r['alpha'] == 1.) &
  3325. np.isin(r['pct'], [.01, .99]) &
  3326. np.isin(np.abs(r['beta']), [-.1, .1])
  3327. ) |
  3328. # various points ok but too sparse to list
  3329. (r['alpha'] >= 1.1)
  3330. )
  3331. )
  3332. ],
  3333. # piecewise generally good accuracy
  3334. [
  3335. 'piecewise', 1e-11, lambda r: (
  3336. np.isin(r['pct'], pct_range) &
  3337. np.isin(r['alpha'], alpha_range) &
  3338. np.isin(r['beta'], beta_range) &
  3339. (r['alpha'] > 0.2) &
  3340. (r['alpha'] != 1.)
  3341. )
  3342. ],
  3343. # for alpha = 1. for linux 32 bit optimize.bisect
  3344. # has some issues for .01 and .99 percentile
  3345. [
  3346. 'piecewise', 1e-11, lambda r: (
  3347. (r['alpha'] == 1.) &
  3348. (not is_linux_32) &
  3349. np.isin(r['pct'], pct_range) &
  3350. (1. in alpha_range) &
  3351. np.isin(r['beta'], beta_range)
  3352. )
  3353. ],
  3354. # for small alpha very slightly reduced accuracy
  3355. [
  3356. 'piecewise', 2.5e-10, lambda r: (
  3357. np.isin(r['pct'], pct_range) &
  3358. np.isin(r['alpha'], alpha_range) &
  3359. np.isin(r['beta'], beta_range) &
  3360. (r['alpha'] <= 0.2)
  3361. )
  3362. ],
  3363. # fft accuracy reduces as alpha decreases
  3364. [
  3365. 'fft-simpson', 1e-5, lambda r: (
  3366. (r['alpha'] >= 1.9) &
  3367. np.isin(r['pct'], pct_range) &
  3368. np.isin(r['alpha'], alpha_range) &
  3369. np.isin(r['beta'], beta_range)
  3370. ),
  3371. ],
  3372. [
  3373. 'fft-simpson', 1e-6, lambda r: (
  3374. np.isin(r['pct'], pct_range) &
  3375. np.isin(r['alpha'], alpha_range) &
  3376. np.isin(r['beta'], beta_range) &
  3377. (r['alpha'] > 1) &
  3378. (r['alpha'] < 1.9)
  3379. )
  3380. ],
  3381. # fft relative errors for alpha < 1, will raise if enabled
  3382. # ['fft-simpson', 1e-4, lambda r: r['alpha'] == 0.9],
  3383. # ['fft-simpson', 1e-3, lambda r: r['alpha'] == 0.8],
  3384. # ['fft-simpson', 1e-2, lambda r: r['alpha'] == 0.7],
  3385. # ['fft-simpson', 1e-1, lambda r: r['alpha'] == 0.6],
  3386. ]
  3387. # fmt: on
  3388. for ix, (default_method, rtol,
  3389. filter_func) in enumerate(tests):
  3390. stats.levy_stable.pdf_default_method = default_method
  3391. subdata = data[filter_func(data)
  3392. ] if filter_func is not None else data
  3393. with suppress_warnings() as sup:
  3394. # occurs in FFT methods only
  3395. sup.record(
  3396. RuntimeWarning,
  3397. "Density calculations experimental for FFT method.*"
  3398. )
  3399. p = stats.levy_stable.pdf(
  3400. subdata['x'],
  3401. subdata['alpha'],
  3402. subdata['beta'],
  3403. scale=1,
  3404. loc=0
  3405. )
  3406. with np.errstate(over="ignore"):
  3407. subdata2 = rec_append_fields(
  3408. subdata,
  3409. ['calc', 'abserr', 'relerr'],
  3410. [
  3411. p,
  3412. np.abs(p - subdata['p']),
  3413. np.abs(p - subdata['p']) / np.abs(subdata['p'])
  3414. ]
  3415. )
  3416. failures = subdata2[
  3417. (subdata2['relerr'] >= rtol) |
  3418. np.isnan(p)
  3419. ]
  3420. assert_allclose(
  3421. p,
  3422. subdata['p'],
  3423. rtol,
  3424. err_msg="pdf test %s failed with method '%s'"
  3425. " [platform: %s]\n%s\n%s" %
  3426. (ix, default_method, platform_desc, failures.dtype.names,
  3427. failures),
  3428. verbose=False
  3429. )
  3430. @pytest.mark.parametrize(
  3431. "pct_range,alpha_range,beta_range", [
  3432. pytest.param(
  3433. [.01, .5, .99],
  3434. [.1, 1, 2],
  3435. [-1, 0, .8],
  3436. ),
  3437. pytest.param(
  3438. [.01, .05, .5, .95, .99],
  3439. [.1, .5, 1, 1.5, 2],
  3440. [-.9, -.5, 0, .3, .6, 1],
  3441. marks=pytest.mark.slow
  3442. ),
  3443. pytest.param(
  3444. [.01, .05, .1, .25, .35, .5, .65, .75, .9, .95, .99],
  3445. np.linspace(0.1, 2, 20),
  3446. np.linspace(-1, 1, 21),
  3447. marks=pytest.mark.xslow,
  3448. ),
  3449. ]
  3450. )
  3451. def test_cdf_nolan_samples(
  3452. self, nolan_cdf_sample_data, pct_range, alpha_range, beta_range
  3453. ):
  3454. """ Test cdf values against Nolan's stablec.exe output."""
  3455. data = nolan_cdf_sample_data
  3456. tests = [
  3457. # piecewise generally good accuracy
  3458. [
  3459. 'piecewise', 2e-12, lambda r: (
  3460. np.isin(r['pct'], pct_range) &
  3461. np.isin(r['alpha'], alpha_range) &
  3462. np.isin(r['beta'], beta_range) &
  3463. ~(
  3464. (
  3465. (r['alpha'] == 1.) &
  3466. np.isin(r['beta'], [-0.3, -0.2, -0.1]) &
  3467. (r['pct'] == 0.01)
  3468. ) |
  3469. (
  3470. (r['alpha'] == 1.) &
  3471. np.isin(r['beta'], [0.1, 0.2, 0.3]) &
  3472. (r['pct'] == 0.99)
  3473. )
  3474. )
  3475. )
  3476. ],
  3477. # for some points with alpha=1, Nolan's STABLE clearly
  3478. # loses accuracy
  3479. [
  3480. 'piecewise', 5e-2, lambda r: (
  3481. np.isin(r['pct'], pct_range) &
  3482. np.isin(r['alpha'], alpha_range) &
  3483. np.isin(r['beta'], beta_range) &
  3484. (
  3485. (r['alpha'] == 1.) &
  3486. np.isin(r['beta'], [-0.3, -0.2, -0.1]) &
  3487. (r['pct'] == 0.01)
  3488. ) |
  3489. (
  3490. (r['alpha'] == 1.) &
  3491. np.isin(r['beta'], [0.1, 0.2, 0.3]) &
  3492. (r['pct'] == 0.99)
  3493. )
  3494. )
  3495. ],
  3496. # fft accuracy poor, very poor alpha < 1
  3497. [
  3498. 'fft-simpson', 1e-5, lambda r: (
  3499. np.isin(r['pct'], pct_range) &
  3500. np.isin(r['alpha'], alpha_range) &
  3501. np.isin(r['beta'], beta_range) &
  3502. (r['alpha'] > 1.7)
  3503. )
  3504. ],
  3505. [
  3506. 'fft-simpson', 1e-4, lambda r: (
  3507. np.isin(r['pct'], pct_range) &
  3508. np.isin(r['alpha'], alpha_range) &
  3509. np.isin(r['beta'], beta_range) &
  3510. (r['alpha'] > 1.5) &
  3511. (r['alpha'] <= 1.7)
  3512. )
  3513. ],
  3514. [
  3515. 'fft-simpson', 1e-3, lambda r: (
  3516. np.isin(r['pct'], pct_range) &
  3517. np.isin(r['alpha'], alpha_range) &
  3518. np.isin(r['beta'], beta_range) &
  3519. (r['alpha'] > 1.3) &
  3520. (r['alpha'] <= 1.5)
  3521. )
  3522. ],
  3523. [
  3524. 'fft-simpson', 1e-2, lambda r: (
  3525. np.isin(r['pct'], pct_range) &
  3526. np.isin(r['alpha'], alpha_range) &
  3527. np.isin(r['beta'], beta_range) &
  3528. (r['alpha'] > 1.0) &
  3529. (r['alpha'] <= 1.3)
  3530. )
  3531. ],
  3532. ]
  3533. for ix, (default_method, rtol,
  3534. filter_func) in enumerate(tests):
  3535. stats.levy_stable.cdf_default_method = default_method
  3536. subdata = data[filter_func(data)
  3537. ] if filter_func is not None else data
  3538. with suppress_warnings() as sup:
  3539. sup.record(
  3540. RuntimeWarning,
  3541. 'Cumulative density calculations experimental for FFT'
  3542. + ' method. Use piecewise method instead.*'
  3543. )
  3544. p = stats.levy_stable.cdf(
  3545. subdata['x'],
  3546. subdata['alpha'],
  3547. subdata['beta'],
  3548. scale=1,
  3549. loc=0
  3550. )
  3551. with np.errstate(over="ignore"):
  3552. subdata2 = rec_append_fields(
  3553. subdata,
  3554. ['calc', 'abserr', 'relerr'],
  3555. [
  3556. p,
  3557. np.abs(p - subdata['p']),
  3558. np.abs(p - subdata['p']) / np.abs(subdata['p'])
  3559. ]
  3560. )
  3561. failures = subdata2[
  3562. (subdata2['relerr'] >= rtol) |
  3563. np.isnan(p)
  3564. ]
  3565. assert_allclose(
  3566. p,
  3567. subdata['p'],
  3568. rtol,
  3569. err_msg="cdf test %s failed with method '%s'\n%s\n%s" %
  3570. (ix, default_method, failures.dtype.names, failures),
  3571. verbose=False
  3572. )
  3573. @pytest.mark.parametrize("param", [0, 1])
  3574. @pytest.mark.parametrize("case", ["pdf", "cdf"])
  3575. def test_location_scale(
  3576. self, nolan_loc_scale_sample_data, param, case
  3577. ):
  3578. """Tests for pdf and cdf where loc, scale are different from 0, 1
  3579. """
  3580. uname = platform.uname()
  3581. is_linux_32 = uname.system == 'Linux' and "32bit" in platform.architecture()[0]
  3582. # Test seems to be unstable (see gh-17839 for a bug report on Debian
  3583. # i386), so skip it.
  3584. if is_linux_32 and case == 'pdf':
  3585. pytest.skip("Test unstable on some platforms; see gh-17839, 17859")
  3586. data = nolan_loc_scale_sample_data
  3587. # We only test against piecewise as location/scale transforms
  3588. # are same for other methods.
  3589. stats.levy_stable.cdf_default_method = "piecewise"
  3590. stats.levy_stable.pdf_default_method = "piecewise"
  3591. subdata = data[data["param"] == param]
  3592. stats.levy_stable.parameterization = f"S{param}"
  3593. assert case in ["pdf", "cdf"]
  3594. function = (
  3595. stats.levy_stable.pdf if case == "pdf" else stats.levy_stable.cdf
  3596. )
  3597. v1 = function(
  3598. subdata['x'], subdata['alpha'], subdata['beta'], scale=2, loc=3
  3599. )
  3600. assert_allclose(v1, subdata[case], 1e-5)
  3601. @pytest.mark.parametrize(
  3602. "method,decimal_places",
  3603. [
  3604. ['dni', 4],
  3605. ['piecewise', 4],
  3606. ]
  3607. )
  3608. def test_pdf_alpha_equals_one_beta_non_zero(self, method, decimal_places):
  3609. """ sample points extracted from Tables and Graphs of Stable
  3610. Probability Density Functions - Donald R Holt - 1973 - p 187.
  3611. """
  3612. xs = np.array(
  3613. [0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4]
  3614. )
  3615. density = np.array(
  3616. [
  3617. .3183, .3096, .2925, .2622, .1591, .1587, .1599, .1635, .0637,
  3618. .0729, .0812, .0955, .0318, .0390, .0458, .0586, .0187, .0236,
  3619. .0285, .0384
  3620. ]
  3621. )
  3622. betas = np.array(
  3623. [
  3624. 0, .25, .5, 1, 0, .25, .5, 1, 0, .25, .5, 1, 0, .25, .5, 1, 0,
  3625. .25, .5, 1
  3626. ]
  3627. )
  3628. with np.errstate(all='ignore'), suppress_warnings() as sup:
  3629. sup.filter(
  3630. category=RuntimeWarning,
  3631. message="Density calculation unstable.*"
  3632. )
  3633. stats.levy_stable.pdf_default_method = method
  3634. # stats.levy_stable.fft_grid_spacing = 0.0001
  3635. pdf = stats.levy_stable.pdf(xs, 1, betas, scale=1, loc=0)
  3636. assert_almost_equal(
  3637. pdf, density, decimal_places, method
  3638. )
  3639. @pytest.mark.parametrize(
  3640. "params,expected",
  3641. [
  3642. [(1.48, -.22, 0, 1), (0, np.inf, np.NaN, np.NaN)],
  3643. [(2, .9, 10, 1.5), (10, 4.5, 0, 0)]
  3644. ]
  3645. )
  3646. def test_stats(self, params, expected):
  3647. observed = stats.levy_stable.stats(
  3648. params[0], params[1], loc=params[2], scale=params[3],
  3649. moments='mvsk'
  3650. )
  3651. assert_almost_equal(observed, expected)
  3652. @pytest.mark.parametrize('alpha', [0.25, 0.5, 0.75])
  3653. @pytest.mark.parametrize(
  3654. 'function,beta,points,expected',
  3655. [
  3656. (
  3657. stats.levy_stable.cdf,
  3658. 1.0,
  3659. np.linspace(-25, 0, 10),
  3660. 0.0,
  3661. ),
  3662. (
  3663. stats.levy_stable.pdf,
  3664. 1.0,
  3665. np.linspace(-25, 0, 10),
  3666. 0.0,
  3667. ),
  3668. (
  3669. stats.levy_stable.cdf,
  3670. -1.0,
  3671. np.linspace(0, 25, 10),
  3672. 1.0,
  3673. ),
  3674. (
  3675. stats.levy_stable.pdf,
  3676. -1.0,
  3677. np.linspace(0, 25, 10),
  3678. 0.0,
  3679. )
  3680. ]
  3681. )
  3682. def test_distribution_outside_support(
  3683. self, alpha, function, beta, points, expected
  3684. ):
  3685. """Ensure the pdf/cdf routines do not return nan outside support.
  3686. This distribution's support becomes truncated in a few special cases:
  3687. support is [mu, infty) if alpha < 1 and beta = 1
  3688. support is (-infty, mu] if alpha < 1 and beta = -1
  3689. Otherwise, the support is all reals. Here, mu is zero by default.
  3690. """
  3691. assert 0 < alpha < 1
  3692. assert_almost_equal(
  3693. function(points, alpha=alpha, beta=beta),
  3694. np.full(len(points), expected)
  3695. )
  3696. class TestArrayArgument: # test for ticket:992
  3697. def setup_method(self):
  3698. np.random.seed(1234)
  3699. def test_noexception(self):
  3700. rvs = stats.norm.rvs(loc=(np.arange(5)), scale=np.ones(5),
  3701. size=(10, 5))
  3702. assert_equal(rvs.shape, (10, 5))
  3703. class TestDocstring:
  3704. def test_docstrings(self):
  3705. # See ticket #761
  3706. if stats.rayleigh.__doc__ is not None:
  3707. assert_("rayleigh" in stats.rayleigh.__doc__.lower())
  3708. if stats.bernoulli.__doc__ is not None:
  3709. assert_("bernoulli" in stats.bernoulli.__doc__.lower())
  3710. def test_no_name_arg(self):
  3711. # If name is not given, construction shouldn't fail. See #1508.
  3712. stats.rv_continuous()
  3713. stats.rv_discrete()
  3714. def TestArgsreduce():
  3715. a = array([1, 3, 2, 1, 2, 3, 3])
  3716. b, c = argsreduce(a > 1, a, 2)
  3717. assert_array_equal(b, [3, 2, 2, 3, 3])
  3718. assert_array_equal(c, [2, 2, 2, 2, 2])
  3719. b, c = argsreduce(2 > 1, a, 2)
  3720. assert_array_equal(b, a[0])
  3721. assert_array_equal(c, [2])
  3722. b, c = argsreduce(a > 0, a, 2)
  3723. assert_array_equal(b, a)
  3724. assert_array_equal(c, [2] * numpy.size(a))
  3725. class TestFitMethod:
  3726. skip = ['ncf', 'ksone', 'kstwo']
  3727. def setup_method(self):
  3728. np.random.seed(1234)
  3729. # skip these b/c deprecated, or only loc and scale arguments
  3730. fitSkipNonFinite = ['expon', 'norm', 'uniform']
  3731. @pytest.mark.parametrize('dist,args', distcont)
  3732. def test_fit_w_non_finite_data_values(self, dist, args):
  3733. """gh-10300"""
  3734. if dist in self.fitSkipNonFinite:
  3735. pytest.skip("%s fit known to fail or deprecated" % dist)
  3736. x = np.array([1.6483, 2.7169, 2.4667, 1.1791, 3.5433, np.nan])
  3737. y = np.array([1.6483, 2.7169, 2.4667, 1.1791, 3.5433, np.inf])
  3738. distfunc = getattr(stats, dist)
  3739. assert_raises(ValueError, distfunc.fit, x, fscale=1)
  3740. assert_raises(ValueError, distfunc.fit, y, fscale=1)
  3741. def test_fix_fit_2args_lognorm(self):
  3742. # Regression test for #1551.
  3743. np.random.seed(12345)
  3744. with np.errstate(all='ignore'):
  3745. x = stats.lognorm.rvs(0.25, 0., 20.0, size=20)
  3746. expected_shape = np.sqrt(((np.log(x) - np.log(20))**2).mean())
  3747. assert_allclose(np.array(stats.lognorm.fit(x, floc=0, fscale=20)),
  3748. [expected_shape, 0, 20], atol=1e-8)
  3749. def test_fix_fit_norm(self):
  3750. x = np.arange(1, 6)
  3751. loc, scale = stats.norm.fit(x)
  3752. assert_almost_equal(loc, 3)
  3753. assert_almost_equal(scale, np.sqrt(2))
  3754. loc, scale = stats.norm.fit(x, floc=2)
  3755. assert_equal(loc, 2)
  3756. assert_equal(scale, np.sqrt(3))
  3757. loc, scale = stats.norm.fit(x, fscale=2)
  3758. assert_almost_equal(loc, 3)
  3759. assert_equal(scale, 2)
  3760. def test_fix_fit_gamma(self):
  3761. x = np.arange(1, 6)
  3762. meanlog = np.log(x).mean()
  3763. # A basic test of gamma.fit with floc=0.
  3764. floc = 0
  3765. a, loc, scale = stats.gamma.fit(x, floc=floc)
  3766. s = np.log(x.mean()) - meanlog
  3767. assert_almost_equal(np.log(a) - special.digamma(a), s, decimal=5)
  3768. assert_equal(loc, floc)
  3769. assert_almost_equal(scale, x.mean()/a, decimal=8)
  3770. # Regression tests for gh-2514.
  3771. # The problem was that if `floc=0` was given, any other fixed
  3772. # parameters were ignored.
  3773. f0 = 1
  3774. floc = 0
  3775. a, loc, scale = stats.gamma.fit(x, f0=f0, floc=floc)
  3776. assert_equal(a, f0)
  3777. assert_equal(loc, floc)
  3778. assert_almost_equal(scale, x.mean()/a, decimal=8)
  3779. f0 = 2
  3780. floc = 0
  3781. a, loc, scale = stats.gamma.fit(x, f0=f0, floc=floc)
  3782. assert_equal(a, f0)
  3783. assert_equal(loc, floc)
  3784. assert_almost_equal(scale, x.mean()/a, decimal=8)
  3785. # loc and scale fixed.
  3786. floc = 0
  3787. fscale = 2
  3788. a, loc, scale = stats.gamma.fit(x, floc=floc, fscale=fscale)
  3789. assert_equal(loc, floc)
  3790. assert_equal(scale, fscale)
  3791. c = meanlog - np.log(fscale)
  3792. assert_almost_equal(special.digamma(a), c)
  3793. def test_fix_fit_beta(self):
  3794. # Test beta.fit when both floc and fscale are given.
  3795. def mlefunc(a, b, x):
  3796. # Zeros of this function are critical points of
  3797. # the maximum likelihood function.
  3798. n = len(x)
  3799. s1 = np.log(x).sum()
  3800. s2 = np.log(1-x).sum()
  3801. psiab = special.psi(a + b)
  3802. func = [s1 - n * (-psiab + special.psi(a)),
  3803. s2 - n * (-psiab + special.psi(b))]
  3804. return func
  3805. # Basic test with floc and fscale given.
  3806. x = np.array([0.125, 0.25, 0.5])
  3807. a, b, loc, scale = stats.beta.fit(x, floc=0, fscale=1)
  3808. assert_equal(loc, 0)
  3809. assert_equal(scale, 1)
  3810. assert_allclose(mlefunc(a, b, x), [0, 0], atol=1e-6)
  3811. # Basic test with f0, floc and fscale given.
  3812. # This is also a regression test for gh-2514.
  3813. x = np.array([0.125, 0.25, 0.5])
  3814. a, b, loc, scale = stats.beta.fit(x, f0=2, floc=0, fscale=1)
  3815. assert_equal(a, 2)
  3816. assert_equal(loc, 0)
  3817. assert_equal(scale, 1)
  3818. da, db = mlefunc(a, b, x)
  3819. assert_allclose(db, 0, atol=1e-5)
  3820. # Same floc and fscale values as above, but reverse the data
  3821. # and fix b (f1).
  3822. x2 = 1 - x
  3823. a2, b2, loc2, scale2 = stats.beta.fit(x2, f1=2, floc=0, fscale=1)
  3824. assert_equal(b2, 2)
  3825. assert_equal(loc2, 0)
  3826. assert_equal(scale2, 1)
  3827. da, db = mlefunc(a2, b2, x2)
  3828. assert_allclose(da, 0, atol=1e-5)
  3829. # a2 of this test should equal b from above.
  3830. assert_almost_equal(a2, b)
  3831. # Check for detection of data out of bounds when floc and fscale
  3832. # are given.
  3833. assert_raises(ValueError, stats.beta.fit, x, floc=0.5, fscale=1)
  3834. y = np.array([0, .5, 1])
  3835. assert_raises(ValueError, stats.beta.fit, y, floc=0, fscale=1)
  3836. assert_raises(ValueError, stats.beta.fit, y, floc=0, fscale=1, f0=2)
  3837. assert_raises(ValueError, stats.beta.fit, y, floc=0, fscale=1, f1=2)
  3838. # Check that attempting to fix all the parameters raises a ValueError.
  3839. assert_raises(ValueError, stats.beta.fit, y, f0=0, f1=1,
  3840. floc=2, fscale=3)
  3841. def test_expon_fit(self):
  3842. x = np.array([2, 2, 4, 4, 4, 4, 4, 8])
  3843. loc, scale = stats.expon.fit(x)
  3844. assert_equal(loc, 2) # x.min()
  3845. assert_equal(scale, 2) # x.mean() - x.min()
  3846. loc, scale = stats.expon.fit(x, fscale=3)
  3847. assert_equal(loc, 2) # x.min()
  3848. assert_equal(scale, 3) # fscale
  3849. loc, scale = stats.expon.fit(x, floc=0)
  3850. assert_equal(loc, 0) # floc
  3851. assert_equal(scale, 4) # x.mean() - loc
  3852. def test_lognorm_fit(self):
  3853. x = np.array([1.5, 3, 10, 15, 23, 59])
  3854. lnxm1 = np.log(x - 1)
  3855. shape, loc, scale = stats.lognorm.fit(x, floc=1)
  3856. assert_allclose(shape, lnxm1.std(), rtol=1e-12)
  3857. assert_equal(loc, 1)
  3858. assert_allclose(scale, np.exp(lnxm1.mean()), rtol=1e-12)
  3859. shape, loc, scale = stats.lognorm.fit(x, floc=1, fscale=6)
  3860. assert_allclose(shape, np.sqrt(((lnxm1 - np.log(6))**2).mean()),
  3861. rtol=1e-12)
  3862. assert_equal(loc, 1)
  3863. assert_equal(scale, 6)
  3864. shape, loc, scale = stats.lognorm.fit(x, floc=1, fix_s=0.75)
  3865. assert_equal(shape, 0.75)
  3866. assert_equal(loc, 1)
  3867. assert_allclose(scale, np.exp(lnxm1.mean()), rtol=1e-12)
  3868. def test_uniform_fit(self):
  3869. x = np.array([1.0, 1.1, 1.2, 9.0])
  3870. loc, scale = stats.uniform.fit(x)
  3871. assert_equal(loc, x.min())
  3872. assert_equal(scale, x.ptp())
  3873. loc, scale = stats.uniform.fit(x, floc=0)
  3874. assert_equal(loc, 0)
  3875. assert_equal(scale, x.max())
  3876. loc, scale = stats.uniform.fit(x, fscale=10)
  3877. assert_equal(loc, 0)
  3878. assert_equal(scale, 10)
  3879. assert_raises(ValueError, stats.uniform.fit, x, floc=2.0)
  3880. assert_raises(ValueError, stats.uniform.fit, x, fscale=5.0)
  3881. @pytest.mark.slow
  3882. @pytest.mark.parametrize("method", ["MLE", "MM"])
  3883. def test_fshapes(self, method):
  3884. # take a beta distribution, with shapes='a, b', and make sure that
  3885. # fa is equivalent to f0, and fb is equivalent to f1
  3886. a, b = 3., 4.
  3887. x = stats.beta.rvs(a, b, size=100, random_state=1234)
  3888. res_1 = stats.beta.fit(x, f0=3., method=method)
  3889. res_2 = stats.beta.fit(x, fa=3., method=method)
  3890. assert_allclose(res_1, res_2, atol=1e-12, rtol=1e-12)
  3891. res_2 = stats.beta.fit(x, fix_a=3., method=method)
  3892. assert_allclose(res_1, res_2, atol=1e-12, rtol=1e-12)
  3893. res_3 = stats.beta.fit(x, f1=4., method=method)
  3894. res_4 = stats.beta.fit(x, fb=4., method=method)
  3895. assert_allclose(res_3, res_4, atol=1e-12, rtol=1e-12)
  3896. res_4 = stats.beta.fit(x, fix_b=4., method=method)
  3897. assert_allclose(res_3, res_4, atol=1e-12, rtol=1e-12)
  3898. # cannot specify both positional and named args at the same time
  3899. assert_raises(ValueError, stats.beta.fit, x, fa=1, f0=2, method=method)
  3900. # check that attempting to fix all parameters raises a ValueError
  3901. assert_raises(ValueError, stats.beta.fit, x, fa=0, f1=1,
  3902. floc=2, fscale=3, method=method)
  3903. # check that specifying floc, fscale and fshapes works for
  3904. # beta and gamma which override the generic fit method
  3905. res_5 = stats.beta.fit(x, fa=3., floc=0, fscale=1, method=method)
  3906. aa, bb, ll, ss = res_5
  3907. assert_equal([aa, ll, ss], [3., 0, 1])
  3908. # gamma distribution
  3909. a = 3.
  3910. data = stats.gamma.rvs(a, size=100)
  3911. aa, ll, ss = stats.gamma.fit(data, fa=a, method=method)
  3912. assert_equal(aa, a)
  3913. @pytest.mark.parametrize("method", ["MLE", "MM"])
  3914. def test_extra_params(self, method):
  3915. # unknown parameters should raise rather than be silently ignored
  3916. dist = stats.exponnorm
  3917. data = dist.rvs(K=2, size=100)
  3918. dct = dict(enikibeniki=-101)
  3919. assert_raises(TypeError, dist.fit, data, **dct, method=method)
  3920. class TestFrozen:
  3921. def setup_method(self):
  3922. np.random.seed(1234)
  3923. # Test that a frozen distribution gives the same results as the original
  3924. # object.
  3925. #
  3926. # Only tested for the normal distribution (with loc and scale specified)
  3927. # and for the gamma distribution (with a shape parameter specified).
  3928. def test_norm(self):
  3929. dist = stats.norm
  3930. frozen = stats.norm(loc=10.0, scale=3.0)
  3931. result_f = frozen.pdf(20.0)
  3932. result = dist.pdf(20.0, loc=10.0, scale=3.0)
  3933. assert_equal(result_f, result)
  3934. result_f = frozen.cdf(20.0)
  3935. result = dist.cdf(20.0, loc=10.0, scale=3.0)
  3936. assert_equal(result_f, result)
  3937. result_f = frozen.ppf(0.25)
  3938. result = dist.ppf(0.25, loc=10.0, scale=3.0)
  3939. assert_equal(result_f, result)
  3940. result_f = frozen.isf(0.25)
  3941. result = dist.isf(0.25, loc=10.0, scale=3.0)
  3942. assert_equal(result_f, result)
  3943. result_f = frozen.sf(10.0)
  3944. result = dist.sf(10.0, loc=10.0, scale=3.0)
  3945. assert_equal(result_f, result)
  3946. result_f = frozen.median()
  3947. result = dist.median(loc=10.0, scale=3.0)
  3948. assert_equal(result_f, result)
  3949. result_f = frozen.mean()
  3950. result = dist.mean(loc=10.0, scale=3.0)
  3951. assert_equal(result_f, result)
  3952. result_f = frozen.var()
  3953. result = dist.var(loc=10.0, scale=3.0)
  3954. assert_equal(result_f, result)
  3955. result_f = frozen.std()
  3956. result = dist.std(loc=10.0, scale=3.0)
  3957. assert_equal(result_f, result)
  3958. result_f = frozen.entropy()
  3959. result = dist.entropy(loc=10.0, scale=3.0)
  3960. assert_equal(result_f, result)
  3961. result_f = frozen.moment(2)
  3962. result = dist.moment(2, loc=10.0, scale=3.0)
  3963. assert_equal(result_f, result)
  3964. assert_equal(frozen.a, dist.a)
  3965. assert_equal(frozen.b, dist.b)
  3966. def test_gamma(self):
  3967. a = 2.0
  3968. dist = stats.gamma
  3969. frozen = stats.gamma(a)
  3970. result_f = frozen.pdf(20.0)
  3971. result = dist.pdf(20.0, a)
  3972. assert_equal(result_f, result)
  3973. result_f = frozen.cdf(20.0)
  3974. result = dist.cdf(20.0, a)
  3975. assert_equal(result_f, result)
  3976. result_f = frozen.ppf(0.25)
  3977. result = dist.ppf(0.25, a)
  3978. assert_equal(result_f, result)
  3979. result_f = frozen.isf(0.25)
  3980. result = dist.isf(0.25, a)
  3981. assert_equal(result_f, result)
  3982. result_f = frozen.sf(10.0)
  3983. result = dist.sf(10.0, a)
  3984. assert_equal(result_f, result)
  3985. result_f = frozen.median()
  3986. result = dist.median(a)
  3987. assert_equal(result_f, result)
  3988. result_f = frozen.mean()
  3989. result = dist.mean(a)
  3990. assert_equal(result_f, result)
  3991. result_f = frozen.var()
  3992. result = dist.var(a)
  3993. assert_equal(result_f, result)
  3994. result_f = frozen.std()
  3995. result = dist.std(a)
  3996. assert_equal(result_f, result)
  3997. result_f = frozen.entropy()
  3998. result = dist.entropy(a)
  3999. assert_equal(result_f, result)
  4000. result_f = frozen.moment(2)
  4001. result = dist.moment(2, a)
  4002. assert_equal(result_f, result)
  4003. assert_equal(frozen.a, frozen.dist.a)
  4004. assert_equal(frozen.b, frozen.dist.b)
  4005. def test_regression_ticket_1293(self):
  4006. # Create a frozen distribution.
  4007. frozen = stats.lognorm(1)
  4008. # Call one of its methods that does not take any keyword arguments.
  4009. m1 = frozen.moment(2)
  4010. # Now call a method that takes a keyword argument.
  4011. frozen.stats(moments='mvsk')
  4012. # Call moment(2) again.
  4013. # After calling stats(), the following was raising an exception.
  4014. # So this test passes if the following does not raise an exception.
  4015. m2 = frozen.moment(2)
  4016. # The following should also be true, of course. But it is not
  4017. # the focus of this test.
  4018. assert_equal(m1, m2)
  4019. def test_ab(self):
  4020. # test that the support of a frozen distribution
  4021. # (i) remains frozen even if it changes for the original one
  4022. # (ii) is actually correct if the shape parameters are such that
  4023. # the values of [a, b] are not the default [0, inf]
  4024. # take a genpareto as an example where the support
  4025. # depends on the value of the shape parameter:
  4026. # for c > 0: a, b = 0, inf
  4027. # for c < 0: a, b = 0, -1/c
  4028. c = -0.1
  4029. rv = stats.genpareto(c=c)
  4030. a, b = rv.dist._get_support(c)
  4031. assert_equal([a, b], [0., 10.])
  4032. c = 0.1
  4033. stats.genpareto.pdf(0, c=c)
  4034. assert_equal(rv.dist._get_support(c), [0, np.inf])
  4035. c = -0.1
  4036. rv = stats.genpareto(c=c)
  4037. a, b = rv.dist._get_support(c)
  4038. assert_equal([a, b], [0., 10.])
  4039. c = 0.1
  4040. stats.genpareto.pdf(0, c) # this should NOT change genpareto.b
  4041. assert_equal((rv.dist.a, rv.dist.b), stats.genpareto._get_support(c))
  4042. rv1 = stats.genpareto(c=0.1)
  4043. assert_(rv1.dist is not rv.dist)
  4044. # c >= 0: a, b = [0, inf]
  4045. for c in [1., 0.]:
  4046. c = np.asarray(c)
  4047. rv = stats.genpareto(c=c)
  4048. a, b = rv.a, rv.b
  4049. assert_equal(a, 0.)
  4050. assert_(np.isposinf(b))
  4051. # c < 0: a=0, b=1/|c|
  4052. c = np.asarray(-2.)
  4053. a, b = stats.genpareto._get_support(c)
  4054. assert_allclose([a, b], [0., 0.5])
  4055. def test_rv_frozen_in_namespace(self):
  4056. # Regression test for gh-3522
  4057. assert_(hasattr(stats.distributions, 'rv_frozen'))
  4058. def test_random_state(self):
  4059. # only check that the random_state attribute exists,
  4060. frozen = stats.norm()
  4061. assert_(hasattr(frozen, 'random_state'))
  4062. # ... that it can be set,
  4063. frozen.random_state = 42
  4064. assert_equal(frozen.random_state.get_state(),
  4065. np.random.RandomState(42).get_state())
  4066. # ... and that .rvs method accepts it as an argument
  4067. rndm = np.random.RandomState(1234)
  4068. frozen.rvs(size=8, random_state=rndm)
  4069. def test_pickling(self):
  4070. # test that a frozen instance pickles and unpickles
  4071. # (this method is a clone of common_tests.check_pickling)
  4072. beta = stats.beta(2.3098496451481823, 0.62687954300963677)
  4073. poiss = stats.poisson(3.)
  4074. sample = stats.rv_discrete(values=([0, 1, 2, 3],
  4075. [0.1, 0.2, 0.3, 0.4]))
  4076. for distfn in [beta, poiss, sample]:
  4077. distfn.random_state = 1234
  4078. distfn.rvs(size=8)
  4079. s = pickle.dumps(distfn)
  4080. r0 = distfn.rvs(size=8)
  4081. unpickled = pickle.loads(s)
  4082. r1 = unpickled.rvs(size=8)
  4083. assert_equal(r0, r1)
  4084. # also smoke test some methods
  4085. medians = [distfn.ppf(0.5), unpickled.ppf(0.5)]
  4086. assert_equal(medians[0], medians[1])
  4087. assert_equal(distfn.cdf(medians[0]),
  4088. unpickled.cdf(medians[1]))
  4089. def test_expect(self):
  4090. # smoke test the expect method of the frozen distribution
  4091. # only take a gamma w/loc and scale and poisson with loc specified
  4092. def func(x):
  4093. return x
  4094. gm = stats.gamma(a=2, loc=3, scale=4)
  4095. with np.errstate(invalid="ignore", divide="ignore"):
  4096. gm_val = gm.expect(func, lb=1, ub=2, conditional=True)
  4097. gamma_val = stats.gamma.expect(func, args=(2,), loc=3, scale=4,
  4098. lb=1, ub=2, conditional=True)
  4099. assert_allclose(gm_val, gamma_val)
  4100. p = stats.poisson(3, loc=4)
  4101. p_val = p.expect(func)
  4102. poisson_val = stats.poisson.expect(func, args=(3,), loc=4)
  4103. assert_allclose(p_val, poisson_val)
  4104. class TestExpect:
  4105. # Test for expect method.
  4106. #
  4107. # Uses normal distribution and beta distribution for finite bounds, and
  4108. # hypergeom for discrete distribution with finite support
  4109. def test_norm(self):
  4110. v = stats.norm.expect(lambda x: (x-5)*(x-5), loc=5, scale=2)
  4111. assert_almost_equal(v, 4, decimal=14)
  4112. m = stats.norm.expect(lambda x: (x), loc=5, scale=2)
  4113. assert_almost_equal(m, 5, decimal=14)
  4114. lb = stats.norm.ppf(0.05, loc=5, scale=2)
  4115. ub = stats.norm.ppf(0.95, loc=5, scale=2)
  4116. prob90 = stats.norm.expect(lambda x: 1, loc=5, scale=2, lb=lb, ub=ub)
  4117. assert_almost_equal(prob90, 0.9, decimal=14)
  4118. prob90c = stats.norm.expect(lambda x: 1, loc=5, scale=2, lb=lb, ub=ub,
  4119. conditional=True)
  4120. assert_almost_equal(prob90c, 1., decimal=14)
  4121. def test_beta(self):
  4122. # case with finite support interval
  4123. v = stats.beta.expect(lambda x: (x-19/3.)*(x-19/3.), args=(10, 5),
  4124. loc=5, scale=2)
  4125. assert_almost_equal(v, 1./18., decimal=13)
  4126. m = stats.beta.expect(lambda x: x, args=(10, 5), loc=5., scale=2.)
  4127. assert_almost_equal(m, 19/3., decimal=13)
  4128. ub = stats.beta.ppf(0.95, 10, 10, loc=5, scale=2)
  4129. lb = stats.beta.ppf(0.05, 10, 10, loc=5, scale=2)
  4130. prob90 = stats.beta.expect(lambda x: 1., args=(10, 10), loc=5.,
  4131. scale=2., lb=lb, ub=ub, conditional=False)
  4132. assert_almost_equal(prob90, 0.9, decimal=13)
  4133. prob90c = stats.beta.expect(lambda x: 1, args=(10, 10), loc=5,
  4134. scale=2, lb=lb, ub=ub, conditional=True)
  4135. assert_almost_equal(prob90c, 1., decimal=13)
  4136. def test_hypergeom(self):
  4137. # test case with finite bounds
  4138. # without specifying bounds
  4139. m_true, v_true = stats.hypergeom.stats(20, 10, 8, loc=5.)
  4140. m = stats.hypergeom.expect(lambda x: x, args=(20, 10, 8), loc=5.)
  4141. assert_almost_equal(m, m_true, decimal=13)
  4142. v = stats.hypergeom.expect(lambda x: (x-9.)**2, args=(20, 10, 8),
  4143. loc=5.)
  4144. assert_almost_equal(v, v_true, decimal=14)
  4145. # with bounds, bounds equal to shifted support
  4146. v_bounds = stats.hypergeom.expect(lambda x: (x-9.)**2,
  4147. args=(20, 10, 8),
  4148. loc=5., lb=5, ub=13)
  4149. assert_almost_equal(v_bounds, v_true, decimal=14)
  4150. # drop boundary points
  4151. prob_true = 1-stats.hypergeom.pmf([5, 13], 20, 10, 8, loc=5).sum()
  4152. prob_bounds = stats.hypergeom.expect(lambda x: 1, args=(20, 10, 8),
  4153. loc=5., lb=6, ub=12)
  4154. assert_almost_equal(prob_bounds, prob_true, decimal=13)
  4155. # conditional
  4156. prob_bc = stats.hypergeom.expect(lambda x: 1, args=(20, 10, 8), loc=5.,
  4157. lb=6, ub=12, conditional=True)
  4158. assert_almost_equal(prob_bc, 1, decimal=14)
  4159. # check simple integral
  4160. prob_b = stats.hypergeom.expect(lambda x: 1, args=(20, 10, 8),
  4161. lb=0, ub=8)
  4162. assert_almost_equal(prob_b, 1, decimal=13)
  4163. def test_poisson(self):
  4164. # poisson, use lower bound only
  4165. prob_bounds = stats.poisson.expect(lambda x: 1, args=(2,), lb=3,
  4166. conditional=False)
  4167. prob_b_true = 1-stats.poisson.cdf(2, 2)
  4168. assert_almost_equal(prob_bounds, prob_b_true, decimal=14)
  4169. prob_lb = stats.poisson.expect(lambda x: 1, args=(2,), lb=2,
  4170. conditional=True)
  4171. assert_almost_equal(prob_lb, 1, decimal=14)
  4172. def test_genhalflogistic(self):
  4173. # genhalflogistic, changes upper bound of support in _argcheck
  4174. # regression test for gh-2622
  4175. halflog = stats.genhalflogistic
  4176. # check consistency when calling expect twice with the same input
  4177. res1 = halflog.expect(args=(1.5,))
  4178. halflog.expect(args=(0.5,))
  4179. res2 = halflog.expect(args=(1.5,))
  4180. assert_almost_equal(res1, res2, decimal=14)
  4181. def test_rice_overflow(self):
  4182. # rice.pdf(999, 0.74) was inf since special.i0 silentyly overflows
  4183. # check that using i0e fixes it
  4184. assert_(np.isfinite(stats.rice.pdf(999, 0.74)))
  4185. assert_(np.isfinite(stats.rice.expect(lambda x: 1, args=(0.74,))))
  4186. assert_(np.isfinite(stats.rice.expect(lambda x: 2, args=(0.74,))))
  4187. assert_(np.isfinite(stats.rice.expect(lambda x: 3, args=(0.74,))))
  4188. def test_logser(self):
  4189. # test a discrete distribution with infinite support and loc
  4190. p, loc = 0.3, 3
  4191. res_0 = stats.logser.expect(lambda k: k, args=(p,))
  4192. # check against the correct answer (sum of a geom series)
  4193. assert_allclose(res_0,
  4194. p / (p - 1.) / np.log(1. - p), atol=1e-15)
  4195. # now check it with `loc`
  4196. res_l = stats.logser.expect(lambda k: k, args=(p,), loc=loc)
  4197. assert_allclose(res_l, res_0 + loc, atol=1e-15)
  4198. @pytest.mark.filterwarnings('ignore::RuntimeWarning')
  4199. def test_skellam(self):
  4200. # Use a discrete distribution w/ bi-infinite support. Compute two first
  4201. # moments and compare to known values (cf skellam.stats)
  4202. p1, p2 = 18, 22
  4203. m1 = stats.skellam.expect(lambda x: x, args=(p1, p2))
  4204. m2 = stats.skellam.expect(lambda x: x**2, args=(p1, p2))
  4205. assert_allclose(m1, p1 - p2, atol=1e-12)
  4206. assert_allclose(m2 - m1**2, p1 + p2, atol=1e-12)
  4207. def test_randint(self):
  4208. # Use a discrete distribution w/ parameter-dependent support, which
  4209. # is larger than the default chunksize
  4210. lo, hi = 0, 113
  4211. res = stats.randint.expect(lambda x: x, (lo, hi))
  4212. assert_allclose(res,
  4213. sum(_ for _ in range(lo, hi)) / (hi - lo), atol=1e-15)
  4214. def test_zipf(self):
  4215. # Test that there is no infinite loop even if the sum diverges
  4216. assert_warns(RuntimeWarning, stats.zipf.expect,
  4217. lambda x: x**2, (2,))
  4218. def test_discrete_kwds(self):
  4219. # check that discrete expect accepts keywords to control the summation
  4220. n0 = stats.poisson.expect(lambda x: 1, args=(2,))
  4221. n1 = stats.poisson.expect(lambda x: 1, args=(2,),
  4222. maxcount=1001, chunksize=32, tolerance=1e-8)
  4223. assert_almost_equal(n0, n1, decimal=14)
  4224. def test_moment(self):
  4225. # test the .moment() method: compute a higher moment and compare to
  4226. # a known value
  4227. def poiss_moment5(mu):
  4228. return mu**5 + 10*mu**4 + 25*mu**3 + 15*mu**2 + mu
  4229. for mu in [5, 7]:
  4230. m5 = stats.poisson.moment(5, mu)
  4231. assert_allclose(m5, poiss_moment5(mu), rtol=1e-10)
  4232. def test_challenging_cases_gh8928(self):
  4233. # Several cases where `expect` failed to produce a correct result were
  4234. # reported in gh-8928. Check that these cases have been resolved.
  4235. assert_allclose(stats.norm.expect(loc=36, scale=1.0), 36)
  4236. assert_allclose(stats.norm.expect(loc=40, scale=1.0), 40)
  4237. assert_allclose(stats.norm.expect(loc=10, scale=0.1), 10)
  4238. assert_allclose(stats.gamma.expect(args=(148,)), 148)
  4239. assert_allclose(stats.logistic.expect(loc=85), 85)
  4240. def test_lb_ub_gh15855(self):
  4241. # Make sure changes to `expect` made in gh15855 treat lb/ub correctly
  4242. dist = stats.uniform
  4243. ref = dist.mean(loc=10, scale=5) # 12.5
  4244. # moment over whole distribution
  4245. assert_allclose(dist.expect(loc=10, scale=5), ref)
  4246. # moment over whole distribution, lb and ub outside of support
  4247. assert_allclose(dist.expect(loc=10, scale=5, lb=9, ub=16), ref)
  4248. # moment over 60% of distribution, [lb, ub] centered within support
  4249. assert_allclose(dist.expect(loc=10, scale=5, lb=11, ub=14), ref*0.6)
  4250. # moment over truncated distribution, essentially
  4251. assert_allclose(dist.expect(loc=10, scale=5, lb=11, ub=14,
  4252. conditional=True), ref)
  4253. # moment over 40% of distribution, [lb, ub] not centered within support
  4254. assert_allclose(dist.expect(loc=10, scale=5, lb=11, ub=13), 12*0.4)
  4255. # moment with lb > ub
  4256. assert_allclose(dist.expect(loc=10, scale=5, lb=13, ub=11), -12*0.4)
  4257. # moment with lb > ub, conditional
  4258. assert_allclose(dist.expect(loc=10, scale=5, lb=13, ub=11,
  4259. conditional=True), 12)
  4260. class TestNct:
  4261. def test_nc_parameter(self):
  4262. # Parameter values c<=0 were not enabled (gh-2402).
  4263. # For negative values c and for c=0 results of rv.cdf(0) below were nan
  4264. rv = stats.nct(5, 0)
  4265. assert_equal(rv.cdf(0), 0.5)
  4266. rv = stats.nct(5, -1)
  4267. assert_almost_equal(rv.cdf(0), 0.841344746069, decimal=10)
  4268. def test_broadcasting(self):
  4269. res = stats.nct.pdf(5, np.arange(4, 7)[:, None],
  4270. np.linspace(0.1, 1, 4))
  4271. expected = array([[0.00321886, 0.00557466, 0.00918418, 0.01442997],
  4272. [0.00217142, 0.00395366, 0.00683888, 0.01126276],
  4273. [0.00153078, 0.00291093, 0.00525206, 0.00900815]])
  4274. assert_allclose(res, expected, rtol=1e-5)
  4275. def test_variance_gh_issue_2401(self):
  4276. # Computation of the variance of a non-central t-distribution resulted
  4277. # in a TypeError: ufunc 'isinf' not supported for the input types,
  4278. # and the inputs could not be safely coerced to any supported types
  4279. # according to the casting rule 'safe'
  4280. rv = stats.nct(4, 0)
  4281. assert_equal(rv.var(), 2.0)
  4282. def test_nct_inf_moments(self):
  4283. # n-th moment of nct only exists for df > n
  4284. m, v, s, k = stats.nct.stats(df=0.9, nc=0.3, moments='mvsk')
  4285. assert_equal([m, v, s, k], [np.nan, np.nan, np.nan, np.nan])
  4286. m, v, s, k = stats.nct.stats(df=1.9, nc=0.3, moments='mvsk')
  4287. assert_(np.isfinite(m))
  4288. assert_equal([v, s, k], [np.nan, np.nan, np.nan])
  4289. m, v, s, k = stats.nct.stats(df=3.1, nc=0.3, moments='mvsk')
  4290. assert_(np.isfinite([m, v, s]).all())
  4291. assert_equal(k, np.nan)
  4292. def test_nct_stats_large_df_values(self):
  4293. # previously gamma function was used which lost precision at df=345
  4294. # cf. https://github.com/scipy/scipy/issues/12919 for details
  4295. nct_mean_df_1000 = stats.nct.mean(1000, 2)
  4296. nct_stats_df_1000 = stats.nct.stats(1000, 2)
  4297. # These expected values were computed with mpmath. They were also
  4298. # verified with the Wolfram Alpha expressions:
  4299. # Mean[NoncentralStudentTDistribution[1000, 2]]
  4300. # Var[NoncentralStudentTDistribution[1000, 2]]
  4301. expected_stats_df_1000 = [2.0015015641422464, 1.0040115288163005]
  4302. assert_allclose(nct_mean_df_1000, expected_stats_df_1000[0],
  4303. rtol=1e-10)
  4304. assert_allclose(nct_stats_df_1000, expected_stats_df_1000,
  4305. rtol=1e-10)
  4306. # and a bigger df value
  4307. nct_mean = stats.nct.mean(100000, 2)
  4308. nct_stats = stats.nct.stats(100000, 2)
  4309. # These expected values were computed with mpmath.
  4310. expected_stats = [2.0000150001562518, 1.0000400011500288]
  4311. assert_allclose(nct_mean, expected_stats[0], rtol=1e-10)
  4312. assert_allclose(nct_stats, expected_stats, rtol=1e-9)
  4313. class TestRecipInvGauss:
  4314. def test_pdf_endpoint(self):
  4315. p = stats.recipinvgauss.pdf(0, 0.6)
  4316. assert p == 0.0
  4317. def test_logpdf_endpoint(self):
  4318. logp = stats.recipinvgauss.logpdf(0, 0.6)
  4319. assert logp == -np.inf
  4320. def test_cdf_small_x(self):
  4321. # The expected value was computer with mpmath:
  4322. #
  4323. # import mpmath
  4324. #
  4325. # mpmath.mp.dps = 100
  4326. #
  4327. # def recipinvgauss_cdf_mp(x, mu):
  4328. # x = mpmath.mpf(x)
  4329. # mu = mpmath.mpf(mu)
  4330. # trm1 = 1/mu - x
  4331. # trm2 = 1/mu + x
  4332. # isqx = 1/mpmath.sqrt(x)
  4333. # return (mpmath.ncdf(-isqx*trm1)
  4334. # - mpmath.exp(2/mu)*mpmath.ncdf(-isqx*trm2))
  4335. #
  4336. p = stats.recipinvgauss.cdf(0.05, 0.5)
  4337. expected = 6.590396159501331e-20
  4338. assert_allclose(p, expected, rtol=1e-14)
  4339. def test_sf_large_x(self):
  4340. # The expected value was computed with mpmath; see test_cdf_small.
  4341. p = stats.recipinvgauss.sf(80, 0.5)
  4342. expected = 2.699819200556787e-18
  4343. assert_allclose(p, expected, 5e-15)
  4344. class TestRice:
  4345. def test_rice_zero_b(self):
  4346. # rice distribution should work with b=0, cf gh-2164
  4347. x = [0.2, 1., 5.]
  4348. assert_(np.isfinite(stats.rice.pdf(x, b=0.)).all())
  4349. assert_(np.isfinite(stats.rice.logpdf(x, b=0.)).all())
  4350. assert_(np.isfinite(stats.rice.cdf(x, b=0.)).all())
  4351. assert_(np.isfinite(stats.rice.logcdf(x, b=0.)).all())
  4352. q = [0.1, 0.1, 0.5, 0.9]
  4353. assert_(np.isfinite(stats.rice.ppf(q, b=0.)).all())
  4354. mvsk = stats.rice.stats(0, moments='mvsk')
  4355. assert_(np.isfinite(mvsk).all())
  4356. # furthermore, pdf is continuous as b\to 0
  4357. # rice.pdf(x, b\to 0) = x exp(-x^2/2) + O(b^2)
  4358. # see e.g. Abramovich & Stegun 9.6.7 & 9.6.10
  4359. b = 1e-8
  4360. assert_allclose(stats.rice.pdf(x, 0), stats.rice.pdf(x, b),
  4361. atol=b, rtol=0)
  4362. def test_rice_rvs(self):
  4363. rvs = stats.rice.rvs
  4364. assert_equal(rvs(b=3.).size, 1)
  4365. assert_equal(rvs(b=3., size=(3, 5)).shape, (3, 5))
  4366. def test_rice_gh9836(self):
  4367. # test that gh-9836 is resolved; previously jumped to 1 at the end
  4368. cdf = stats.rice.cdf(np.arange(10, 160, 10), np.arange(10, 160, 10))
  4369. # Generated in R
  4370. # library(VGAM)
  4371. # options(digits=16)
  4372. # x = seq(10, 150, 10)
  4373. # print(price(x, sigma=1, vee=x))
  4374. cdf_exp = [0.4800278103504522, 0.4900233218590353, 0.4933500379379548,
  4375. 0.4950128317658719, 0.4960103776798502, 0.4966753655438764,
  4376. 0.4971503395812474, 0.4975065620443196, 0.4977836197921638,
  4377. 0.4980052636649550, 0.4981866072661382, 0.4983377260666599,
  4378. 0.4984655952615694, 0.4985751970541413, 0.4986701850071265]
  4379. assert_allclose(cdf, cdf_exp)
  4380. probabilities = np.arange(0.1, 1, 0.1)
  4381. ppf = stats.rice.ppf(probabilities, 500/4, scale=4)
  4382. # Generated in R
  4383. # library(VGAM)
  4384. # options(digits=16)
  4385. # p = seq(0.1, .9, by = .1)
  4386. # print(qrice(p, vee = 500, sigma = 4))
  4387. ppf_exp = [494.8898762347361, 496.6495690858350, 497.9184315188069,
  4388. 499.0026277378915, 500.0159999146250, 501.0293721352668,
  4389. 502.1135684981884, 503.3824312270405, 505.1421247157822]
  4390. assert_allclose(ppf, ppf_exp)
  4391. ppf = scipy.stats.rice.ppf(0.5, np.arange(10, 150, 10))
  4392. # Generated in R
  4393. # library(VGAM)
  4394. # options(digits=16)
  4395. # b <- seq(10, 140, 10)
  4396. # print(qrice(0.5, vee = b, sigma = 1))
  4397. ppf_exp = [10.04995862522287, 20.02499480078302, 30.01666512465732,
  4398. 40.01249934924363, 50.00999966676032, 60.00833314046875,
  4399. 70.00714273568241, 80.00624991862573, 90.00555549840364,
  4400. 100.00499995833597, 110.00454542324384, 120.00416664255323,
  4401. 130.00384613488120, 140.00357141338748]
  4402. assert_allclose(ppf, ppf_exp)
  4403. class TestErlang:
  4404. def setup_method(self):
  4405. np.random.seed(1234)
  4406. def test_erlang_runtimewarning(self):
  4407. # erlang should generate a RuntimeWarning if a non-integer
  4408. # shape parameter is used.
  4409. with warnings.catch_warnings():
  4410. warnings.simplefilter("error", RuntimeWarning)
  4411. # The non-integer shape parameter 1.3 should trigger a
  4412. # RuntimeWarning
  4413. assert_raises(RuntimeWarning,
  4414. stats.erlang.rvs, 1.3, loc=0, scale=1, size=4)
  4415. # Calling the fit method with `f0` set to an integer should
  4416. # *not* trigger a RuntimeWarning. It should return the same
  4417. # values as gamma.fit(...).
  4418. data = [0.5, 1.0, 2.0, 4.0]
  4419. result_erlang = stats.erlang.fit(data, f0=1)
  4420. result_gamma = stats.gamma.fit(data, f0=1)
  4421. assert_allclose(result_erlang, result_gamma, rtol=1e-3)
  4422. def test_gh_pr_10949_argcheck(self):
  4423. assert_equal(stats.erlang.pdf(0.5, a=[1, -1]),
  4424. stats.gamma.pdf(0.5, a=[1, -1]))
  4425. class TestRayleigh:
  4426. def setup_method(self):
  4427. np.random.seed(987654321)
  4428. # gh-6227
  4429. def test_logpdf(self):
  4430. y = stats.rayleigh.logpdf(50)
  4431. assert_allclose(y, -1246.0879769945718)
  4432. def test_logsf(self):
  4433. y = stats.rayleigh.logsf(50)
  4434. assert_allclose(y, -1250)
  4435. @pytest.mark.parametrize("rvs_loc,rvs_scale", [(0.85373171, 0.86932204),
  4436. (0.20558821, 0.61621008)])
  4437. def test_fit(self, rvs_loc, rvs_scale):
  4438. data = stats.rayleigh.rvs(size=250, loc=rvs_loc, scale=rvs_scale)
  4439. def scale_mle(data, floc):
  4440. return (np.sum((data - floc) ** 2) / (2 * len(data))) ** .5
  4441. # when `floc` is provided, `scale` is found with an analytical formula
  4442. scale_expect = scale_mle(data, rvs_loc)
  4443. loc, scale = stats.rayleigh.fit(data, floc=rvs_loc)
  4444. assert_equal(loc, rvs_loc)
  4445. assert_equal(scale, scale_expect)
  4446. # when `fscale` is fixed, superclass fit is used to determine `loc`.
  4447. loc, scale = stats.rayleigh.fit(data, fscale=.6)
  4448. assert_equal(scale, .6)
  4449. # with both parameters free, one dimensional optimization is done
  4450. # over a new function that takes into account the dependent relation
  4451. # of `scale` to `loc`.
  4452. loc, scale = stats.rayleigh.fit(data)
  4453. # test that `scale` is defined by its relation to `loc`
  4454. assert_equal(scale, scale_mle(data, loc))
  4455. @pytest.mark.parametrize("rvs_loc,rvs_scale", [[0.74, 0.01],
  4456. [0.08464463, 0.12069025]])
  4457. def test_fit_comparison_super_method(self, rvs_loc, rvs_scale):
  4458. # test that the objective function result of the analytical MLEs is
  4459. # less than or equal to that of the numerically optimized estimate
  4460. data = stats.rayleigh.rvs(size=250, loc=rvs_loc, scale=rvs_scale)
  4461. # obtain objective function with same method as `rv_continuous.fit`
  4462. args = [data, (stats.rayleigh._fitstart(data), )]
  4463. func = stats.rayleigh._reduce_func(args, {})[1]
  4464. _assert_less_or_close_loglike(stats.rayleigh, data, func)
  4465. def test_fit_warnings(self):
  4466. assert_fit_warnings(stats.rayleigh)
  4467. def test_fit_gh17088(self):
  4468. # `rayleigh.fit` could return a location that was inconsistent with
  4469. # the data. See gh-17088.
  4470. rng = np.random.default_rng(456)
  4471. loc, scale, size = 50, 600, 500
  4472. rvs = stats.rayleigh.rvs(loc, scale, size=size, random_state=rng)
  4473. loc_fit, _ = stats.rayleigh.fit(rvs)
  4474. assert loc_fit < np.min(rvs)
  4475. loc_fit, scale_fit = stats.rayleigh.fit(rvs, fscale=scale)
  4476. assert loc_fit < np.min(rvs)
  4477. assert scale_fit == scale
  4478. class TestExponWeib:
  4479. def test_pdf_logpdf(self):
  4480. # Regression test for gh-3508.
  4481. x = 0.1
  4482. a = 1.0
  4483. c = 100.0
  4484. p = stats.exponweib.pdf(x, a, c)
  4485. logp = stats.exponweib.logpdf(x, a, c)
  4486. # Expected values were computed with mpmath.
  4487. assert_allclose([p, logp],
  4488. [1.0000000000000054e-97, -223.35075402042244])
  4489. def test_a_is_1(self):
  4490. # For issue gh-3508.
  4491. # Check that when a=1, the pdf and logpdf methods of exponweib are the
  4492. # same as those of weibull_min.
  4493. x = np.logspace(-4, -1, 4)
  4494. a = 1
  4495. c = 100
  4496. p = stats.exponweib.pdf(x, a, c)
  4497. expected = stats.weibull_min.pdf(x, c)
  4498. assert_allclose(p, expected)
  4499. logp = stats.exponweib.logpdf(x, a, c)
  4500. expected = stats.weibull_min.logpdf(x, c)
  4501. assert_allclose(logp, expected)
  4502. def test_a_is_1_c_is_1(self):
  4503. # When a = 1 and c = 1, the distribution is exponential.
  4504. x = np.logspace(-8, 1, 10)
  4505. a = 1
  4506. c = 1
  4507. p = stats.exponweib.pdf(x, a, c)
  4508. expected = stats.expon.pdf(x)
  4509. assert_allclose(p, expected)
  4510. logp = stats.exponweib.logpdf(x, a, c)
  4511. expected = stats.expon.logpdf(x)
  4512. assert_allclose(logp, expected)
  4513. class TestFatigueLife:
  4514. def test_sf_tail(self):
  4515. # Expected value computed with mpmath:
  4516. # import mpmath
  4517. # mpmath.mp.dps = 80
  4518. # x = mpmath.mpf(800.0)
  4519. # c = mpmath.mpf(2.5)
  4520. # s = float(1 - mpmath.ncdf(1/c * (mpmath.sqrt(x)
  4521. # - 1/mpmath.sqrt(x))))
  4522. # print(s)
  4523. # Output:
  4524. # 6.593376447038406e-30
  4525. s = stats.fatiguelife.sf(800.0, 2.5)
  4526. assert_allclose(s, 6.593376447038406e-30, rtol=1e-13)
  4527. def test_isf_tail(self):
  4528. # See test_sf_tail for the mpmath code.
  4529. p = 6.593376447038406e-30
  4530. q = stats.fatiguelife.isf(p, 2.5)
  4531. assert_allclose(q, 800.0, rtol=1e-13)
  4532. class TestWeibull:
  4533. def test_logpdf(self):
  4534. # gh-6217
  4535. y = stats.weibull_min.logpdf(0, 1)
  4536. assert_equal(y, 0)
  4537. def test_with_maxima_distrib(self):
  4538. # Tests for weibull_min and weibull_max.
  4539. # The expected values were computed using the symbolic algebra
  4540. # program 'maxima' with the package 'distrib', which has
  4541. # 'pdf_weibull' and 'cdf_weibull'. The mapping between the
  4542. # scipy and maxima functions is as follows:
  4543. # -----------------------------------------------------------------
  4544. # scipy maxima
  4545. # --------------------------------- ------------------------------
  4546. # weibull_min.pdf(x, a, scale=b) pdf_weibull(x, a, b)
  4547. # weibull_min.logpdf(x, a, scale=b) log(pdf_weibull(x, a, b))
  4548. # weibull_min.cdf(x, a, scale=b) cdf_weibull(x, a, b)
  4549. # weibull_min.logcdf(x, a, scale=b) log(cdf_weibull(x, a, b))
  4550. # weibull_min.sf(x, a, scale=b) 1 - cdf_weibull(x, a, b)
  4551. # weibull_min.logsf(x, a, scale=b) log(1 - cdf_weibull(x, a, b))
  4552. #
  4553. # weibull_max.pdf(x, a, scale=b) pdf_weibull(-x, a, b)
  4554. # weibull_max.logpdf(x, a, scale=b) log(pdf_weibull(-x, a, b))
  4555. # weibull_max.cdf(x, a, scale=b) 1 - cdf_weibull(-x, a, b)
  4556. # weibull_max.logcdf(x, a, scale=b) log(1 - cdf_weibull(-x, a, b))
  4557. # weibull_max.sf(x, a, scale=b) cdf_weibull(-x, a, b)
  4558. # weibull_max.logsf(x, a, scale=b) log(cdf_weibull(-x, a, b))
  4559. # -----------------------------------------------------------------
  4560. x = 1.5
  4561. a = 2.0
  4562. b = 3.0
  4563. # weibull_min
  4564. p = stats.weibull_min.pdf(x, a, scale=b)
  4565. assert_allclose(p, np.exp(-0.25)/3)
  4566. lp = stats.weibull_min.logpdf(x, a, scale=b)
  4567. assert_allclose(lp, -0.25 - np.log(3))
  4568. c = stats.weibull_min.cdf(x, a, scale=b)
  4569. assert_allclose(c, -special.expm1(-0.25))
  4570. lc = stats.weibull_min.logcdf(x, a, scale=b)
  4571. assert_allclose(lc, np.log(-special.expm1(-0.25)))
  4572. s = stats.weibull_min.sf(x, a, scale=b)
  4573. assert_allclose(s, np.exp(-0.25))
  4574. ls = stats.weibull_min.logsf(x, a, scale=b)
  4575. assert_allclose(ls, -0.25)
  4576. # Also test using a large value x, for which computing the survival
  4577. # function using the CDF would result in 0.
  4578. s = stats.weibull_min.sf(30, 2, scale=3)
  4579. assert_allclose(s, np.exp(-100))
  4580. ls = stats.weibull_min.logsf(30, 2, scale=3)
  4581. assert_allclose(ls, -100)
  4582. # weibull_max
  4583. x = -1.5
  4584. p = stats.weibull_max.pdf(x, a, scale=b)
  4585. assert_allclose(p, np.exp(-0.25)/3)
  4586. lp = stats.weibull_max.logpdf(x, a, scale=b)
  4587. assert_allclose(lp, -0.25 - np.log(3))
  4588. c = stats.weibull_max.cdf(x, a, scale=b)
  4589. assert_allclose(c, np.exp(-0.25))
  4590. lc = stats.weibull_max.logcdf(x, a, scale=b)
  4591. assert_allclose(lc, -0.25)
  4592. s = stats.weibull_max.sf(x, a, scale=b)
  4593. assert_allclose(s, -special.expm1(-0.25))
  4594. ls = stats.weibull_max.logsf(x, a, scale=b)
  4595. assert_allclose(ls, np.log(-special.expm1(-0.25)))
  4596. # Also test using a value of x close to 0, for which computing the
  4597. # survival function using the CDF would result in 0.
  4598. s = stats.weibull_max.sf(-1e-9, 2, scale=3)
  4599. assert_allclose(s, -special.expm1(-1/9000000000000000000))
  4600. ls = stats.weibull_max.logsf(-1e-9, 2, scale=3)
  4601. assert_allclose(ls, np.log(-special.expm1(-1/9000000000000000000)))
  4602. def test_fit_min(self):
  4603. rng = np.random.default_rng(5985959307161735394)
  4604. c, loc, scale = 2, 3.5, 0.5 # arbitrary, valid parameters
  4605. dist = stats.weibull_min(c, loc, scale)
  4606. rvs = dist.rvs(size=100, random_state=rng)
  4607. # test that MLE still honors guesses and fixed parameters
  4608. c2, loc2, scale2 = stats.weibull_min.fit(rvs, 1.5, floc=3)
  4609. c3, loc3, scale3 = stats.weibull_min.fit(rvs, 1.6, floc=3)
  4610. assert loc2 == loc3 == 3 # fixed parameter is respected
  4611. assert c2 != c3 # different guess -> (slightly) different outcome
  4612. # quality of fit is tested elsewhere
  4613. # test that MoM honors fixed parameters, accepts (but ignores) guesses
  4614. c4, loc4, scale4 = stats.weibull_min.fit(rvs, 3, fscale=3, method='mm')
  4615. assert scale4 == 3
  4616. # because scale was fixed, only the mean and skewness will be matched
  4617. dist4 = stats.weibull_min(c4, loc4, scale4)
  4618. res = dist4.stats(moments='ms')
  4619. ref = np.mean(rvs), stats.skew(rvs)
  4620. assert_allclose(res, ref)
  4621. class TestTruncWeibull(object):
  4622. def test_pdf_bounds(self):
  4623. # test bounds
  4624. y = stats.truncweibull_min.pdf([0.1, 2.0], 2.0, 0.11, 1.99)
  4625. assert_equal(y, [0.0, 0.0])
  4626. def test_logpdf(self):
  4627. y = stats.truncweibull_min.logpdf(2.0, 1.0, 2.0, np.inf)
  4628. assert_equal(y, 0.0)
  4629. # hand calculation
  4630. y = stats.truncweibull_min.logpdf(2.0, 1.0, 2.0, 4.0)
  4631. assert_allclose(y, 0.14541345786885884)
  4632. def test_ppf_bounds(self):
  4633. # test bounds
  4634. y = stats.truncweibull_min.ppf([0.0, 1.0], 2.0, 0.1, 2.0)
  4635. assert_equal(y, [0.1, 2.0])
  4636. def test_cdf_to_ppf(self):
  4637. q = [0., 0.1, .25, 0.50, 0.75, 0.90, 1.]
  4638. x = stats.truncweibull_min.ppf(q, 2., 0., 3.)
  4639. q_out = stats.truncweibull_min.cdf(x, 2., 0., 3.)
  4640. assert_allclose(q, q_out)
  4641. def test_sf_to_isf(self):
  4642. q = [0., 0.1, .25, 0.50, 0.75, 0.90, 1.]
  4643. x = stats.truncweibull_min.isf(q, 2., 0., 3.)
  4644. q_out = stats.truncweibull_min.sf(x, 2., 0., 3.)
  4645. assert_allclose(q, q_out)
  4646. def test_munp(self):
  4647. c = 2.
  4648. a = 1.
  4649. b = 3.
  4650. def xnpdf(x, n):
  4651. return x**n*stats.truncweibull_min.pdf(x, c, a, b)
  4652. m0 = stats.truncweibull_min.moment(0, c, a, b)
  4653. assert_equal(m0, 1.)
  4654. m1 = stats.truncweibull_min.moment(1, c, a, b)
  4655. m1_expected, _ = quad(lambda x: xnpdf(x, 1), a, b)
  4656. assert_allclose(m1, m1_expected)
  4657. m2 = stats.truncweibull_min.moment(2, c, a, b)
  4658. m2_expected, _ = quad(lambda x: xnpdf(x, 2), a, b)
  4659. assert_allclose(m2, m2_expected)
  4660. m3 = stats.truncweibull_min.moment(3, c, a, b)
  4661. m3_expected, _ = quad(lambda x: xnpdf(x, 3), a, b)
  4662. assert_allclose(m3, m3_expected)
  4663. m4 = stats.truncweibull_min.moment(4, c, a, b)
  4664. m4_expected, _ = quad(lambda x: xnpdf(x, 4), a, b)
  4665. assert_allclose(m4, m4_expected)
  4666. def test_reference_values(self):
  4667. a = 1.
  4668. b = 3.
  4669. c = 2.
  4670. x_med = np.sqrt(1 - np.log(0.5 + np.exp(-(8. + np.log(2.)))))
  4671. cdf = stats.truncweibull_min.cdf(x_med, c, a, b)
  4672. assert_allclose(cdf, 0.5)
  4673. lc = stats.truncweibull_min.logcdf(x_med, c, a, b)
  4674. assert_allclose(lc, -np.log(2.))
  4675. ppf = stats.truncweibull_min.ppf(0.5, c, a, b)
  4676. assert_allclose(ppf, x_med)
  4677. sf = stats.truncweibull_min.sf(x_med, c, a, b)
  4678. assert_allclose(sf, 0.5)
  4679. ls = stats.truncweibull_min.logsf(x_med, c, a, b)
  4680. assert_allclose(ls, -np.log(2.))
  4681. isf = stats.truncweibull_min.isf(0.5, c, a, b)
  4682. assert_allclose(isf, x_med)
  4683. def test_compare_weibull_min(self):
  4684. # Verify that the truncweibull_min distribution gives the same results
  4685. # as the original weibull_min
  4686. x = 1.5
  4687. c = 2.0
  4688. a = 0.0
  4689. b = np.inf
  4690. scale = 3.0
  4691. p = stats.weibull_min.pdf(x, c, scale=scale)
  4692. p_trunc = stats.truncweibull_min.pdf(x, c, a, b, scale=scale)
  4693. assert_allclose(p, p_trunc)
  4694. lp = stats.weibull_min.logpdf(x, c, scale=scale)
  4695. lp_trunc = stats.truncweibull_min.logpdf(x, c, a, b, scale=scale)
  4696. assert_allclose(lp, lp_trunc)
  4697. cdf = stats.weibull_min.cdf(x, c, scale=scale)
  4698. cdf_trunc = stats.truncweibull_min.cdf(x, c, a, b, scale=scale)
  4699. assert_allclose(cdf, cdf_trunc)
  4700. lc = stats.weibull_min.logcdf(x, c, scale=scale)
  4701. lc_trunc = stats.truncweibull_min.logcdf(x, c, a, b, scale=scale)
  4702. assert_allclose(lc, lc_trunc)
  4703. s = stats.weibull_min.sf(x, c, scale=scale)
  4704. s_trunc = stats.truncweibull_min.sf(x, c, a, b, scale=scale)
  4705. assert_allclose(s, s_trunc)
  4706. ls = stats.weibull_min.logsf(x, c, scale=scale)
  4707. ls_trunc = stats.truncweibull_min.logsf(x, c, a, b, scale=scale)
  4708. assert_allclose(ls, ls_trunc)
  4709. # # Also test using a large value x, for which computing the survival
  4710. # # function using the CDF would result in 0.
  4711. s = stats.truncweibull_min.sf(30, 2, a, b, scale=3)
  4712. assert_allclose(s, np.exp(-100))
  4713. ls = stats.truncweibull_min.logsf(30, 2, a, b, scale=3)
  4714. assert_allclose(ls, -100)
  4715. def test_compare_weibull_min2(self):
  4716. # Verify that the truncweibull_min distribution PDF and CDF results
  4717. # are the same as those calculated from truncating weibull_min
  4718. c, a, b = 2.5, 0.25, 1.25
  4719. x = np.linspace(a, b, 100)
  4720. pdf1 = stats.truncweibull_min.pdf(x, c, a, b)
  4721. cdf1 = stats.truncweibull_min.cdf(x, c, a, b)
  4722. norm = stats.weibull_min.cdf(b, c) - stats.weibull_min.cdf(a, c)
  4723. pdf2 = stats.weibull_min.pdf(x, c) / norm
  4724. cdf2 = (stats.weibull_min.cdf(x, c) - stats.weibull_min.cdf(a, c))/norm
  4725. np.testing.assert_allclose(pdf1, pdf2)
  4726. np.testing.assert_allclose(cdf1, cdf2)
  4727. class TestRdist:
  4728. def test_rdist_cdf_gh1285(self):
  4729. # check workaround in rdist._cdf for issue gh-1285.
  4730. distfn = stats.rdist
  4731. values = [0.001, 0.5, 0.999]
  4732. assert_almost_equal(distfn.cdf(distfn.ppf(values, 541.0), 541.0),
  4733. values, decimal=5)
  4734. def test_rdist_beta(self):
  4735. # rdist is a special case of stats.beta
  4736. x = np.linspace(-0.99, 0.99, 10)
  4737. c = 2.7
  4738. assert_almost_equal(0.5*stats.beta(c/2, c/2).pdf((x + 1)/2),
  4739. stats.rdist(c).pdf(x))
  4740. class TestTrapezoid:
  4741. def test_reduces_to_triang(self):
  4742. modes = [0, 0.3, 0.5, 1]
  4743. for mode in modes:
  4744. x = [0, mode, 1]
  4745. assert_almost_equal(stats.trapezoid.pdf(x, mode, mode),
  4746. stats.triang.pdf(x, mode))
  4747. assert_almost_equal(stats.trapezoid.cdf(x, mode, mode),
  4748. stats.triang.cdf(x, mode))
  4749. def test_reduces_to_uniform(self):
  4750. x = np.linspace(0, 1, 10)
  4751. assert_almost_equal(stats.trapezoid.pdf(x, 0, 1), stats.uniform.pdf(x))
  4752. assert_almost_equal(stats.trapezoid.cdf(x, 0, 1), stats.uniform.cdf(x))
  4753. def test_cases(self):
  4754. # edge cases
  4755. assert_almost_equal(stats.trapezoid.pdf(0, 0, 0), 2)
  4756. assert_almost_equal(stats.trapezoid.pdf(1, 1, 1), 2)
  4757. assert_almost_equal(stats.trapezoid.pdf(0.5, 0, 0.8),
  4758. 1.11111111111111111)
  4759. assert_almost_equal(stats.trapezoid.pdf(0.5, 0.2, 1.0),
  4760. 1.11111111111111111)
  4761. # straightforward case
  4762. assert_almost_equal(stats.trapezoid.pdf(0.1, 0.2, 0.8), 0.625)
  4763. assert_almost_equal(stats.trapezoid.pdf(0.5, 0.2, 0.8), 1.25)
  4764. assert_almost_equal(stats.trapezoid.pdf(0.9, 0.2, 0.8), 0.625)
  4765. assert_almost_equal(stats.trapezoid.cdf(0.1, 0.2, 0.8), 0.03125)
  4766. assert_almost_equal(stats.trapezoid.cdf(0.2, 0.2, 0.8), 0.125)
  4767. assert_almost_equal(stats.trapezoid.cdf(0.5, 0.2, 0.8), 0.5)
  4768. assert_almost_equal(stats.trapezoid.cdf(0.9, 0.2, 0.8), 0.96875)
  4769. assert_almost_equal(stats.trapezoid.cdf(1.0, 0.2, 0.8), 1.0)
  4770. def test_moments_and_entropy(self):
  4771. # issue #11795: improve precision of trapezoid stats
  4772. # Apply formulas from Wikipedia for the following parameters:
  4773. a, b, c, d = -3, -1, 2, 3 # => 1/3, 5/6, -3, 6
  4774. p1, p2, loc, scale = (b-a) / (d-a), (c-a) / (d-a), a, d-a
  4775. h = 2 / (d+c-b-a)
  4776. def moment(n):
  4777. return (h * ((d**(n+2) - c**(n+2)) / (d-c)
  4778. - (b**(n+2) - a**(n+2)) / (b-a)) /
  4779. (n+1) / (n+2))
  4780. mean = moment(1)
  4781. var = moment(2) - mean**2
  4782. entropy = 0.5 * (d-c+b-a) / (d+c-b-a) + np.log(0.5 * (d+c-b-a))
  4783. assert_almost_equal(stats.trapezoid.mean(p1, p2, loc, scale),
  4784. mean, decimal=13)
  4785. assert_almost_equal(stats.trapezoid.var(p1, p2, loc, scale),
  4786. var, decimal=13)
  4787. assert_almost_equal(stats.trapezoid.entropy(p1, p2, loc, scale),
  4788. entropy, decimal=13)
  4789. # Check boundary cases where scipy d=0 or d=1.
  4790. assert_almost_equal(stats.trapezoid.mean(0, 0, -3, 6), -1, decimal=13)
  4791. assert_almost_equal(stats.trapezoid.mean(0, 1, -3, 6), 0, decimal=13)
  4792. assert_almost_equal(stats.trapezoid.var(0, 1, -3, 6), 3, decimal=13)
  4793. def test_trapezoid_vect(self):
  4794. # test that array-valued shapes and arguments are handled
  4795. c = np.array([0.1, 0.2, 0.3])
  4796. d = np.array([0.5, 0.6])[:, None]
  4797. x = np.array([0.15, 0.25, 0.9])
  4798. v = stats.trapezoid.pdf(x, c, d)
  4799. cc, dd, xx = np.broadcast_arrays(c, d, x)
  4800. res = np.empty(xx.size, dtype=xx.dtype)
  4801. ind = np.arange(xx.size)
  4802. for i, x1, c1, d1 in zip(ind, xx.ravel(), cc.ravel(), dd.ravel()):
  4803. res[i] = stats.trapezoid.pdf(x1, c1, d1)
  4804. assert_allclose(v, res.reshape(v.shape), atol=1e-15)
  4805. # Check that the stats() method supports vector arguments.
  4806. v = np.asarray(stats.trapezoid.stats(c, d, moments="mvsk"))
  4807. cc, dd = np.broadcast_arrays(c, d)
  4808. res = np.empty((cc.size, 4)) # 4 stats returned per value
  4809. ind = np.arange(cc.size)
  4810. for i, c1, d1 in zip(ind, cc.ravel(), dd.ravel()):
  4811. res[i] = stats.trapezoid.stats(c1, d1, moments="mvsk")
  4812. assert_allclose(v, res.T.reshape(v.shape), atol=1e-15)
  4813. def test_trapz(self):
  4814. # Basic test for alias
  4815. x = np.linspace(0, 1, 10)
  4816. assert_almost_equal(stats.trapz.pdf(x, 0, 1), stats.uniform.pdf(x))
  4817. class TestTriang:
  4818. def test_edge_cases(self):
  4819. with np.errstate(all='raise'):
  4820. assert_equal(stats.triang.pdf(0, 0), 2.)
  4821. assert_equal(stats.triang.pdf(0.5, 0), 1.)
  4822. assert_equal(stats.triang.pdf(1, 0), 0.)
  4823. assert_equal(stats.triang.pdf(0, 1), 0)
  4824. assert_equal(stats.triang.pdf(0.5, 1), 1.)
  4825. assert_equal(stats.triang.pdf(1, 1), 2)
  4826. assert_equal(stats.triang.cdf(0., 0.), 0.)
  4827. assert_equal(stats.triang.cdf(0.5, 0.), 0.75)
  4828. assert_equal(stats.triang.cdf(1.0, 0.), 1.0)
  4829. assert_equal(stats.triang.cdf(0., 1.), 0.)
  4830. assert_equal(stats.triang.cdf(0.5, 1.), 0.25)
  4831. assert_equal(stats.triang.cdf(1., 1.), 1)
  4832. class TestMielke:
  4833. def test_moments(self):
  4834. k, s = 4.642, 0.597
  4835. # n-th moment exists only if n < s
  4836. assert_equal(stats.mielke(k, s).moment(1), np.inf)
  4837. assert_equal(stats.mielke(k, 1.0).moment(1), np.inf)
  4838. assert_(np.isfinite(stats.mielke(k, 1.01).moment(1)))
  4839. def test_burr_equivalence(self):
  4840. x = np.linspace(0.01, 100, 50)
  4841. k, s = 2.45, 5.32
  4842. assert_allclose(stats.burr.pdf(x, s, k/s), stats.mielke.pdf(x, k, s))
  4843. class TestBurr:
  4844. def test_endpoints_7491(self):
  4845. # gh-7491
  4846. # Compute the pdf at the left endpoint dst.a.
  4847. data = [
  4848. [stats.fisk, (1,), 1],
  4849. [stats.burr, (0.5, 2), 1],
  4850. [stats.burr, (1, 1), 1],
  4851. [stats.burr, (2, 0.5), 1],
  4852. [stats.burr12, (1, 0.5), 0.5],
  4853. [stats.burr12, (1, 1), 1.0],
  4854. [stats.burr12, (1, 2), 2.0]]
  4855. ans = [_f.pdf(_f.a, *_args) for _f, _args, _ in data]
  4856. correct = [_correct_ for _f, _args, _correct_ in data]
  4857. assert_array_almost_equal(ans, correct)
  4858. ans = [_f.logpdf(_f.a, *_args) for _f, _args, _ in data]
  4859. correct = [np.log(_correct_) for _f, _args, _correct_ in data]
  4860. assert_array_almost_equal(ans, correct)
  4861. def test_burr_stats_9544(self):
  4862. # gh-9544. Test from gh-9978
  4863. c, d = 5.0, 3
  4864. mean, variance = stats.burr(c, d).stats()
  4865. # mean = sc.beta(3 + 1/5, 1. - 1/5) * 3 = 1.4110263...
  4866. # var = sc.beta(3 + 2 / 5, 1. - 2 / 5) * 3 -
  4867. # (sc.beta(3 + 1 / 5, 1. - 1 / 5) * 3) ** 2
  4868. mean_hc, variance_hc = 1.4110263183925857, 0.22879948026191643
  4869. assert_allclose(mean, mean_hc)
  4870. assert_allclose(variance, variance_hc)
  4871. def test_burr_nan_mean_var_9544(self):
  4872. # gh-9544. Test from gh-9978
  4873. c, d = 0.5, 3
  4874. mean, variance = stats.burr(c, d).stats()
  4875. assert_(np.isnan(mean))
  4876. assert_(np.isnan(variance))
  4877. c, d = 1.5, 3
  4878. mean, variance = stats.burr(c, d).stats()
  4879. assert_(np.isfinite(mean))
  4880. assert_(np.isnan(variance))
  4881. c, d = 0.5, 3
  4882. e1, e2, e3, e4 = stats.burr._munp(np.array([1, 2, 3, 4]), c, d)
  4883. assert_(np.isnan(e1))
  4884. assert_(np.isnan(e2))
  4885. assert_(np.isnan(e3))
  4886. assert_(np.isnan(e4))
  4887. c, d = 1.5, 3
  4888. e1, e2, e3, e4 = stats.burr._munp([1, 2, 3, 4], c, d)
  4889. assert_(np.isfinite(e1))
  4890. assert_(np.isnan(e2))
  4891. assert_(np.isnan(e3))
  4892. assert_(np.isnan(e4))
  4893. c, d = 2.5, 3
  4894. e1, e2, e3, e4 = stats.burr._munp([1, 2, 3, 4], c, d)
  4895. assert_(np.isfinite(e1))
  4896. assert_(np.isfinite(e2))
  4897. assert_(np.isnan(e3))
  4898. assert_(np.isnan(e4))
  4899. c, d = 3.5, 3
  4900. e1, e2, e3, e4 = stats.burr._munp([1, 2, 3, 4], c, d)
  4901. assert_(np.isfinite(e1))
  4902. assert_(np.isfinite(e2))
  4903. assert_(np.isfinite(e3))
  4904. assert_(np.isnan(e4))
  4905. c, d = 4.5, 3
  4906. e1, e2, e3, e4 = stats.burr._munp([1, 2, 3, 4], c, d)
  4907. assert_(np.isfinite(e1))
  4908. assert_(np.isfinite(e2))
  4909. assert_(np.isfinite(e3))
  4910. assert_(np.isfinite(e4))
  4911. class TestStudentizedRange:
  4912. # For alpha = .05, .01, and .001, and for each value of
  4913. # v = [1, 3, 10, 20, 120, inf], a Q was picked from each table for
  4914. # k = [2, 8, 14, 20].
  4915. # these arrays are written with `k` as column, and `v` as rows.
  4916. # Q values are taken from table 3:
  4917. # https://www.jstor.org/stable/2237810
  4918. q05 = [17.97, 45.40, 54.33, 59.56,
  4919. 4.501, 8.853, 10.35, 11.24,
  4920. 3.151, 5.305, 6.028, 6.467,
  4921. 2.950, 4.768, 5.357, 5.714,
  4922. 2.800, 4.363, 4.842, 5.126,
  4923. 2.772, 4.286, 4.743, 5.012]
  4924. q01 = [90.03, 227.2, 271.8, 298.0,
  4925. 8.261, 15.64, 18.22, 19.77,
  4926. 4.482, 6.875, 7.712, 8.226,
  4927. 4.024, 5.839, 6.450, 6.823,
  4928. 3.702, 5.118, 5.562, 5.827,
  4929. 3.643, 4.987, 5.400, 5.645]
  4930. q001 = [900.3, 2272, 2718, 2980,
  4931. 18.28, 34.12, 39.69, 43.05,
  4932. 6.487, 9.352, 10.39, 11.03,
  4933. 5.444, 7.313, 7.966, 8.370,
  4934. 4.772, 6.039, 6.448, 6.695,
  4935. 4.654, 5.823, 6.191, 6.411]
  4936. qs = np.concatenate((q05, q01, q001))
  4937. ps = [.95, .99, .999]
  4938. vs = [1, 3, 10, 20, 120, np.inf]
  4939. ks = [2, 8, 14, 20]
  4940. data = list(zip(product(ps, vs, ks), qs))
  4941. # A small selection of large-v cases generated with R's `ptukey`
  4942. # Each case is in the format (q, k, v, r_result)
  4943. r_data = [
  4944. (0.1, 3, 9001, 0.002752818526842),
  4945. (1, 10, 1000, 0.000526142388912),
  4946. (1, 3, np.inf, 0.240712641229283),
  4947. (4, 3, np.inf, 0.987012338626815),
  4948. (1, 10, np.inf, 0.000519869467083),
  4949. ]
  4950. def test_cdf_against_tables(self):
  4951. for pvk, q in self.data:
  4952. p_expected, v, k = pvk
  4953. res_p = stats.studentized_range.cdf(q, k, v)
  4954. assert_allclose(res_p, p_expected, rtol=1e-4)
  4955. @pytest.mark.slow
  4956. def test_ppf_against_tables(self):
  4957. for pvk, q_expected in self.data:
  4958. p, v, k = pvk
  4959. res_q = stats.studentized_range.ppf(p, k, v)
  4960. assert_allclose(res_q, q_expected, rtol=5e-4)
  4961. path_prefix = os.path.dirname(__file__)
  4962. relative_path = "data/studentized_range_mpmath_ref.json"
  4963. with open(os.path.join(path_prefix, relative_path), "r") as file:
  4964. pregenerated_data = json.load(file)
  4965. @pytest.mark.parametrize("case_result", pregenerated_data["cdf_data"])
  4966. def test_cdf_against_mp(self, case_result):
  4967. src_case = case_result["src_case"]
  4968. mp_result = case_result["mp_result"]
  4969. qkv = src_case["q"], src_case["k"], src_case["v"]
  4970. res = stats.studentized_range.cdf(*qkv)
  4971. assert_allclose(res, mp_result,
  4972. atol=src_case["expected_atol"],
  4973. rtol=src_case["expected_rtol"])
  4974. @pytest.mark.parametrize("case_result", pregenerated_data["pdf_data"])
  4975. def test_pdf_against_mp(self, case_result):
  4976. src_case = case_result["src_case"]
  4977. mp_result = case_result["mp_result"]
  4978. qkv = src_case["q"], src_case["k"], src_case["v"]
  4979. res = stats.studentized_range.pdf(*qkv)
  4980. assert_allclose(res, mp_result,
  4981. atol=src_case["expected_atol"],
  4982. rtol=src_case["expected_rtol"])
  4983. @pytest.mark.slow
  4984. @pytest.mark.xfail_on_32bit("intermittent RuntimeWarning: invalid value.")
  4985. @pytest.mark.parametrize("case_result", pregenerated_data["moment_data"])
  4986. def test_moment_against_mp(self, case_result):
  4987. src_case = case_result["src_case"]
  4988. mp_result = case_result["mp_result"]
  4989. mkv = src_case["m"], src_case["k"], src_case["v"]
  4990. # Silence invalid value encountered warnings. Actual problems will be
  4991. # caught by the result comparison.
  4992. with np.errstate(invalid='ignore'):
  4993. res = stats.studentized_range.moment(*mkv)
  4994. assert_allclose(res, mp_result,
  4995. atol=src_case["expected_atol"],
  4996. rtol=src_case["expected_rtol"])
  4997. def test_pdf_integration(self):
  4998. k, v = 3, 10
  4999. # Test whether PDF integration is 1 like it should be.
  5000. res = quad(stats.studentized_range.pdf, 0, np.inf, args=(k, v))
  5001. assert_allclose(res[0], 1)
  5002. @pytest.mark.xslow
  5003. def test_pdf_against_cdf(self):
  5004. k, v = 3, 10
  5005. # Test whether the integrated PDF matches the CDF using cumulative
  5006. # integration. Use a small step size to reduce error due to the
  5007. # summation. This is slow, but tests the results well.
  5008. x = np.arange(0, 10, step=0.01)
  5009. y_cdf = stats.studentized_range.cdf(x, k, v)[1:]
  5010. y_pdf_raw = stats.studentized_range.pdf(x, k, v)
  5011. y_pdf_cumulative = cumulative_trapezoid(y_pdf_raw, x)
  5012. # Because of error caused by the summation, use a relatively large rtol
  5013. assert_allclose(y_pdf_cumulative, y_cdf, rtol=1e-4)
  5014. @pytest.mark.parametrize("r_case_result", r_data)
  5015. def test_cdf_against_r(self, r_case_result):
  5016. # Test large `v` values using R
  5017. q, k, v, r_res = r_case_result
  5018. with np.errstate(invalid='ignore'):
  5019. res = stats.studentized_range.cdf(q, k, v)
  5020. assert_allclose(res, r_res)
  5021. @pytest.mark.slow
  5022. @pytest.mark.xfail_on_32bit("intermittent RuntimeWarning: invalid value.")
  5023. def test_moment_vectorization(self):
  5024. # Test moment broadcasting. Calls `_munp` directly because
  5025. # `rv_continuous.moment` is broken at time of writing. See gh-12192
  5026. # Silence invalid value encountered warnings. Actual problems will be
  5027. # caught by the result comparison.
  5028. with np.errstate(invalid='ignore'):
  5029. m = stats.studentized_range._munp([1, 2], [4, 5], [10, 11])
  5030. assert_allclose(m.shape, (2,))
  5031. with pytest.raises(ValueError, match="...could not be broadcast..."):
  5032. stats.studentized_range._munp(1, [4, 5], [10, 11, 12])
  5033. @pytest.mark.xslow
  5034. def test_fitstart_valid(self):
  5035. with suppress_warnings() as sup, np.errstate(invalid="ignore"):
  5036. # the integration warning message may differ
  5037. sup.filter(IntegrationWarning)
  5038. k, df, _, _ = stats.studentized_range._fitstart([1, 2, 3])
  5039. assert_(stats.studentized_range._argcheck(k, df))
  5040. def test_infinite_df(self):
  5041. # Check that the CDF and PDF infinite and normal integrators
  5042. # roughly match for a high df case
  5043. res = stats.studentized_range.pdf(3, 10, np.inf)
  5044. res_finite = stats.studentized_range.pdf(3, 10, 99999)
  5045. assert_allclose(res, res_finite, atol=1e-4, rtol=1e-4)
  5046. res = stats.studentized_range.cdf(3, 10, np.inf)
  5047. res_finite = stats.studentized_range.cdf(3, 10, 99999)
  5048. assert_allclose(res, res_finite, atol=1e-4, rtol=1e-4)
  5049. def test_df_cutoff(self):
  5050. # Test that the CDF and PDF properly switch integrators at df=100,000.
  5051. # The infinite integrator should be different enough that it fails
  5052. # an allclose assertion. Also sanity check that using the same
  5053. # integrator does pass the allclose with a 1-df difference, which
  5054. # should be tiny.
  5055. res = stats.studentized_range.pdf(3, 10, 100000)
  5056. res_finite = stats.studentized_range.pdf(3, 10, 99999)
  5057. res_sanity = stats.studentized_range.pdf(3, 10, 99998)
  5058. assert_raises(AssertionError, assert_allclose, res, res_finite,
  5059. atol=1e-6, rtol=1e-6)
  5060. assert_allclose(res_finite, res_sanity, atol=1e-6, rtol=1e-6)
  5061. res = stats.studentized_range.cdf(3, 10, 100000)
  5062. res_finite = stats.studentized_range.cdf(3, 10, 99999)
  5063. res_sanity = stats.studentized_range.cdf(3, 10, 99998)
  5064. assert_raises(AssertionError, assert_allclose, res, res_finite,
  5065. atol=1e-6, rtol=1e-6)
  5066. assert_allclose(res_finite, res_sanity, atol=1e-6, rtol=1e-6)
  5067. def test_clipping(self):
  5068. # The result of this computation was -9.9253938401489e-14 on some
  5069. # systems. The correct result is very nearly zero, but should not be
  5070. # negative.
  5071. q, k, v = 34.6413996195345746, 3, 339
  5072. p = stats.studentized_range.sf(q, k, v)
  5073. assert_allclose(p, 0, atol=1e-10)
  5074. assert p >= 0
  5075. def test_540_567():
  5076. # test for nan returned in tickets 540, 567
  5077. assert_almost_equal(stats.norm.cdf(-1.7624320982), 0.03899815971089126,
  5078. decimal=10, err_msg='test_540_567')
  5079. assert_almost_equal(stats.norm.cdf(-1.7624320983), 0.038998159702449846,
  5080. decimal=10, err_msg='test_540_567')
  5081. assert_almost_equal(stats.norm.cdf(1.38629436112, loc=0.950273420309,
  5082. scale=0.204423758009),
  5083. 0.98353464004309321,
  5084. decimal=10, err_msg='test_540_567')
  5085. def test_regression_ticket_1316():
  5086. # The following was raising an exception, because _construct_default_doc()
  5087. # did not handle the default keyword extradoc=None. See ticket #1316.
  5088. stats._continuous_distns.gamma_gen(name='gamma')
  5089. def test_regression_ticket_1326():
  5090. # adjust to avoid nan with 0*log(0)
  5091. assert_almost_equal(stats.chi2.pdf(0.0, 2), 0.5, 14)
  5092. def test_regression_tukey_lambda():
  5093. # Make sure that Tukey-Lambda distribution correctly handles
  5094. # non-positive lambdas.
  5095. x = np.linspace(-5.0, 5.0, 101)
  5096. with np.errstate(divide='ignore'):
  5097. for lam in [0.0, -1.0, -2.0, np.array([[-1.0], [0.0], [-2.0]])]:
  5098. p = stats.tukeylambda.pdf(x, lam)
  5099. assert_((p != 0.0).all())
  5100. assert_(~np.isnan(p).all())
  5101. lam = np.array([[-1.0], [0.0], [2.0]])
  5102. p = stats.tukeylambda.pdf(x, lam)
  5103. assert_(~np.isnan(p).all())
  5104. assert_((p[0] != 0.0).all())
  5105. assert_((p[1] != 0.0).all())
  5106. assert_((p[2] != 0.0).any())
  5107. assert_((p[2] == 0.0).any())
  5108. @pytest.mark.skipif(DOCSTRINGS_STRIPPED, reason="docstrings stripped")
  5109. def test_regression_ticket_1421():
  5110. assert_('pdf(x, mu, loc=0, scale=1)' not in stats.poisson.__doc__)
  5111. assert_('pmf(x,' in stats.poisson.__doc__)
  5112. def test_nan_arguments_gh_issue_1362():
  5113. with np.errstate(invalid='ignore'):
  5114. assert_(np.isnan(stats.t.logcdf(1, np.nan)))
  5115. assert_(np.isnan(stats.t.cdf(1, np.nan)))
  5116. assert_(np.isnan(stats.t.logsf(1, np.nan)))
  5117. assert_(np.isnan(stats.t.sf(1, np.nan)))
  5118. assert_(np.isnan(stats.t.pdf(1, np.nan)))
  5119. assert_(np.isnan(stats.t.logpdf(1, np.nan)))
  5120. assert_(np.isnan(stats.t.ppf(1, np.nan)))
  5121. assert_(np.isnan(stats.t.isf(1, np.nan)))
  5122. assert_(np.isnan(stats.bernoulli.logcdf(np.nan, 0.5)))
  5123. assert_(np.isnan(stats.bernoulli.cdf(np.nan, 0.5)))
  5124. assert_(np.isnan(stats.bernoulli.logsf(np.nan, 0.5)))
  5125. assert_(np.isnan(stats.bernoulli.sf(np.nan, 0.5)))
  5126. assert_(np.isnan(stats.bernoulli.pmf(np.nan, 0.5)))
  5127. assert_(np.isnan(stats.bernoulli.logpmf(np.nan, 0.5)))
  5128. assert_(np.isnan(stats.bernoulli.ppf(np.nan, 0.5)))
  5129. assert_(np.isnan(stats.bernoulli.isf(np.nan, 0.5)))
  5130. def test_frozen_fit_ticket_1536():
  5131. np.random.seed(5678)
  5132. true = np.array([0.25, 0., 0.5])
  5133. x = stats.lognorm.rvs(true[0], true[1], true[2], size=100)
  5134. with np.errstate(divide='ignore'):
  5135. params = np.array(stats.lognorm.fit(x, floc=0.))
  5136. assert_almost_equal(params, true, decimal=2)
  5137. params = np.array(stats.lognorm.fit(x, fscale=0.5, loc=0))
  5138. assert_almost_equal(params, true, decimal=2)
  5139. params = np.array(stats.lognorm.fit(x, f0=0.25, loc=0))
  5140. assert_almost_equal(params, true, decimal=2)
  5141. params = np.array(stats.lognorm.fit(x, f0=0.25, floc=0))
  5142. assert_almost_equal(params, true, decimal=2)
  5143. np.random.seed(5678)
  5144. loc = 1
  5145. floc = 0.9
  5146. x = stats.norm.rvs(loc, 2., size=100)
  5147. params = np.array(stats.norm.fit(x, floc=floc))
  5148. expected = np.array([floc, np.sqrt(((x-floc)**2).mean())])
  5149. assert_almost_equal(params, expected, decimal=4)
  5150. def test_regression_ticket_1530():
  5151. # Check the starting value works for Cauchy distribution fit.
  5152. np.random.seed(654321)
  5153. rvs = stats.cauchy.rvs(size=100)
  5154. params = stats.cauchy.fit(rvs)
  5155. expected = (0.045, 1.142)
  5156. assert_almost_equal(params, expected, decimal=1)
  5157. def test_gh_pr_4806():
  5158. # Check starting values for Cauchy distribution fit.
  5159. np.random.seed(1234)
  5160. x = np.random.randn(42)
  5161. for offset in 10000.0, 1222333444.0:
  5162. loc, scale = stats.cauchy.fit(x + offset)
  5163. assert_allclose(loc, offset, atol=1.0)
  5164. assert_allclose(scale, 0.6, atol=1.0)
  5165. def test_tukeylambda_stats_ticket_1545():
  5166. # Some test for the variance and kurtosis of the Tukey Lambda distr.
  5167. # See test_tukeylamdba_stats.py for more tests.
  5168. mv = stats.tukeylambda.stats(0, moments='mvsk')
  5169. # Known exact values:
  5170. expected = [0, np.pi**2/3, 0, 1.2]
  5171. assert_almost_equal(mv, expected, decimal=10)
  5172. mv = stats.tukeylambda.stats(3.13, moments='mvsk')
  5173. # 'expected' computed with mpmath.
  5174. expected = [0, 0.0269220858861465102, 0, -0.898062386219224104]
  5175. assert_almost_equal(mv, expected, decimal=10)
  5176. mv = stats.tukeylambda.stats(0.14, moments='mvsk')
  5177. # 'expected' computed with mpmath.
  5178. expected = [0, 2.11029702221450250, 0, -0.02708377353223019456]
  5179. assert_almost_equal(mv, expected, decimal=10)
  5180. def test_poisson_logpmf_ticket_1436():
  5181. assert_(np.isfinite(stats.poisson.logpmf(1500, 200)))
  5182. def test_powerlaw_stats():
  5183. """Test the powerlaw stats function.
  5184. This unit test is also a regression test for ticket 1548.
  5185. The exact values are:
  5186. mean:
  5187. mu = a / (a + 1)
  5188. variance:
  5189. sigma**2 = a / ((a + 2) * (a + 1) ** 2)
  5190. skewness:
  5191. One formula (see https://en.wikipedia.org/wiki/Skewness) is
  5192. gamma_1 = (E[X**3] - 3*mu*E[X**2] + 2*mu**3) / sigma**3
  5193. A short calculation shows that E[X**k] is a / (a + k), so gamma_1
  5194. can be implemented as
  5195. n = a/(a+3) - 3*(a/(a+1))*a/(a+2) + 2*(a/(a+1))**3
  5196. d = sqrt(a/((a+2)*(a+1)**2)) ** 3
  5197. gamma_1 = n/d
  5198. Either by simplifying, or by a direct calculation of mu_3 / sigma**3,
  5199. one gets the more concise formula:
  5200. gamma_1 = -2.0 * ((a - 1) / (a + 3)) * sqrt((a + 2) / a)
  5201. kurtosis: (See https://en.wikipedia.org/wiki/Kurtosis)
  5202. The excess kurtosis is
  5203. gamma_2 = mu_4 / sigma**4 - 3
  5204. A bit of calculus and algebra (sympy helps) shows that
  5205. mu_4 = 3*a*(3*a**2 - a + 2) / ((a+1)**4 * (a+2) * (a+3) * (a+4))
  5206. so
  5207. gamma_2 = 3*(3*a**2 - a + 2) * (a+2) / (a*(a+3)*(a+4)) - 3
  5208. which can be rearranged to
  5209. gamma_2 = 6 * (a**3 - a**2 - 6*a + 2) / (a*(a+3)*(a+4))
  5210. """
  5211. cases = [(1.0, (0.5, 1./12, 0.0, -1.2)),
  5212. (2.0, (2./3, 2./36, -0.56568542494924734, -0.6))]
  5213. for a, exact_mvsk in cases:
  5214. mvsk = stats.powerlaw.stats(a, moments="mvsk")
  5215. assert_array_almost_equal(mvsk, exact_mvsk)
  5216. def test_powerlaw_edge():
  5217. # Regression test for gh-3986.
  5218. p = stats.powerlaw.logpdf(0, 1)
  5219. assert_equal(p, 0.0)
  5220. def test_exponpow_edge():
  5221. # Regression test for gh-3982.
  5222. p = stats.exponpow.logpdf(0, 1)
  5223. assert_equal(p, 0.0)
  5224. # Check pdf and logpdf at x = 0 for other values of b.
  5225. p = stats.exponpow.pdf(0, [0.25, 1.0, 1.5])
  5226. assert_equal(p, [np.inf, 1.0, 0.0])
  5227. p = stats.exponpow.logpdf(0, [0.25, 1.0, 1.5])
  5228. assert_equal(p, [np.inf, 0.0, -np.inf])
  5229. def test_gengamma_edge():
  5230. # Regression test for gh-3985.
  5231. p = stats.gengamma.pdf(0, 1, 1)
  5232. assert_equal(p, 1.0)
  5233. def test_gengamma_endpoint_with_neg_c():
  5234. p = stats.gengamma.pdf(0, 1, -1)
  5235. assert p == 0.0
  5236. logp = stats.gengamma.logpdf(0, 1, -1)
  5237. assert logp == -np.inf
  5238. def test_gengamma_munp():
  5239. # Regression tests for gh-4724.
  5240. p = stats.gengamma._munp(-2, 200, 1.)
  5241. assert_almost_equal(p, 1./199/198)
  5242. p = stats.gengamma._munp(-2, 10, 1.)
  5243. assert_almost_equal(p, 1./9/8)
  5244. def test_ksone_fit_freeze():
  5245. # Regression test for ticket #1638.
  5246. d = np.array(
  5247. [-0.18879233, 0.15734249, 0.18695107, 0.27908787, -0.248649,
  5248. -0.2171497, 0.12233512, 0.15126419, 0.03119282, 0.4365294,
  5249. 0.08930393, -0.23509903, 0.28231224, -0.09974875, -0.25196048,
  5250. 0.11102028, 0.1427649, 0.10176452, 0.18754054, 0.25826724,
  5251. 0.05988819, 0.0531668, 0.21906056, 0.32106729, 0.2117662,
  5252. 0.10886442, 0.09375789, 0.24583286, -0.22968366, -0.07842391,
  5253. -0.31195432, -0.21271196, 0.1114243, -0.13293002, 0.01331725,
  5254. -0.04330977, -0.09485776, -0.28434547, 0.22245721, -0.18518199,
  5255. -0.10943985, -0.35243174, 0.06897665, -0.03553363, -0.0701746,
  5256. -0.06037974, 0.37670779, -0.21684405])
  5257. with np.errstate(invalid='ignore'):
  5258. with suppress_warnings() as sup:
  5259. sup.filter(IntegrationWarning,
  5260. "The maximum number of subdivisions .50. has been "
  5261. "achieved.")
  5262. sup.filter(RuntimeWarning,
  5263. "floating point number truncated to an integer")
  5264. stats.ksone.fit(d)
  5265. def test_norm_logcdf():
  5266. # Test precision of the logcdf of the normal distribution.
  5267. # This precision was enhanced in ticket 1614.
  5268. x = -np.asarray(list(range(0, 120, 4)))
  5269. # Values from R
  5270. expected = [-0.69314718, -10.36010149, -35.01343716, -75.41067300,
  5271. -131.69539607, -203.91715537, -292.09872100, -396.25241451,
  5272. -516.38564863, -652.50322759, -804.60844201, -972.70364403,
  5273. -1156.79057310, -1356.87055173, -1572.94460885, -1805.01356068,
  5274. -2053.07806561, -2317.13866238, -2597.19579746, -2893.24984493,
  5275. -3205.30112136, -3533.34989701, -3877.39640444, -4237.44084522,
  5276. -4613.48339520, -5005.52420869, -5413.56342187, -5837.60115548,
  5277. -6277.63751711, -6733.67260303]
  5278. assert_allclose(stats.norm().logcdf(x), expected, atol=1e-8)
  5279. # also test the complex-valued code path
  5280. assert_allclose(stats.norm().logcdf(x + 1e-14j).real, expected, atol=1e-8)
  5281. # test the accuracy: d(logcdf)/dx = pdf / cdf \equiv exp(logpdf - logcdf)
  5282. deriv = (stats.norm.logcdf(x + 1e-10j)/1e-10).imag
  5283. deriv_expected = np.exp(stats.norm.logpdf(x) - stats.norm.logcdf(x))
  5284. assert_allclose(deriv, deriv_expected, atol=1e-10)
  5285. def test_levy_cdf_ppf():
  5286. # Test levy.cdf, including small arguments.
  5287. x = np.array([1000, 1.0, 0.5, 0.1, 0.01, 0.001])
  5288. # Expected values were calculated separately with mpmath.
  5289. # E.g.
  5290. # >>> mpmath.mp.dps = 100
  5291. # >>> x = mpmath.mp.mpf('0.01')
  5292. # >>> cdf = mpmath.erfc(mpmath.sqrt(1/(2*x)))
  5293. expected = np.array([0.9747728793699604,
  5294. 0.3173105078629141,
  5295. 0.1572992070502851,
  5296. 0.0015654022580025495,
  5297. 1.523970604832105e-23,
  5298. 1.795832784800726e-219])
  5299. y = stats.levy.cdf(x)
  5300. assert_allclose(y, expected, rtol=1e-10)
  5301. # ppf(expected) should get us back to x.
  5302. xx = stats.levy.ppf(expected)
  5303. assert_allclose(xx, x, rtol=1e-13)
  5304. def test_levy_sf():
  5305. # Large values, far into the tail of the distribution.
  5306. x = np.array([1e15, 1e25, 1e35, 1e50])
  5307. # Expected values were calculated with mpmath.
  5308. expected = np.array([2.5231325220201597e-08,
  5309. 2.52313252202016e-13,
  5310. 2.52313252202016e-18,
  5311. 7.978845608028653e-26])
  5312. y = stats.levy.sf(x)
  5313. assert_allclose(y, expected, rtol=1e-14)
  5314. # The expected values for levy.isf(p) were calculated with mpmath.
  5315. # For loc=0 and scale=1, the inverse SF can be computed with
  5316. #
  5317. # import mpmath
  5318. #
  5319. # def levy_invsf(p):
  5320. # return 1/(2*mpmath.erfinv(p)**2)
  5321. #
  5322. # For example, with mpmath.mp.dps set to 60, float(levy_invsf(1e-20))
  5323. # returns 6.366197723675814e+39.
  5324. #
  5325. @pytest.mark.parametrize('p, expected_isf',
  5326. [(1e-20, 6.366197723675814e+39),
  5327. (1e-8, 6366197723675813.0),
  5328. (0.375, 4.185810119346273),
  5329. (0.875, 0.42489442055310134),
  5330. (0.999, 0.09235685880262713),
  5331. (0.9999999962747097, 0.028766845244146945)])
  5332. def test_levy_isf(p, expected_isf):
  5333. x = stats.levy.isf(p)
  5334. assert_allclose(x, expected_isf, atol=5e-15)
  5335. def test_levy_l_sf():
  5336. # Test levy_l.sf for small arguments.
  5337. x = np.array([-0.016, -0.01, -0.005, -0.0015])
  5338. # Expected values were calculated with mpmath.
  5339. expected = np.array([2.6644463892359302e-15,
  5340. 1.523970604832107e-23,
  5341. 2.0884875837625492e-45,
  5342. 5.302850374626878e-147])
  5343. y = stats.levy_l.sf(x)
  5344. assert_allclose(y, expected, rtol=1e-13)
  5345. def test_levy_l_isf():
  5346. # Test roundtrip sf(isf(p)), including a small input value.
  5347. p = np.array([3.0e-15, 0.25, 0.99])
  5348. x = stats.levy_l.isf(p)
  5349. q = stats.levy_l.sf(x)
  5350. assert_allclose(q, p, rtol=5e-14)
  5351. def test_hypergeom_interval_1802():
  5352. # these two had endless loops
  5353. assert_equal(stats.hypergeom.interval(.95, 187601, 43192, 757),
  5354. (152.0, 197.0))
  5355. assert_equal(stats.hypergeom.interval(.945, 187601, 43192, 757),
  5356. (152.0, 197.0))
  5357. # this was working also before
  5358. assert_equal(stats.hypergeom.interval(.94, 187601, 43192, 757),
  5359. (153.0, 196.0))
  5360. # degenerate case .a == .b
  5361. assert_equal(stats.hypergeom.ppf(0.02, 100, 100, 8), 8)
  5362. assert_equal(stats.hypergeom.ppf(1, 100, 100, 8), 8)
  5363. def test_distribution_too_many_args():
  5364. np.random.seed(1234)
  5365. # Check that a TypeError is raised when too many args are given to a method
  5366. # Regression test for ticket 1815.
  5367. x = np.linspace(0.1, 0.7, num=5)
  5368. assert_raises(TypeError, stats.gamma.pdf, x, 2, 3, loc=1.0)
  5369. assert_raises(TypeError, stats.gamma.pdf, x, 2, 3, 4, loc=1.0)
  5370. assert_raises(TypeError, stats.gamma.pdf, x, 2, 3, 4, 5)
  5371. assert_raises(TypeError, stats.gamma.pdf, x, 2, 3, loc=1.0, scale=0.5)
  5372. assert_raises(TypeError, stats.gamma.rvs, 2., 3, loc=1.0, scale=0.5)
  5373. assert_raises(TypeError, stats.gamma.cdf, x, 2., 3, loc=1.0, scale=0.5)
  5374. assert_raises(TypeError, stats.gamma.ppf, x, 2., 3, loc=1.0, scale=0.5)
  5375. assert_raises(TypeError, stats.gamma.stats, 2., 3, loc=1.0, scale=0.5)
  5376. assert_raises(TypeError, stats.gamma.entropy, 2., 3, loc=1.0, scale=0.5)
  5377. assert_raises(TypeError, stats.gamma.fit, x, 2., 3, loc=1.0, scale=0.5)
  5378. # These should not give errors
  5379. stats.gamma.pdf(x, 2, 3) # loc=3
  5380. stats.gamma.pdf(x, 2, 3, 4) # loc=3, scale=4
  5381. stats.gamma.stats(2., 3)
  5382. stats.gamma.stats(2., 3, 4)
  5383. stats.gamma.stats(2., 3, 4, 'mv')
  5384. stats.gamma.rvs(2., 3, 4, 5)
  5385. stats.gamma.fit(stats.gamma.rvs(2., size=7), 2.)
  5386. # Also for a discrete distribution
  5387. stats.geom.pmf(x, 2, loc=3) # no error, loc=3
  5388. assert_raises(TypeError, stats.geom.pmf, x, 2, 3, 4)
  5389. assert_raises(TypeError, stats.geom.pmf, x, 2, 3, loc=4)
  5390. # And for distributions with 0, 2 and 3 args respectively
  5391. assert_raises(TypeError, stats.expon.pdf, x, 3, loc=1.0)
  5392. assert_raises(TypeError, stats.exponweib.pdf, x, 3, 4, 5, loc=1.0)
  5393. assert_raises(TypeError, stats.exponweib.pdf, x, 3, 4, 5, 0.1, 0.1)
  5394. assert_raises(TypeError, stats.ncf.pdf, x, 3, 4, 5, 6, loc=1.0)
  5395. assert_raises(TypeError, stats.ncf.pdf, x, 3, 4, 5, 6, 1.0, scale=0.5)
  5396. stats.ncf.pdf(x, 3, 4, 5, 6, 1.0) # 3 args, plus loc/scale
  5397. @pytest.mark.filterwarnings('ignore::RuntimeWarning')
  5398. def test_ncx2_tails_ticket_955():
  5399. # Trac #955 -- check that the cdf computed by special functions
  5400. # matches the integrated pdf
  5401. a = stats.ncx2.cdf(np.arange(20, 25, 0.2), 2, 1.07458615e+02)
  5402. b = stats.ncx2._cdfvec(np.arange(20, 25, 0.2), 2, 1.07458615e+02)
  5403. assert_allclose(a, b, rtol=1e-3, atol=0)
  5404. def test_ncx2_tails_pdf():
  5405. # ncx2.pdf does not return nans in extreme tails(example from gh-1577)
  5406. # NB: this is to check that nan_to_num is not needed in ncx2.pdf
  5407. with warnings.catch_warnings():
  5408. warnings.simplefilter('error', RuntimeWarning)
  5409. assert_equal(stats.ncx2.pdf(1, np.arange(340, 350), 2), 0)
  5410. logval = stats.ncx2.logpdf(1, np.arange(340, 350), 2)
  5411. assert_(np.isneginf(logval).all())
  5412. # Verify logpdf has extended precision when pdf underflows to 0
  5413. with warnings.catch_warnings():
  5414. warnings.simplefilter('error', RuntimeWarning)
  5415. assert_equal(stats.ncx2.pdf(10000, 3, 12), 0)
  5416. assert_allclose(stats.ncx2.logpdf(10000, 3, 12), -4662.444377524883)
  5417. @pytest.mark.parametrize('method, expected', [
  5418. ('cdf', np.array([2.497951336e-09, 3.437288941e-10])),
  5419. ('pdf', np.array([1.238579980e-07, 1.710041145e-08])),
  5420. ('logpdf', np.array([-15.90413011, -17.88416331])),
  5421. ('ppf', np.array([4.865182052, 7.017182271]))
  5422. ])
  5423. def test_ncx2_zero_nc(method, expected):
  5424. # gh-5441
  5425. # ncx2 with nc=0 is identical to chi2
  5426. # Comparison to R (v3.5.1)
  5427. # > options(digits=10)
  5428. # > pchisq(0.1, df=10, ncp=c(0,4))
  5429. # > dchisq(0.1, df=10, ncp=c(0,4))
  5430. # > dchisq(0.1, df=10, ncp=c(0,4), log=TRUE)
  5431. # > qchisq(0.1, df=10, ncp=c(0,4))
  5432. result = getattr(stats.ncx2, method)(0.1, nc=[0, 4], df=10)
  5433. assert_allclose(result, expected, atol=1e-15)
  5434. def test_ncx2_zero_nc_rvs():
  5435. # gh-5441
  5436. # ncx2 with nc=0 is identical to chi2
  5437. result = stats.ncx2.rvs(df=10, nc=0, random_state=1)
  5438. expected = stats.chi2.rvs(df=10, random_state=1)
  5439. assert_allclose(result, expected, atol=1e-15)
  5440. @pytest.mark.filterwarnings('ignore::RuntimeWarning')
  5441. def test_ncx2_gh12731():
  5442. # test that gh-12731 is resolved; previously these were all 0.5
  5443. nc = 10**np.arange(5, 10)
  5444. assert_equal(stats.ncx2.cdf(1e4, df=1, nc=nc), 0)
  5445. @pytest.mark.filterwarnings('ignore::RuntimeWarning')
  5446. def test_ncx2_gh8665():
  5447. # test that gh-8665 is resolved; previously this tended to nonzero value
  5448. x = np.array([4.99515382e+00, 1.07617327e+01, 2.31854502e+01,
  5449. 4.99515382e+01, 1.07617327e+02, 2.31854502e+02,
  5450. 4.99515382e+02, 1.07617327e+03, 2.31854502e+03,
  5451. 4.99515382e+03, 1.07617327e+04, 2.31854502e+04,
  5452. 4.99515382e+04])
  5453. nu, lam = 20, 499.51538166556196
  5454. sf = stats.ncx2.sf(x, df=nu, nc=lam)
  5455. # computed in R. Couldn't find a survival function implementation
  5456. # options(digits=16)
  5457. # x <- c(4.99515382e+00, 1.07617327e+01, 2.31854502e+01, 4.99515382e+01,
  5458. # 1.07617327e+02, 2.31854502e+02, 4.99515382e+02, 1.07617327e+03,
  5459. # 2.31854502e+03, 4.99515382e+03, 1.07617327e+04, 2.31854502e+04,
  5460. # 4.99515382e+04)
  5461. # nu <- 20
  5462. # lam <- 499.51538166556196
  5463. # 1 - pchisq(x, df = nu, ncp = lam)
  5464. sf_expected = [1.0000000000000000, 1.0000000000000000, 1.0000000000000000,
  5465. 1.0000000000000000, 1.0000000000000000, 0.9999999999999888,
  5466. 0.6646525582135460, 0.0000000000000000, 0.0000000000000000,
  5467. 0.0000000000000000, 0.0000000000000000, 0.0000000000000000,
  5468. 0.0000000000000000]
  5469. assert_allclose(sf, sf_expected, atol=1e-12)
  5470. def test_ncx2_gh11777():
  5471. # regression test for gh-11777:
  5472. # At high values of degrees of freedom df, ensure the pdf of ncx2 does
  5473. # not get clipped to zero when the non-centrality parameter is
  5474. # sufficiently less than df
  5475. df = 6700
  5476. nc = 5300
  5477. x = np.linspace(stats.ncx2.ppf(0.001, df, nc),
  5478. stats.ncx2.ppf(0.999, df, nc), num=10000)
  5479. ncx2_pdf = stats.ncx2.pdf(x, df, nc)
  5480. gauss_approx = stats.norm.pdf(x, df + nc, np.sqrt(2 * df + 4 * nc))
  5481. # use huge tolerance as we're only looking for obvious discrepancy
  5482. assert_allclose(ncx2_pdf, gauss_approx, atol=1e-4)
  5483. def test_foldnorm_zero():
  5484. # Parameter value c=0 was not enabled, see gh-2399.
  5485. rv = stats.foldnorm(0, scale=1)
  5486. assert_equal(rv.cdf(0), 0) # rv.cdf(0) previously resulted in: nan
  5487. def test_stats_shapes_argcheck():
  5488. # stats method was failing for vector shapes if some of the values
  5489. # were outside of the allowed range, see gh-2678
  5490. mv3 = stats.invgamma.stats([0.0, 0.5, 1.0], 1, 0.5) # 0 is not a legal `a`
  5491. mv2 = stats.invgamma.stats([0.5, 1.0], 1, 0.5)
  5492. mv2_augmented = tuple(np.r_[np.nan, _] for _ in mv2)
  5493. assert_equal(mv2_augmented, mv3)
  5494. # -1 is not a legal shape parameter
  5495. mv3 = stats.lognorm.stats([2, 2.4, -1])
  5496. mv2 = stats.lognorm.stats([2, 2.4])
  5497. mv2_augmented = tuple(np.r_[_, np.nan] for _ in mv2)
  5498. assert_equal(mv2_augmented, mv3)
  5499. # FIXME: this is only a quick-and-dirty test of a quick-and-dirty bugfix.
  5500. # stats method with multiple shape parameters is not properly vectorized
  5501. # anyway, so some distributions may or may not fail.
  5502. # Test subclassing distributions w/ explicit shapes
  5503. class _distr_gen(stats.rv_continuous):
  5504. def _pdf(self, x, a):
  5505. return 42
  5506. class _distr2_gen(stats.rv_continuous):
  5507. def _cdf(self, x, a):
  5508. return 42 * a + x
  5509. class _distr3_gen(stats.rv_continuous):
  5510. def _pdf(self, x, a, b):
  5511. return a + b
  5512. def _cdf(self, x, a):
  5513. # Different # of shape params from _pdf, to be able to check that
  5514. # inspection catches the inconsistency."""
  5515. return 42 * a + x
  5516. class _distr6_gen(stats.rv_continuous):
  5517. # Two shape parameters (both _pdf and _cdf defined, consistent shapes.)
  5518. def _pdf(self, x, a, b):
  5519. return a*x + b
  5520. def _cdf(self, x, a, b):
  5521. return 42 * a + x
  5522. class TestSubclassingExplicitShapes:
  5523. # Construct a distribution w/ explicit shapes parameter and test it.
  5524. def test_correct_shapes(self):
  5525. dummy_distr = _distr_gen(name='dummy', shapes='a')
  5526. assert_equal(dummy_distr.pdf(1, a=1), 42)
  5527. def test_wrong_shapes_1(self):
  5528. dummy_distr = _distr_gen(name='dummy', shapes='A')
  5529. assert_raises(TypeError, dummy_distr.pdf, 1, **dict(a=1))
  5530. def test_wrong_shapes_2(self):
  5531. dummy_distr = _distr_gen(name='dummy', shapes='a, b, c')
  5532. dct = dict(a=1, b=2, c=3)
  5533. assert_raises(TypeError, dummy_distr.pdf, 1, **dct)
  5534. def test_shapes_string(self):
  5535. # shapes must be a string
  5536. dct = dict(name='dummy', shapes=42)
  5537. assert_raises(TypeError, _distr_gen, **dct)
  5538. def test_shapes_identifiers_1(self):
  5539. # shapes must be a comma-separated list of valid python identifiers
  5540. dct = dict(name='dummy', shapes='(!)')
  5541. assert_raises(SyntaxError, _distr_gen, **dct)
  5542. def test_shapes_identifiers_2(self):
  5543. dct = dict(name='dummy', shapes='4chan')
  5544. assert_raises(SyntaxError, _distr_gen, **dct)
  5545. def test_shapes_identifiers_3(self):
  5546. dct = dict(name='dummy', shapes='m(fti)')
  5547. assert_raises(SyntaxError, _distr_gen, **dct)
  5548. def test_shapes_identifiers_nodefaults(self):
  5549. dct = dict(name='dummy', shapes='a=2')
  5550. assert_raises(SyntaxError, _distr_gen, **dct)
  5551. def test_shapes_args(self):
  5552. dct = dict(name='dummy', shapes='*args')
  5553. assert_raises(SyntaxError, _distr_gen, **dct)
  5554. def test_shapes_kwargs(self):
  5555. dct = dict(name='dummy', shapes='**kwargs')
  5556. assert_raises(SyntaxError, _distr_gen, **dct)
  5557. def test_shapes_keywords(self):
  5558. # python keywords cannot be used for shape parameters
  5559. dct = dict(name='dummy', shapes='a, b, c, lambda')
  5560. assert_raises(SyntaxError, _distr_gen, **dct)
  5561. def test_shapes_signature(self):
  5562. # test explicit shapes which agree w/ the signature of _pdf
  5563. class _dist_gen(stats.rv_continuous):
  5564. def _pdf(self, x, a):
  5565. return stats.norm._pdf(x) * a
  5566. dist = _dist_gen(shapes='a')
  5567. assert_equal(dist.pdf(0.5, a=2), stats.norm.pdf(0.5)*2)
  5568. def test_shapes_signature_inconsistent(self):
  5569. # test explicit shapes which do not agree w/ the signature of _pdf
  5570. class _dist_gen(stats.rv_continuous):
  5571. def _pdf(self, x, a):
  5572. return stats.norm._pdf(x) * a
  5573. dist = _dist_gen(shapes='a, b')
  5574. assert_raises(TypeError, dist.pdf, 0.5, **dict(a=1, b=2))
  5575. def test_star_args(self):
  5576. # test _pdf with only starargs
  5577. # NB: **kwargs of pdf will never reach _pdf
  5578. class _dist_gen(stats.rv_continuous):
  5579. def _pdf(self, x, *args):
  5580. extra_kwarg = args[0]
  5581. return stats.norm._pdf(x) * extra_kwarg
  5582. dist = _dist_gen(shapes='extra_kwarg')
  5583. assert_equal(dist.pdf(0.5, extra_kwarg=33), stats.norm.pdf(0.5)*33)
  5584. assert_equal(dist.pdf(0.5, 33), stats.norm.pdf(0.5)*33)
  5585. assert_raises(TypeError, dist.pdf, 0.5, **dict(xxx=33))
  5586. def test_star_args_2(self):
  5587. # test _pdf with named & starargs
  5588. # NB: **kwargs of pdf will never reach _pdf
  5589. class _dist_gen(stats.rv_continuous):
  5590. def _pdf(self, x, offset, *args):
  5591. extra_kwarg = args[0]
  5592. return stats.norm._pdf(x) * extra_kwarg + offset
  5593. dist = _dist_gen(shapes='offset, extra_kwarg')
  5594. assert_equal(dist.pdf(0.5, offset=111, extra_kwarg=33),
  5595. stats.norm.pdf(0.5)*33 + 111)
  5596. assert_equal(dist.pdf(0.5, 111, 33),
  5597. stats.norm.pdf(0.5)*33 + 111)
  5598. def test_extra_kwarg(self):
  5599. # **kwargs to _pdf are ignored.
  5600. # this is a limitation of the framework (_pdf(x, *goodargs))
  5601. class _distr_gen(stats.rv_continuous):
  5602. def _pdf(self, x, *args, **kwargs):
  5603. # _pdf should handle *args, **kwargs itself. Here "handling"
  5604. # is ignoring *args and looking for ``extra_kwarg`` and using
  5605. # that.
  5606. extra_kwarg = kwargs.pop('extra_kwarg', 1)
  5607. return stats.norm._pdf(x) * extra_kwarg
  5608. dist = _distr_gen(shapes='extra_kwarg')
  5609. assert_equal(dist.pdf(1, extra_kwarg=3), stats.norm.pdf(1))
  5610. def shapes_empty_string(self):
  5611. # shapes='' is equivalent to shapes=None
  5612. class _dist_gen(stats.rv_continuous):
  5613. def _pdf(self, x):
  5614. return stats.norm.pdf(x)
  5615. dist = _dist_gen(shapes='')
  5616. assert_equal(dist.pdf(0.5), stats.norm.pdf(0.5))
  5617. class TestSubclassingNoShapes:
  5618. # Construct a distribution w/o explicit shapes parameter and test it.
  5619. def test_only__pdf(self):
  5620. dummy_distr = _distr_gen(name='dummy')
  5621. assert_equal(dummy_distr.pdf(1, a=1), 42)
  5622. def test_only__cdf(self):
  5623. # _pdf is determined from _cdf by taking numerical derivative
  5624. dummy_distr = _distr2_gen(name='dummy')
  5625. assert_almost_equal(dummy_distr.pdf(1, a=1), 1)
  5626. @pytest.mark.skipif(DOCSTRINGS_STRIPPED, reason="docstring stripped")
  5627. def test_signature_inspection(self):
  5628. # check that _pdf signature inspection works correctly, and is used in
  5629. # the class docstring
  5630. dummy_distr = _distr_gen(name='dummy')
  5631. assert_equal(dummy_distr.numargs, 1)
  5632. assert_equal(dummy_distr.shapes, 'a')
  5633. res = re.findall(r'logpdf\(x, a, loc=0, scale=1\)',
  5634. dummy_distr.__doc__)
  5635. assert_(len(res) == 1)
  5636. @pytest.mark.skipif(DOCSTRINGS_STRIPPED, reason="docstring stripped")
  5637. def test_signature_inspection_2args(self):
  5638. # same for 2 shape params and both _pdf and _cdf defined
  5639. dummy_distr = _distr6_gen(name='dummy')
  5640. assert_equal(dummy_distr.numargs, 2)
  5641. assert_equal(dummy_distr.shapes, 'a, b')
  5642. res = re.findall(r'logpdf\(x, a, b, loc=0, scale=1\)',
  5643. dummy_distr.__doc__)
  5644. assert_(len(res) == 1)
  5645. def test_signature_inspection_2args_incorrect_shapes(self):
  5646. # both _pdf and _cdf defined, but shapes are inconsistent: raises
  5647. assert_raises(TypeError, _distr3_gen, name='dummy')
  5648. def test_defaults_raise(self):
  5649. # default arguments should raise
  5650. class _dist_gen(stats.rv_continuous):
  5651. def _pdf(self, x, a=42):
  5652. return 42
  5653. assert_raises(TypeError, _dist_gen, **dict(name='dummy'))
  5654. def test_starargs_raise(self):
  5655. # without explicit shapes, *args are not allowed
  5656. class _dist_gen(stats.rv_continuous):
  5657. def _pdf(self, x, a, *args):
  5658. return 42
  5659. assert_raises(TypeError, _dist_gen, **dict(name='dummy'))
  5660. def test_kwargs_raise(self):
  5661. # without explicit shapes, **kwargs are not allowed
  5662. class _dist_gen(stats.rv_continuous):
  5663. def _pdf(self, x, a, **kwargs):
  5664. return 42
  5665. assert_raises(TypeError, _dist_gen, **dict(name='dummy'))
  5666. @pytest.mark.skipif(DOCSTRINGS_STRIPPED, reason="docstring stripped")
  5667. def test_docstrings():
  5668. badones = [r',\s*,', r'\(\s*,', r'^\s*:']
  5669. for distname in stats.__all__:
  5670. dist = getattr(stats, distname)
  5671. if isinstance(dist, (stats.rv_discrete, stats.rv_continuous)):
  5672. for regex in badones:
  5673. assert_(re.search(regex, dist.__doc__) is None)
  5674. def test_infinite_input():
  5675. assert_almost_equal(stats.skellam.sf(np.inf, 10, 11), 0)
  5676. assert_almost_equal(stats.ncx2._cdf(np.inf, 8, 0.1), 1)
  5677. def test_lomax_accuracy():
  5678. # regression test for gh-4033
  5679. p = stats.lomax.ppf(stats.lomax.cdf(1e-100, 1), 1)
  5680. assert_allclose(p, 1e-100)
  5681. def test_gompertz_accuracy():
  5682. # Regression test for gh-4031
  5683. p = stats.gompertz.ppf(stats.gompertz.cdf(1e-100, 1), 1)
  5684. assert_allclose(p, 1e-100)
  5685. def test_truncexpon_accuracy():
  5686. # regression test for gh-4035
  5687. p = stats.truncexpon.ppf(stats.truncexpon.cdf(1e-100, 1), 1)
  5688. assert_allclose(p, 1e-100)
  5689. def test_rayleigh_accuracy():
  5690. # regression test for gh-4034
  5691. p = stats.rayleigh.isf(stats.rayleigh.sf(9, 1), 1)
  5692. assert_almost_equal(p, 9.0, decimal=15)
  5693. def test_genextreme_give_no_warnings():
  5694. """regression test for gh-6219"""
  5695. with warnings.catch_warnings(record=True) as w:
  5696. warnings.simplefilter("always")
  5697. stats.genextreme.cdf(.5, 0)
  5698. stats.genextreme.pdf(.5, 0)
  5699. stats.genextreme.ppf(.5, 0)
  5700. stats.genextreme.logpdf(-np.inf, 0.0)
  5701. number_of_warnings_thrown = len(w)
  5702. assert_equal(number_of_warnings_thrown, 0)
  5703. def test_genextreme_entropy():
  5704. # regression test for gh-5181
  5705. euler_gamma = 0.5772156649015329
  5706. h = stats.genextreme.entropy(-1.0)
  5707. assert_allclose(h, 2*euler_gamma + 1, rtol=1e-14)
  5708. h = stats.genextreme.entropy(0)
  5709. assert_allclose(h, euler_gamma + 1, rtol=1e-14)
  5710. h = stats.genextreme.entropy(1.0)
  5711. assert_equal(h, 1)
  5712. h = stats.genextreme.entropy(-2.0, scale=10)
  5713. assert_allclose(h, euler_gamma*3 + np.log(10) + 1, rtol=1e-14)
  5714. h = stats.genextreme.entropy(10)
  5715. assert_allclose(h, -9*euler_gamma + 1, rtol=1e-14)
  5716. h = stats.genextreme.entropy(-10)
  5717. assert_allclose(h, 11*euler_gamma + 1, rtol=1e-14)
  5718. def test_genextreme_sf_isf():
  5719. # Expected values were computed using mpmath:
  5720. #
  5721. # import mpmath
  5722. #
  5723. # def mp_genextreme_sf(x, xi, mu=0, sigma=1):
  5724. # # Formula from wikipedia, which has a sign convention for xi that
  5725. # # is the opposite of scipy's shape parameter.
  5726. # if xi != 0:
  5727. # t = mpmath.power(1 + ((x - mu)/sigma)*xi, -1/xi)
  5728. # else:
  5729. # t = mpmath.exp(-(x - mu)/sigma)
  5730. # return 1 - mpmath.exp(-t)
  5731. #
  5732. # >>> mpmath.mp.dps = 1000
  5733. # >>> s = mp_genextreme_sf(mpmath.mp.mpf("1e8"), mpmath.mp.mpf("0.125"))
  5734. # >>> float(s)
  5735. # 1.6777205262585625e-57
  5736. # >>> s = mp_genextreme_sf(mpmath.mp.mpf("7.98"), mpmath.mp.mpf("-0.125"))
  5737. # >>> float(s)
  5738. # 1.52587890625e-21
  5739. # >>> s = mp_genextreme_sf(mpmath.mp.mpf("7.98"), mpmath.mp.mpf("0"))
  5740. # >>> float(s)
  5741. # 0.00034218086528426593
  5742. x = 1e8
  5743. s = stats.genextreme.sf(x, -0.125)
  5744. assert_allclose(s, 1.6777205262585625e-57)
  5745. x2 = stats.genextreme.isf(s, -0.125)
  5746. assert_allclose(x2, x)
  5747. x = 7.98
  5748. s = stats.genextreme.sf(x, 0.125)
  5749. assert_allclose(s, 1.52587890625e-21)
  5750. x2 = stats.genextreme.isf(s, 0.125)
  5751. assert_allclose(x2, x)
  5752. x = 7.98
  5753. s = stats.genextreme.sf(x, 0)
  5754. assert_allclose(s, 0.00034218086528426593)
  5755. x2 = stats.genextreme.isf(s, 0)
  5756. assert_allclose(x2, x)
  5757. def test_burr12_ppf_small_arg():
  5758. prob = 1e-16
  5759. quantile = stats.burr12.ppf(prob, 2, 3)
  5760. # The expected quantile was computed using mpmath:
  5761. # >>> import mpmath
  5762. # >>> mpmath.mp.dps = 100
  5763. # >>> prob = mpmath.mpf('1e-16')
  5764. # >>> c = mpmath.mpf(2)
  5765. # >>> d = mpmath.mpf(3)
  5766. # >>> float(((1-prob)**(-1/d) - 1)**(1/c))
  5767. # 5.7735026918962575e-09
  5768. assert_allclose(quantile, 5.7735026918962575e-09)
  5769. def test_crystalball_function():
  5770. """
  5771. All values are calculated using the independent implementation of the
  5772. ROOT framework (see https://root.cern.ch/).
  5773. Corresponding ROOT code is given in the comments.
  5774. """
  5775. X = np.linspace(-5.0, 5.0, 21)[:-1]
  5776. # for(float x = -5.0; x < 5.0; x+=0.5)
  5777. # std::cout << ROOT::Math::crystalball_pdf(x, 1.0, 2.0, 1.0) << ", ";
  5778. calculated = stats.crystalball.pdf(X, beta=1.0, m=2.0)
  5779. expected = np.array([0.0202867, 0.0241428, 0.0292128, 0.0360652, 0.045645,
  5780. 0.059618, 0.0811467, 0.116851, 0.18258, 0.265652,
  5781. 0.301023, 0.265652, 0.18258, 0.097728, 0.0407391,
  5782. 0.013226, 0.00334407, 0.000658486, 0.000100982,
  5783. 1.20606e-05])
  5784. assert_allclose(expected, calculated, rtol=0.001)
  5785. # for(float x = -5.0; x < 5.0; x+=0.5)
  5786. # std::cout << ROOT::Math::crystalball_pdf(x, 2.0, 3.0, 1.0) << ", ";
  5787. calculated = stats.crystalball.pdf(X, beta=2.0, m=3.0)
  5788. expected = np.array([0.0019648, 0.00279754, 0.00417592, 0.00663121,
  5789. 0.0114587, 0.0223803, 0.0530497, 0.12726, 0.237752,
  5790. 0.345928, 0.391987, 0.345928, 0.237752, 0.12726,
  5791. 0.0530497, 0.0172227, 0.00435458, 0.000857469,
  5792. 0.000131497, 1.57051e-05])
  5793. assert_allclose(expected, calculated, rtol=0.001)
  5794. # for(float x = -5.0; x < 5.0; x+=0.5) {
  5795. # std::cout << ROOT::Math::crystalball_pdf(x, 2.0, 3.0, 2.0, 0.5);
  5796. # std::cout << ", ";
  5797. # }
  5798. calculated = stats.crystalball.pdf(X, beta=2.0, m=3.0, loc=0.5, scale=2.0)
  5799. expected = np.array([0.00785921, 0.0111902, 0.0167037, 0.0265249,
  5800. 0.0423866, 0.0636298, 0.0897324, 0.118876, 0.147944,
  5801. 0.172964, 0.189964, 0.195994, 0.189964, 0.172964,
  5802. 0.147944, 0.118876, 0.0897324, 0.0636298, 0.0423866,
  5803. 0.0265249])
  5804. assert_allclose(expected, calculated, rtol=0.001)
  5805. # for(float x = -5.0; x < 5.0; x+=0.5)
  5806. # std::cout << ROOT::Math::crystalball_cdf(x, 1.0, 2.0, 1.0) << ", ";
  5807. calculated = stats.crystalball.cdf(X, beta=1.0, m=2.0)
  5808. expected = np.array([0.12172, 0.132785, 0.146064, 0.162293, 0.18258,
  5809. 0.208663, 0.24344, 0.292128, 0.36516, 0.478254,
  5810. 0.622723, 0.767192, 0.880286, 0.94959, 0.982834,
  5811. 0.995314, 0.998981, 0.999824, 0.999976, 0.999997])
  5812. assert_allclose(expected, calculated, rtol=0.001)
  5813. # for(float x = -5.0; x < 5.0; x+=0.5)
  5814. # std::cout << ROOT::Math::crystalball_cdf(x, 2.0, 3.0, 1.0) << ", ";
  5815. calculated = stats.crystalball.cdf(X, beta=2.0, m=3.0)
  5816. expected = np.array([0.00442081, 0.00559509, 0.00730787, 0.00994682,
  5817. 0.0143234, 0.0223803, 0.0397873, 0.0830763, 0.173323,
  5818. 0.320592, 0.508717, 0.696841, 0.844111, 0.934357,
  5819. 0.977646, 0.993899, 0.998674, 0.999771, 0.999969,
  5820. 0.999997])
  5821. assert_allclose(expected, calculated, rtol=0.001)
  5822. # for(float x = -5.0; x < 5.0; x+=0.5) {
  5823. # std::cout << ROOT::Math::crystalball_cdf(x, 2.0, 3.0, 2.0, 0.5);
  5824. # std::cout << ", ";
  5825. # }
  5826. calculated = stats.crystalball.cdf(X, beta=2.0, m=3.0, loc=0.5, scale=2.0)
  5827. expected = np.array([0.0176832, 0.0223803, 0.0292315, 0.0397873, 0.0567945,
  5828. 0.0830763, 0.121242, 0.173323, 0.24011, 0.320592,
  5829. 0.411731, 0.508717, 0.605702, 0.696841, 0.777324,
  5830. 0.844111, 0.896192, 0.934357, 0.960639, 0.977646])
  5831. assert_allclose(expected, calculated, rtol=0.001)
  5832. def test_crystalball_function_moments():
  5833. """
  5834. All values are calculated using the pdf formula and the integrate function
  5835. of Mathematica
  5836. """
  5837. # The Last two (alpha, n) pairs test the special case n == alpha**2
  5838. beta = np.array([2.0, 1.0, 3.0, 2.0, 3.0])
  5839. m = np.array([3.0, 3.0, 2.0, 4.0, 9.0])
  5840. # The distribution should be correctly normalised
  5841. expected_0th_moment = np.array([1.0, 1.0, 1.0, 1.0, 1.0])
  5842. calculated_0th_moment = stats.crystalball._munp(0, beta, m)
  5843. assert_allclose(expected_0th_moment, calculated_0th_moment, rtol=0.001)
  5844. # calculated using wolframalpha.com
  5845. # e.g. for beta = 2 and m = 3 we calculate the norm like this:
  5846. # integrate exp(-x^2/2) from -2 to infinity +
  5847. # integrate (3/2)^3*exp(-2^2/2)*(3/2-2-x)^(-3) from -infinity to -2
  5848. norm = np.array([2.5511, 3.01873, 2.51065, 2.53983, 2.507410455])
  5849. a = np.array([-0.21992, -3.03265, np.inf, -0.135335, -0.003174])
  5850. expected_1th_moment = a / norm
  5851. calculated_1th_moment = stats.crystalball._munp(1, beta, m)
  5852. assert_allclose(expected_1th_moment, calculated_1th_moment, rtol=0.001)
  5853. a = np.array([np.inf, np.inf, np.inf, 3.2616, 2.519908])
  5854. expected_2th_moment = a / norm
  5855. calculated_2th_moment = stats.crystalball._munp(2, beta, m)
  5856. assert_allclose(expected_2th_moment, calculated_2th_moment, rtol=0.001)
  5857. a = np.array([np.inf, np.inf, np.inf, np.inf, -0.0577668])
  5858. expected_3th_moment = a / norm
  5859. calculated_3th_moment = stats.crystalball._munp(3, beta, m)
  5860. assert_allclose(expected_3th_moment, calculated_3th_moment, rtol=0.001)
  5861. a = np.array([np.inf, np.inf, np.inf, np.inf, 7.78468])
  5862. expected_4th_moment = a / norm
  5863. calculated_4th_moment = stats.crystalball._munp(4, beta, m)
  5864. assert_allclose(expected_4th_moment, calculated_4th_moment, rtol=0.001)
  5865. a = np.array([np.inf, np.inf, np.inf, np.inf, -1.31086])
  5866. expected_5th_moment = a / norm
  5867. calculated_5th_moment = stats.crystalball._munp(5, beta, m)
  5868. assert_allclose(expected_5th_moment, calculated_5th_moment, rtol=0.001)
  5869. def test_crystalball_entropy():
  5870. # regression test for gh-13602
  5871. cb = stats.crystalball(2, 3)
  5872. res1 = cb.entropy()
  5873. # -20000 and 30 are negative and positive infinity, respectively
  5874. lo, hi, N = -20000, 30, 200000
  5875. x = np.linspace(lo, hi, N)
  5876. res2 = trapezoid(entr(cb.pdf(x)), x)
  5877. assert_allclose(res1, res2, rtol=1e-7)
  5878. def test_invweibull_fit():
  5879. """
  5880. Test fitting invweibull to data.
  5881. Here is a the same calculation in R:
  5882. > library(evd)
  5883. > library(fitdistrplus)
  5884. > x = c(1, 1.25, 2, 2.5, 2.8, 3, 3.8, 4, 5, 8, 10, 12, 64, 99)
  5885. > result = fitdist(x, 'frechet', control=list(reltol=1e-13),
  5886. + fix.arg=list(loc=0), start=list(shape=2, scale=3))
  5887. > result
  5888. Fitting of the distribution ' frechet ' by maximum likelihood
  5889. Parameters:
  5890. estimate Std. Error
  5891. shape 1.048482 0.2261815
  5892. scale 3.099456 0.8292887
  5893. Fixed parameters:
  5894. value
  5895. loc 0
  5896. """
  5897. def optimizer(func, x0, args=(), disp=0):
  5898. return fmin(func, x0, args=args, disp=disp, xtol=1e-12, ftol=1e-12)
  5899. x = np.array([1, 1.25, 2, 2.5, 2.8, 3, 3.8, 4, 5, 8, 10, 12, 64, 99])
  5900. c, loc, scale = stats.invweibull.fit(x, floc=0, optimizer=optimizer)
  5901. assert_allclose(c, 1.048482, rtol=5e-6)
  5902. assert loc == 0
  5903. assert_allclose(scale, 3.099456, rtol=5e-6)
  5904. # Expected values were computed with mpmath.
  5905. @pytest.mark.parametrize('x, c, expected',
  5906. [(3, 1.5, 0.175064510070713299327),
  5907. (2000, 1.5, 1.11802773877318715787e-5),
  5908. (2000, 9.25, 2.92060308832269637092e-31),
  5909. (1e15, 1.5, 3.16227766016837933199884e-23)])
  5910. def test_invweibull_sf(x, c, expected):
  5911. computed = stats.invweibull.sf(x, c)
  5912. assert_allclose(computed, expected, rtol=1e-15)
  5913. # Expected values were computed with mpmath.
  5914. @pytest.mark.parametrize('p, c, expected',
  5915. [(0.5, 2.5, 1.15789669836468183976),
  5916. (3e-18, 5, 3195.77171838060906447)])
  5917. def test_invweibull_isf(p, c, expected):
  5918. computed = stats.invweibull.isf(p, c)
  5919. assert_allclose(computed, expected, rtol=1e-15)
  5920. @pytest.mark.parametrize(
  5921. 'df1,df2,x',
  5922. [(2, 2, [-0.5, 0.2, 1.0, 2.3]),
  5923. (4, 11, [-0.5, 0.2, 1.0, 2.3]),
  5924. (7, 17, [1, 2, 3, 4, 5])]
  5925. )
  5926. def test_ncf_edge_case(df1, df2, x):
  5927. # Test for edge case described in gh-11660.
  5928. # Non-central Fisher distribution when nc = 0
  5929. # should be the same as Fisher distribution.
  5930. nc = 0
  5931. expected_cdf = stats.f.cdf(x, df1, df2)
  5932. calculated_cdf = stats.ncf.cdf(x, df1, df2, nc)
  5933. assert_allclose(expected_cdf, calculated_cdf, rtol=1e-14)
  5934. # when ncf_gen._skip_pdf will be used instead of generic pdf,
  5935. # this additional test will be useful.
  5936. expected_pdf = stats.f.pdf(x, df1, df2)
  5937. calculated_pdf = stats.ncf.pdf(x, df1, df2, nc)
  5938. assert_allclose(expected_pdf, calculated_pdf, rtol=1e-6)
  5939. def test_ncf_variance():
  5940. # Regression test for gh-10658 (incorrect variance formula for ncf).
  5941. # The correct value of ncf.var(2, 6, 4), 42.75, can be verified with, for
  5942. # example, Wolfram Alpha with the expression
  5943. # Variance[NoncentralFRatioDistribution[2, 6, 4]]
  5944. # or with the implementation of the noncentral F distribution in the C++
  5945. # library Boost.
  5946. v = stats.ncf.var(2, 6, 4)
  5947. assert_allclose(v, 42.75, rtol=1e-14)
  5948. def test_ncf_cdf_spotcheck():
  5949. # Regression test for gh-15582 testing against values from R/MATLAB
  5950. # Generate check_val from R or MATLAB as follows:
  5951. # R: pf(20, df1 = 6, df2 = 33, ncp = 30.4) = 0.998921
  5952. # MATLAB: ncfcdf(20, 6, 33, 30.4) = 0.998921
  5953. scipy_val = stats.ncf.cdf(20, 6, 33, 30.4)
  5954. check_val = 0.998921
  5955. assert_allclose(check_val, np.round(scipy_val, decimals=6))
  5956. @pytest.mark.skipif(sys.maxsize <= 2**32,
  5957. reason="On some 32-bit the warning is not raised")
  5958. def test_ncf_ppf_issue_17026():
  5959. # Regression test for gh-17026
  5960. x = np.linspace(0, 1, 600)
  5961. x[0] = 1e-16
  5962. par = (0.1, 2, 5, 0, 1)
  5963. with pytest.warns(RuntimeWarning):
  5964. q = stats.ncf.ppf(x, *par)
  5965. q0 = [stats.ncf.ppf(xi, *par) for xi in x]
  5966. assert_allclose(q, q0)
  5967. class TestHistogram:
  5968. def setup_method(self):
  5969. np.random.seed(1234)
  5970. # We have 8 bins
  5971. # [1,2), [2,3), [3,4), [4,5), [5,6), [6,7), [7,8), [8,9)
  5972. # But actually np.histogram will put the last 9 also in the [8,9) bin!
  5973. # Therefore there is a slight difference below for the last bin, from
  5974. # what you might have expected.
  5975. histogram = np.histogram([1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5,
  5976. 6, 6, 6, 6, 7, 7, 7, 8, 8, 9], bins=8)
  5977. self.template = stats.rv_histogram(histogram)
  5978. data = stats.norm.rvs(loc=1.0, scale=2.5, size=10000, random_state=123)
  5979. norm_histogram = np.histogram(data, bins=50)
  5980. self.norm_template = stats.rv_histogram(norm_histogram)
  5981. def test_pdf(self):
  5982. values = np.array([0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5,
  5983. 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5])
  5984. pdf_values = np.asarray([0.0/25.0, 0.0/25.0, 1.0/25.0, 1.0/25.0,
  5985. 2.0/25.0, 2.0/25.0, 3.0/25.0, 3.0/25.0,
  5986. 4.0/25.0, 4.0/25.0, 5.0/25.0, 5.0/25.0,
  5987. 4.0/25.0, 4.0/25.0, 3.0/25.0, 3.0/25.0,
  5988. 3.0/25.0, 3.0/25.0, 0.0/25.0, 0.0/25.0])
  5989. assert_allclose(self.template.pdf(values), pdf_values)
  5990. # Test explicitly the corner cases:
  5991. # As stated above the pdf in the bin [8,9) is greater than
  5992. # one would naively expect because np.histogram putted the 9
  5993. # into the [8,9) bin.
  5994. assert_almost_equal(self.template.pdf(8.0), 3.0/25.0)
  5995. assert_almost_equal(self.template.pdf(8.5), 3.0/25.0)
  5996. # 9 is outside our defined bins [8,9) hence the pdf is already 0
  5997. # for a continuous distribution this is fine, because a single value
  5998. # does not have a finite probability!
  5999. assert_almost_equal(self.template.pdf(9.0), 0.0/25.0)
  6000. assert_almost_equal(self.template.pdf(10.0), 0.0/25.0)
  6001. x = np.linspace(-2, 2, 10)
  6002. assert_allclose(self.norm_template.pdf(x),
  6003. stats.norm.pdf(x, loc=1.0, scale=2.5), rtol=0.1)
  6004. def test_cdf_ppf(self):
  6005. values = np.array([0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5,
  6006. 5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5])
  6007. cdf_values = np.asarray([0.0/25.0, 0.0/25.0, 0.0/25.0, 0.5/25.0,
  6008. 1.0/25.0, 2.0/25.0, 3.0/25.0, 4.5/25.0,
  6009. 6.0/25.0, 8.0/25.0, 10.0/25.0, 12.5/25.0,
  6010. 15.0/25.0, 17.0/25.0, 19.0/25.0, 20.5/25.0,
  6011. 22.0/25.0, 23.5/25.0, 25.0/25.0, 25.0/25.0])
  6012. assert_allclose(self.template.cdf(values), cdf_values)
  6013. # First three and last two values in cdf_value are not unique
  6014. assert_allclose(self.template.ppf(cdf_values[2:-1]), values[2:-1])
  6015. # Test of cdf and ppf are inverse functions
  6016. x = np.linspace(1.0, 9.0, 100)
  6017. assert_allclose(self.template.ppf(self.template.cdf(x)), x)
  6018. x = np.linspace(0.0, 1.0, 100)
  6019. assert_allclose(self.template.cdf(self.template.ppf(x)), x)
  6020. x = np.linspace(-2, 2, 10)
  6021. assert_allclose(self.norm_template.cdf(x),
  6022. stats.norm.cdf(x, loc=1.0, scale=2.5), rtol=0.1)
  6023. def test_rvs(self):
  6024. N = 10000
  6025. sample = self.template.rvs(size=N, random_state=123)
  6026. assert_equal(np.sum(sample < 1.0), 0.0)
  6027. assert_allclose(np.sum(sample <= 2.0), 1.0/25.0 * N, rtol=0.2)
  6028. assert_allclose(np.sum(sample <= 2.5), 2.0/25.0 * N, rtol=0.2)
  6029. assert_allclose(np.sum(sample <= 3.0), 3.0/25.0 * N, rtol=0.1)
  6030. assert_allclose(np.sum(sample <= 3.5), 4.5/25.0 * N, rtol=0.1)
  6031. assert_allclose(np.sum(sample <= 4.0), 6.0/25.0 * N, rtol=0.1)
  6032. assert_allclose(np.sum(sample <= 4.5), 8.0/25.0 * N, rtol=0.1)
  6033. assert_allclose(np.sum(sample <= 5.0), 10.0/25.0 * N, rtol=0.05)
  6034. assert_allclose(np.sum(sample <= 5.5), 12.5/25.0 * N, rtol=0.05)
  6035. assert_allclose(np.sum(sample <= 6.0), 15.0/25.0 * N, rtol=0.05)
  6036. assert_allclose(np.sum(sample <= 6.5), 17.0/25.0 * N, rtol=0.05)
  6037. assert_allclose(np.sum(sample <= 7.0), 19.0/25.0 * N, rtol=0.05)
  6038. assert_allclose(np.sum(sample <= 7.5), 20.5/25.0 * N, rtol=0.05)
  6039. assert_allclose(np.sum(sample <= 8.0), 22.0/25.0 * N, rtol=0.05)
  6040. assert_allclose(np.sum(sample <= 8.5), 23.5/25.0 * N, rtol=0.05)
  6041. assert_allclose(np.sum(sample <= 9.0), 25.0/25.0 * N, rtol=0.05)
  6042. assert_allclose(np.sum(sample <= 9.0), 25.0/25.0 * N, rtol=0.05)
  6043. assert_equal(np.sum(sample > 9.0), 0.0)
  6044. def test_munp(self):
  6045. for n in range(4):
  6046. assert_allclose(self.norm_template._munp(n),
  6047. stats.norm(1.0, 2.5).moment(n), rtol=0.05)
  6048. def test_entropy(self):
  6049. assert_allclose(self.norm_template.entropy(),
  6050. stats.norm.entropy(loc=1.0, scale=2.5), rtol=0.05)
  6051. def test_histogram_non_uniform():
  6052. # Tests rv_histogram works even for non-uniform bin widths
  6053. counts, bins = ([1, 1], [0, 1, 1001])
  6054. dist = stats.rv_histogram((counts, bins), density=False)
  6055. np.testing.assert_allclose(dist.pdf([0.5, 200]), [0.5, 0.0005])
  6056. assert dist.median() == 1
  6057. dist = stats.rv_histogram((counts, bins), density=True)
  6058. np.testing.assert_allclose(dist.pdf([0.5, 200]), 1/1001)
  6059. assert dist.median() == 1001/2
  6060. # Omitting density produces a warning for non-uniform bins...
  6061. message = "Bin widths are not constant. Assuming..."
  6062. with assert_warns(RuntimeWarning, match=message):
  6063. dist = stats.rv_histogram((counts, bins))
  6064. assert dist.median() == 1001/2 # default is like `density=True`
  6065. # ... but not for uniform bins
  6066. dist = stats.rv_histogram((counts, [0, 1, 2]))
  6067. assert dist.median() == 1
  6068. class TestLogUniform:
  6069. def test_alias(self):
  6070. # This test makes sure that "reciprocal" and "loguniform" are
  6071. # aliases of the same distribution and that both are log-uniform
  6072. rng = np.random.default_rng(98643218961)
  6073. rv = stats.loguniform(10 ** -3, 10 ** 0)
  6074. rvs = rv.rvs(size=10000, random_state=rng)
  6075. rng = np.random.default_rng(98643218961)
  6076. rv2 = stats.reciprocal(10 ** -3, 10 ** 0)
  6077. rvs2 = rv2.rvs(size=10000, random_state=rng)
  6078. assert_allclose(rvs2, rvs)
  6079. vals, _ = np.histogram(np.log10(rvs), bins=10)
  6080. assert 900 <= vals.min() <= vals.max() <= 1100
  6081. assert np.abs(np.median(vals) - 1000) <= 10
  6082. @pytest.mark.parametrize("method", ['mle', 'mm'])
  6083. def test_fit_override(self, method):
  6084. # loguniform is overparameterized, so check that fit override enforces
  6085. # scale=1 unless fscale is provided by the user
  6086. rng = np.random.default_rng(98643218961)
  6087. rvs = stats.loguniform.rvs(0.1, 1, size=1000, random_state=rng)
  6088. a, b, loc, scale = stats.loguniform.fit(rvs, method=method)
  6089. assert scale == 1
  6090. a, b, loc, scale = stats.loguniform.fit(rvs, fscale=2, method=method)
  6091. assert scale == 2
  6092. class TestArgus:
  6093. def test_argus_rvs_large_chi(self):
  6094. # test that the algorithm can handle large values of chi
  6095. x = stats.argus.rvs(50, size=500, random_state=325)
  6096. assert_almost_equal(stats.argus(50).mean(), x.mean(), decimal=4)
  6097. @pytest.mark.parametrize('chi, random_state', [
  6098. [0.1, 325], # chi <= 0.5: rejection method case 1
  6099. [1.3, 155], # 0.5 < chi <= 1.8: rejection method case 2
  6100. [3.5, 135] # chi > 1.8: transform conditional Gamma distribution
  6101. ])
  6102. def test_rvs(self, chi, random_state):
  6103. x = stats.argus.rvs(chi, size=500, random_state=random_state)
  6104. _, p = stats.kstest(x, "argus", (chi, ))
  6105. assert_(p > 0.05)
  6106. @pytest.mark.parametrize('chi', [1e-9, 1e-6])
  6107. def test_rvs_small_chi(self, chi):
  6108. # test for gh-11699 => rejection method case 1 can even handle chi=0
  6109. # the CDF of the distribution for chi=0 is 1 - (1 - x**2)**(3/2)
  6110. # test rvs against distribution of limit chi=0
  6111. r = stats.argus.rvs(chi, size=500, random_state=890981)
  6112. _, p = stats.kstest(r, lambda x: 1 - (1 - x**2)**(3/2))
  6113. assert_(p > 0.05)
  6114. # Expected values were computed with mpmath.
  6115. @pytest.mark.parametrize('chi, expected_mean',
  6116. [(1, 0.6187026683551835),
  6117. (10, 0.984805536783744),
  6118. (40, 0.9990617659702923),
  6119. (60, 0.9995831885165300),
  6120. (99, 0.9998469348663028)])
  6121. def test_mean(self, chi, expected_mean):
  6122. m = stats.argus.mean(chi, scale=1)
  6123. assert_allclose(m, expected_mean, rtol=1e-13)
  6124. # Expected values were computed with mpmath.
  6125. @pytest.mark.parametrize('chi, expected_var, rtol',
  6126. [(1, 0.05215651254197807, 1e-13),
  6127. (10, 0.00015805472008165595, 1e-11),
  6128. (40, 5.877763210262901e-07, 1e-8),
  6129. (60, 1.1590179389611416e-07, 1e-8),
  6130. (99, 1.5623277006064666e-08, 1e-8)])
  6131. def test_var(self, chi, expected_var, rtol):
  6132. v = stats.argus.var(chi, scale=1)
  6133. assert_allclose(v, expected_var, rtol=rtol)
  6134. # Expected values were computed with mpmath (code: see gh-13370).
  6135. @pytest.mark.parametrize('chi, expected, rtol',
  6136. [(0.9, 0.07646314974436118, 1e-14),
  6137. (0.5, 0.015429797891863365, 1e-14),
  6138. (0.1, 0.0001325825293278049, 1e-14),
  6139. (0.01, 1.3297677078224565e-07, 1e-15),
  6140. (1e-3, 1.3298072023958999e-10, 1e-14),
  6141. (1e-4, 1.3298075973486862e-13, 1e-14),
  6142. (1e-6, 1.32980760133771e-19, 1e-14),
  6143. (1e-9, 1.329807601338109e-28, 1e-15)])
  6144. def test_argus_phi_small_chi(self, chi, expected, rtol):
  6145. assert_allclose(_argus_phi(chi), expected, rtol=rtol)
  6146. # Expected values were computed with mpmath (code: see gh-13370).
  6147. @pytest.mark.parametrize(
  6148. 'chi, expected',
  6149. [(0.5, (0.28414073302940573, 1.2742227939992954, 1.2381254688255896)),
  6150. (0.2, (0.296172952995264, 1.2951290588110516, 1.1865767100877576)),
  6151. (0.1, (0.29791447523536274, 1.29806307956989, 1.1793168289857412)),
  6152. (0.01, (0.2984904104866452, 1.2990283628160553, 1.1769268414080531)),
  6153. (1e-3, (0.298496172925224, 1.2990380082487925, 1.176902956021053)),
  6154. (1e-4, (0.29849623054991836, 1.2990381047023793, 1.1769027171686324)),
  6155. (1e-6, (0.2984962311319278, 1.2990381056765605, 1.1769027147562232)),
  6156. (1e-9, (0.298496231131986, 1.299038105676658, 1.1769027147559818))])
  6157. def test_pdf_small_chi(self, chi, expected):
  6158. x = np.array([0.1, 0.5, 0.9])
  6159. assert_allclose(stats.argus.pdf(x, chi), expected, rtol=1e-13)
  6160. # Expected values were computed with mpmath (code: see gh-13370).
  6161. @pytest.mark.parametrize(
  6162. 'chi, expected',
  6163. [(0.5, (0.9857660526895221, 0.6616565930168475, 0.08796070398429937)),
  6164. (0.2, (0.9851555052359501, 0.6514666238985464, 0.08362690023746594)),
  6165. (0.1, (0.9850670974995661, 0.6500061310508574, 0.08302050640683846)),
  6166. (0.01, (0.9850378582451867, 0.6495239242251358, 0.08282109244852445)),
  6167. (1e-3, (0.9850375656906663, 0.6495191015522573, 0.08281910005231098)),
  6168. (1e-4, (0.9850375627651049, 0.6495190533254682, 0.08281908012852317)),
  6169. (1e-6, (0.9850375627355568, 0.6495190528383777, 0.08281907992729293)),
  6170. (1e-9, (0.9850375627355538, 0.649519052838329, 0.0828190799272728))])
  6171. def test_sf_small_chi(self, chi, expected):
  6172. x = np.array([0.1, 0.5, 0.9])
  6173. assert_allclose(stats.argus.sf(x, chi), expected, rtol=1e-14)
  6174. # Expected values were computed with mpmath (code: see gh-13370).
  6175. @pytest.mark.parametrize(
  6176. 'chi, expected',
  6177. [(0.5, (0.0142339473104779, 0.3383434069831524, 0.9120392960157007)),
  6178. (0.2, (0.014844494764049919, 0.34853337610145363, 0.916373099762534)),
  6179. (0.1, (0.014932902500433911, 0.34999386894914264, 0.9169794935931616)),
  6180. (0.01, (0.014962141754813293, 0.35047607577486417, 0.9171789075514756)),
  6181. (1e-3, (0.01496243430933372, 0.35048089844774266, 0.917180899947689)),
  6182. (1e-4, (0.014962437234895118, 0.3504809466745317, 0.9171809198714769)),
  6183. (1e-6, (0.01496243726444329, 0.3504809471616223, 0.9171809200727071)),
  6184. (1e-9, (0.014962437264446245, 0.350480947161671, 0.9171809200727272))])
  6185. def test_cdf_small_chi(self, chi, expected):
  6186. x = np.array([0.1, 0.5, 0.9])
  6187. assert_allclose(stats.argus.cdf(x, chi), expected, rtol=1e-12)
  6188. # Expected values were computed with mpmath (code: see gh-13370).
  6189. @pytest.mark.parametrize(
  6190. 'chi, expected, rtol',
  6191. [(0.5, (0.5964284712757741, 0.052890651988588604), 1e-12),
  6192. (0.101, (0.5893490968089076, 0.053017469847275685), 1e-11),
  6193. (0.1, (0.5893431757009437, 0.05301755449499372), 1e-13),
  6194. (0.01, (0.5890515677940915, 0.05302167905837031), 1e-13),
  6195. (1e-3, (0.5890486520005177, 0.053021719862088104), 1e-13),
  6196. (1e-4, (0.5890486228426105, 0.0530217202700811), 1e-13),
  6197. (1e-6, (0.5890486225481156, 0.05302172027420182), 1e-13),
  6198. (1e-9, (0.5890486225480862, 0.05302172027420224), 1e-13)])
  6199. def test_stats_small_chi(self, chi, expected, rtol):
  6200. val = stats.argus.stats(chi, moments='mv')
  6201. assert_allclose(val, expected, rtol=rtol)
  6202. class TestNakagami:
  6203. def test_logpdf(self):
  6204. # Test nakagami logpdf for an input where the PDF is smaller
  6205. # than can be represented with 64 bit floating point.
  6206. # The expected value of logpdf was computed with mpmath:
  6207. #
  6208. # def logpdf(x, nu):
  6209. # x = mpmath.mpf(x)
  6210. # nu = mpmath.mpf(nu)
  6211. # return (mpmath.log(2) + nu*mpmath.log(nu) -
  6212. # mpmath.loggamma(nu) + (2*nu - 1)*mpmath.log(x) -
  6213. # nu*x**2)
  6214. #
  6215. nu = 2.5
  6216. x = 25
  6217. logp = stats.nakagami.logpdf(x, nu)
  6218. assert_allclose(logp, -1546.9253055607549)
  6219. def test_sf_isf(self):
  6220. # Test nakagami sf and isf when the survival function
  6221. # value is very small.
  6222. # The expected value of the survival function was computed
  6223. # with mpmath:
  6224. #
  6225. # def sf(x, nu):
  6226. # x = mpmath.mpf(x)
  6227. # nu = mpmath.mpf(nu)
  6228. # return mpmath.gammainc(nu, nu*x*x, regularized=True)
  6229. #
  6230. nu = 2.5
  6231. x0 = 5.0
  6232. sf = stats.nakagami.sf(x0, nu)
  6233. assert_allclose(sf, 2.736273158588307e-25, rtol=1e-13)
  6234. # Check round trip back to x0.
  6235. x1 = stats.nakagami.isf(sf, nu)
  6236. assert_allclose(x1, x0, rtol=1e-13)
  6237. @pytest.mark.xfail(reason="Fit of nakagami not reliable, see gh-10908.")
  6238. @pytest.mark.parametrize('nu', [1.6, 2.5, 3.9])
  6239. @pytest.mark.parametrize('loc', [25.0, 10, 35])
  6240. @pytest.mark.parametrize('scale', [13, 5, 20])
  6241. def test_fit(self, nu, loc, scale):
  6242. # Regression test for gh-13396 (21/27 cases failed previously)
  6243. # The first tuple of the parameters' values is discussed in gh-10908
  6244. N = 100
  6245. samples = stats.nakagami.rvs(size=N, nu=nu, loc=loc,
  6246. scale=scale, random_state=1337)
  6247. nu_est, loc_est, scale_est = stats.nakagami.fit(samples)
  6248. assert_allclose(nu_est, nu, rtol=0.2)
  6249. assert_allclose(loc_est, loc, rtol=0.2)
  6250. assert_allclose(scale_est, scale, rtol=0.2)
  6251. def dlogl_dnu(nu, loc, scale):
  6252. return ((-2*nu + 1) * np.sum(1/(samples - loc))
  6253. + 2*nu/scale**2 * np.sum(samples - loc))
  6254. def dlogl_dloc(nu, loc, scale):
  6255. return (N * (1 + np.log(nu) - polygamma(0, nu)) +
  6256. 2 * np.sum(np.log((samples - loc) / scale))
  6257. - np.sum(((samples - loc) / scale)**2))
  6258. def dlogl_dscale(nu, loc, scale):
  6259. return (- 2 * N * nu / scale
  6260. + 2 * nu / scale ** 3 * np.sum((samples - loc) ** 2))
  6261. assert_allclose(dlogl_dnu(nu_est, loc_est, scale_est), 0, atol=1e-3)
  6262. assert_allclose(dlogl_dloc(nu_est, loc_est, scale_est), 0, atol=1e-3)
  6263. assert_allclose(dlogl_dscale(nu_est, loc_est, scale_est), 0, atol=1e-3)
  6264. @pytest.mark.parametrize('loc', [25.0, 10, 35])
  6265. @pytest.mark.parametrize('scale', [13, 5, 20])
  6266. def test_fit_nu(self, loc, scale):
  6267. # For nu = 0.5, we have analytical values for
  6268. # the MLE of the loc and the scale
  6269. nu = 0.5
  6270. n = 100
  6271. samples = stats.nakagami.rvs(size=n, nu=nu, loc=loc,
  6272. scale=scale, random_state=1337)
  6273. nu_est, loc_est, scale_est = stats.nakagami.fit(samples, f0=nu)
  6274. # Analytical values
  6275. loc_theo = np.min(samples)
  6276. scale_theo = np.sqrt(np.mean((samples - loc_est) ** 2))
  6277. assert_allclose(nu_est, nu, rtol=1e-7)
  6278. assert_allclose(loc_est, loc_theo, rtol=1e-7)
  6279. assert_allclose(scale_est, scale_theo, rtol=1e-7)
  6280. class TestWrapCauchy:
  6281. def test_cdf_shape_broadcasting(self):
  6282. # Regression test for gh-13791.
  6283. # Check that wrapcauchy.cdf broadcasts the shape parameter
  6284. # correctly.
  6285. c = np.array([[0.03, 0.25], [0.5, 0.75]])
  6286. x = np.array([[1.0], [4.0]])
  6287. p = stats.wrapcauchy.cdf(x, c)
  6288. assert p.shape == (2, 2)
  6289. scalar_values = [stats.wrapcauchy.cdf(x1, c1)
  6290. for (x1, c1) in np.nditer((x, c))]
  6291. assert_allclose(p.ravel(), scalar_values, rtol=1e-13)
  6292. def test_cdf_center(self):
  6293. p = stats.wrapcauchy.cdf(np.pi, 0.03)
  6294. assert_allclose(p, 0.5, rtol=1e-14)
  6295. def test_cdf(self):
  6296. x1 = 1.0 # less than pi
  6297. x2 = 4.0 # greater than pi
  6298. c = 0.75
  6299. p = stats.wrapcauchy.cdf([x1, x2], c)
  6300. cr = (1 + c)/(1 - c)
  6301. assert_allclose(p[0], np.arctan(cr*np.tan(x1/2))/np.pi)
  6302. assert_allclose(p[1], 1 - np.arctan(cr*np.tan(np.pi - x2/2))/np.pi)
  6303. def test_rvs_no_size_error():
  6304. # _rvs methods must have parameter `size`; see gh-11394
  6305. class rvs_no_size_gen(stats.rv_continuous):
  6306. def _rvs(self):
  6307. return 1
  6308. rvs_no_size = rvs_no_size_gen(name='rvs_no_size')
  6309. with assert_raises(TypeError, match=r"_rvs\(\) got (an|\d) unexpected"):
  6310. rvs_no_size.rvs()
  6311. @pytest.mark.parametrize('distname, args', invdistdiscrete + invdistcont)
  6312. def test_support_gh13294_regression(distname, args):
  6313. if distname in skip_test_support_gh13294_regression:
  6314. pytest.skip(f"skipping test for the support method for "
  6315. f"distribution {distname}.")
  6316. dist = getattr(stats, distname)
  6317. # test support method with invalid arguents
  6318. if isinstance(dist, stats.rv_continuous):
  6319. # test with valid scale
  6320. if len(args) != 0:
  6321. a0, b0 = dist.support(*args)
  6322. assert_equal(a0, np.nan)
  6323. assert_equal(b0, np.nan)
  6324. # test with invalid scale
  6325. # For some distributions, that take no parameters,
  6326. # the case of only invalid scale occurs and hence,
  6327. # it is implicitly tested in this test case.
  6328. loc1, scale1 = 0, -1
  6329. a1, b1 = dist.support(*args, loc1, scale1)
  6330. assert_equal(a1, np.nan)
  6331. assert_equal(b1, np.nan)
  6332. else:
  6333. a, b = dist.support(*args)
  6334. assert_equal(a, np.nan)
  6335. assert_equal(b, np.nan)
  6336. def test_support_broadcasting_gh13294_regression():
  6337. a0, b0 = stats.norm.support([0, 0, 0, 1], [1, 1, 1, -1])
  6338. ex_a0 = np.array([-np.inf, -np.inf, -np.inf, np.nan])
  6339. ex_b0 = np.array([np.inf, np.inf, np.inf, np.nan])
  6340. assert_equal(a0, ex_a0)
  6341. assert_equal(b0, ex_b0)
  6342. assert a0.shape == ex_a0.shape
  6343. assert b0.shape == ex_b0.shape
  6344. a1, b1 = stats.norm.support([], [])
  6345. ex_a1, ex_b1 = np.array([]), np.array([])
  6346. assert_equal(a1, ex_a1)
  6347. assert_equal(b1, ex_b1)
  6348. assert a1.shape == ex_a1.shape
  6349. assert b1.shape == ex_b1.shape
  6350. a2, b2 = stats.norm.support([0, 0, 0, 1], [-1])
  6351. ex_a2 = np.array(4*[np.nan])
  6352. ex_b2 = np.array(4*[np.nan])
  6353. assert_equal(a2, ex_a2)
  6354. assert_equal(b2, ex_b2)
  6355. assert a2.shape == ex_a2.shape
  6356. assert b2.shape == ex_b2.shape
  6357. def test_stats_broadcasting_gh14953_regression():
  6358. # test case in gh14953
  6359. loc = [0., 0.]
  6360. scale = [[1.], [2.], [3.]]
  6361. assert_equal(stats.norm.var(loc, scale), [[1., 1.], [4., 4.], [9., 9.]])
  6362. # test some edge cases
  6363. loc = np.empty((0, ))
  6364. scale = np.empty((1, 0))
  6365. assert stats.norm.var(loc, scale).shape == (1, 0)
  6366. # Check a few values of the cosine distribution's cdf, sf, ppf and
  6367. # isf methods. Expected values were computed with mpmath.
  6368. @pytest.mark.parametrize('x, expected',
  6369. [(-3.14159, 4.956444476505336e-19),
  6370. (3.14, 0.9999999998928399)])
  6371. def test_cosine_cdf_sf(x, expected):
  6372. assert_allclose(stats.cosine.cdf(x), expected)
  6373. assert_allclose(stats.cosine.sf(-x), expected)
  6374. @pytest.mark.parametrize('p, expected',
  6375. [(1e-6, -3.1080612413765905),
  6376. (1e-17, -3.141585429601399),
  6377. (0.975, 2.1447547020964923)])
  6378. def test_cosine_ppf_isf(p, expected):
  6379. assert_allclose(stats.cosine.ppf(p), expected)
  6380. assert_allclose(stats.cosine.isf(p), -expected)
  6381. def test_cosine_logpdf_endpoints():
  6382. logp = stats.cosine.logpdf([-np.pi, np.pi])
  6383. assert_equal(logp, [-np.inf, -np.inf])
  6384. def test_distr_params_lists():
  6385. # distribution objects are extra distributions added in
  6386. # test_discrete_basic. All other distributions are strings (names)
  6387. # and so we only choose those to compare whether both lists match.
  6388. discrete_distnames = {name for name, _ in distdiscrete
  6389. if isinstance(name, str)}
  6390. invdiscrete_distnames = {name for name, _ in invdistdiscrete}
  6391. assert discrete_distnames == invdiscrete_distnames
  6392. cont_distnames = {name for name, _ in distcont}
  6393. invcont_distnames = {name for name, _ in invdistcont}
  6394. assert cont_distnames == invcont_distnames
  6395. def test_moment_order_4():
  6396. # gh-13655 reported that if a distribution has a `_stats` method that
  6397. # accepts the `moments` parameter, then if the distribution's `moment`
  6398. # method is called with `order=4`, the faster/more accurate`_stats` gets
  6399. # called, but the results aren't used, and the generic `_munp` method is
  6400. # called to calculate the moment anyway. This tests that the issue has
  6401. # been fixed.
  6402. # stats.skewnorm._stats accepts the `moments` keyword
  6403. stats.skewnorm._stats(a=0, moments='k') # no failure = has `moments`
  6404. # When `moment` is called, `_stats` is used, so the moment is very accurate
  6405. # (exactly equal to Pearson's kurtosis of the normal distribution, 3)
  6406. assert stats.skewnorm.moment(order=4, a=0) == 3.0
  6407. # At the time of gh-13655, skewnorm._munp() used the generic method
  6408. # to compute its result, which was inefficient and not very accurate.
  6409. # At that time, the following assertion would fail. skewnorm._munp()
  6410. # has since been made more accurate and efficient, so now this test
  6411. # is expected to pass.
  6412. assert stats.skewnorm._munp(4, 0) == 3.0