_function_base_impl.py 191 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827
  1. import builtins
  2. import collections.abc
  3. import functools
  4. import re
  5. import sys
  6. import warnings
  7. import numpy as np
  8. import numpy._core.numeric as _nx
  9. from numpy._core import transpose, overrides
  10. from numpy._core.numeric import (
  11. ones, zeros_like, arange, concatenate, array, asarray, asanyarray, empty,
  12. ndarray, take, dot, where, intp, integer, isscalar, absolute
  13. )
  14. from numpy._core.umath import (
  15. pi, add, arctan2, frompyfunc, cos, less_equal, sqrt, sin,
  16. mod, exp, not_equal, subtract, minimum
  17. )
  18. from numpy._core.fromnumeric import (
  19. ravel, nonzero, partition, mean, any, sum
  20. )
  21. from numpy._core.numerictypes import typecodes
  22. from numpy.lib._twodim_base_impl import diag
  23. from numpy._core.multiarray import (
  24. _place, bincount, normalize_axis_index, _monotonicity,
  25. interp as compiled_interp, interp_complex as compiled_interp_complex
  26. )
  27. from numpy._core._multiarray_umath import _array_converter
  28. from numpy._utils import set_module
  29. # needed in this module for compatibility
  30. from numpy.lib._histograms_impl import histogram, histogramdd # noqa: F401
  31. array_function_dispatch = functools.partial(
  32. overrides.array_function_dispatch, module='numpy')
  33. __all__ = [
  34. 'select', 'piecewise', 'trim_zeros', 'copy', 'iterable', 'percentile',
  35. 'diff', 'gradient', 'angle', 'unwrap', 'sort_complex', 'flip',
  36. 'rot90', 'extract', 'place', 'vectorize', 'asarray_chkfinite', 'average',
  37. 'bincount', 'digitize', 'cov', 'corrcoef',
  38. 'median', 'sinc', 'hamming', 'hanning', 'bartlett',
  39. 'blackman', 'kaiser', 'trapezoid', 'trapz', 'i0',
  40. 'meshgrid', 'delete', 'insert', 'append', 'interp',
  41. 'quantile'
  42. ]
  43. # _QuantileMethods is a dictionary listing all the supported methods to
  44. # compute quantile/percentile.
  45. #
  46. # Below virtual_index refers to the index of the element where the percentile
  47. # would be found in the sorted sample.
  48. # When the sample contains exactly the percentile wanted, the virtual_index is
  49. # an integer to the index of this element.
  50. # When the percentile wanted is in between two elements, the virtual_index
  51. # is made of a integer part (a.k.a 'i' or 'left') and a fractional part
  52. # (a.k.a 'g' or 'gamma')
  53. #
  54. # Each method in _QuantileMethods has two properties
  55. # get_virtual_index : Callable
  56. # The function used to compute the virtual_index.
  57. # fix_gamma : Callable
  58. # A function used for discrete methods to force the index to a specific value.
  59. _QuantileMethods = dict(
  60. # --- HYNDMAN and FAN METHODS
  61. # Discrete methods
  62. inverted_cdf=dict(
  63. get_virtual_index=lambda n, quantiles: _inverted_cdf(n, quantiles),
  64. fix_gamma=None, # should never be called
  65. ),
  66. averaged_inverted_cdf=dict(
  67. get_virtual_index=lambda n, quantiles: (n * quantiles) - 1,
  68. fix_gamma=lambda gamma, _: _get_gamma_mask(
  69. shape=gamma.shape,
  70. default_value=1.,
  71. conditioned_value=0.5,
  72. where=gamma == 0),
  73. ),
  74. closest_observation=dict(
  75. get_virtual_index=lambda n, quantiles: _closest_observation(n,
  76. quantiles),
  77. fix_gamma=None, # should never be called
  78. ),
  79. # Continuous methods
  80. interpolated_inverted_cdf=dict(
  81. get_virtual_index=lambda n, quantiles:
  82. _compute_virtual_index(n, quantiles, 0, 1),
  83. fix_gamma=lambda gamma, _: gamma,
  84. ),
  85. hazen=dict(
  86. get_virtual_index=lambda n, quantiles:
  87. _compute_virtual_index(n, quantiles, 0.5, 0.5),
  88. fix_gamma=lambda gamma, _: gamma,
  89. ),
  90. weibull=dict(
  91. get_virtual_index=lambda n, quantiles:
  92. _compute_virtual_index(n, quantiles, 0, 0),
  93. fix_gamma=lambda gamma, _: gamma,
  94. ),
  95. # Default method.
  96. # To avoid some rounding issues, `(n-1) * quantiles` is preferred to
  97. # `_compute_virtual_index(n, quantiles, 1, 1)`.
  98. # They are mathematically equivalent.
  99. linear=dict(
  100. get_virtual_index=lambda n, quantiles: (n - 1) * quantiles,
  101. fix_gamma=lambda gamma, _: gamma,
  102. ),
  103. median_unbiased=dict(
  104. get_virtual_index=lambda n, quantiles:
  105. _compute_virtual_index(n, quantiles, 1 / 3.0, 1 / 3.0),
  106. fix_gamma=lambda gamma, _: gamma,
  107. ),
  108. normal_unbiased=dict(
  109. get_virtual_index=lambda n, quantiles:
  110. _compute_virtual_index(n, quantiles, 3 / 8.0, 3 / 8.0),
  111. fix_gamma=lambda gamma, _: gamma,
  112. ),
  113. # --- OTHER METHODS
  114. lower=dict(
  115. get_virtual_index=lambda n, quantiles: np.floor(
  116. (n - 1) * quantiles).astype(np.intp),
  117. fix_gamma=None, # should never be called, index dtype is int
  118. ),
  119. higher=dict(
  120. get_virtual_index=lambda n, quantiles: np.ceil(
  121. (n - 1) * quantiles).astype(np.intp),
  122. fix_gamma=None, # should never be called, index dtype is int
  123. ),
  124. midpoint=dict(
  125. get_virtual_index=lambda n, quantiles: 0.5 * (
  126. np.floor((n - 1) * quantiles)
  127. + np.ceil((n - 1) * quantiles)),
  128. fix_gamma=lambda gamma, index: _get_gamma_mask(
  129. shape=gamma.shape,
  130. default_value=0.5,
  131. conditioned_value=0.,
  132. where=index % 1 == 0),
  133. ),
  134. nearest=dict(
  135. get_virtual_index=lambda n, quantiles: np.around(
  136. (n - 1) * quantiles).astype(np.intp),
  137. fix_gamma=None,
  138. # should never be called, index dtype is int
  139. ))
  140. def _rot90_dispatcher(m, k=None, axes=None):
  141. return (m,)
  142. @array_function_dispatch(_rot90_dispatcher)
  143. def rot90(m, k=1, axes=(0, 1)):
  144. """
  145. Rotate an array by 90 degrees in the plane specified by axes.
  146. Rotation direction is from the first towards the second axis.
  147. This means for a 2D array with the default `k` and `axes`, the
  148. rotation will be counterclockwise.
  149. Parameters
  150. ----------
  151. m : array_like
  152. Array of two or more dimensions.
  153. k : integer
  154. Number of times the array is rotated by 90 degrees.
  155. axes : (2,) array_like
  156. The array is rotated in the plane defined by the axes.
  157. Axes must be different.
  158. Returns
  159. -------
  160. y : ndarray
  161. A rotated view of `m`.
  162. See Also
  163. --------
  164. flip : Reverse the order of elements in an array along the given axis.
  165. fliplr : Flip an array horizontally.
  166. flipud : Flip an array vertically.
  167. Notes
  168. -----
  169. ``rot90(m, k=1, axes=(1,0))`` is the reverse of
  170. ``rot90(m, k=1, axes=(0,1))``
  171. ``rot90(m, k=1, axes=(1,0))`` is equivalent to
  172. ``rot90(m, k=-1, axes=(0,1))``
  173. Examples
  174. --------
  175. >>> import numpy as np
  176. >>> m = np.array([[1,2],[3,4]], int)
  177. >>> m
  178. array([[1, 2],
  179. [3, 4]])
  180. >>> np.rot90(m)
  181. array([[2, 4],
  182. [1, 3]])
  183. >>> np.rot90(m, 2)
  184. array([[4, 3],
  185. [2, 1]])
  186. >>> m = np.arange(8).reshape((2,2,2))
  187. >>> np.rot90(m, 1, (1,2))
  188. array([[[1, 3],
  189. [0, 2]],
  190. [[5, 7],
  191. [4, 6]]])
  192. """
  193. axes = tuple(axes)
  194. if len(axes) != 2:
  195. raise ValueError("len(axes) must be 2.")
  196. m = asanyarray(m)
  197. if axes[0] == axes[1] or absolute(axes[0] - axes[1]) == m.ndim:
  198. raise ValueError("Axes must be different.")
  199. if (axes[0] >= m.ndim or axes[0] < -m.ndim
  200. or axes[1] >= m.ndim or axes[1] < -m.ndim):
  201. raise ValueError("Axes={} out of range for array of ndim={}."
  202. .format(axes, m.ndim))
  203. k %= 4
  204. if k == 0:
  205. return m[:]
  206. if k == 2:
  207. return flip(flip(m, axes[0]), axes[1])
  208. axes_list = arange(0, m.ndim)
  209. (axes_list[axes[0]], axes_list[axes[1]]) = (axes_list[axes[1]],
  210. axes_list[axes[0]])
  211. if k == 1:
  212. return transpose(flip(m, axes[1]), axes_list)
  213. else:
  214. # k == 3
  215. return flip(transpose(m, axes_list), axes[1])
  216. def _flip_dispatcher(m, axis=None):
  217. return (m,)
  218. @array_function_dispatch(_flip_dispatcher)
  219. def flip(m, axis=None):
  220. """
  221. Reverse the order of elements in an array along the given axis.
  222. The shape of the array is preserved, but the elements are reordered.
  223. Parameters
  224. ----------
  225. m : array_like
  226. Input array.
  227. axis : None or int or tuple of ints, optional
  228. Axis or axes along which to flip over. The default,
  229. axis=None, will flip over all of the axes of the input array.
  230. If axis is negative it counts from the last to the first axis.
  231. If axis is a tuple of ints, flipping is performed on all of the axes
  232. specified in the tuple.
  233. Returns
  234. -------
  235. out : array_like
  236. A view of `m` with the entries of axis reversed. Since a view is
  237. returned, this operation is done in constant time.
  238. See Also
  239. --------
  240. flipud : Flip an array vertically (axis=0).
  241. fliplr : Flip an array horizontally (axis=1).
  242. Notes
  243. -----
  244. flip(m, 0) is equivalent to flipud(m).
  245. flip(m, 1) is equivalent to fliplr(m).
  246. flip(m, n) corresponds to ``m[...,::-1,...]`` with ``::-1`` at position n.
  247. flip(m) corresponds to ``m[::-1,::-1,...,::-1]`` with ``::-1`` at all
  248. positions.
  249. flip(m, (0, 1)) corresponds to ``m[::-1,::-1,...]`` with ``::-1`` at
  250. position 0 and position 1.
  251. Examples
  252. --------
  253. >>> import numpy as np
  254. >>> A = np.arange(8).reshape((2,2,2))
  255. >>> A
  256. array([[[0, 1],
  257. [2, 3]],
  258. [[4, 5],
  259. [6, 7]]])
  260. >>> np.flip(A, 0)
  261. array([[[4, 5],
  262. [6, 7]],
  263. [[0, 1],
  264. [2, 3]]])
  265. >>> np.flip(A, 1)
  266. array([[[2, 3],
  267. [0, 1]],
  268. [[6, 7],
  269. [4, 5]]])
  270. >>> np.flip(A)
  271. array([[[7, 6],
  272. [5, 4]],
  273. [[3, 2],
  274. [1, 0]]])
  275. >>> np.flip(A, (0, 2))
  276. array([[[5, 4],
  277. [7, 6]],
  278. [[1, 0],
  279. [3, 2]]])
  280. >>> rng = np.random.default_rng()
  281. >>> A = rng.normal(size=(3,4,5))
  282. >>> np.all(np.flip(A,2) == A[:,:,::-1,...])
  283. True
  284. """
  285. if not hasattr(m, 'ndim'):
  286. m = asarray(m)
  287. if axis is None:
  288. indexer = (np.s_[::-1],) * m.ndim
  289. else:
  290. axis = _nx.normalize_axis_tuple(axis, m.ndim)
  291. indexer = [np.s_[:]] * m.ndim
  292. for ax in axis:
  293. indexer[ax] = np.s_[::-1]
  294. indexer = tuple(indexer)
  295. return m[indexer]
  296. @set_module('numpy')
  297. def iterable(y):
  298. """
  299. Check whether or not an object can be iterated over.
  300. Parameters
  301. ----------
  302. y : object
  303. Input object.
  304. Returns
  305. -------
  306. b : bool
  307. Return ``True`` if the object has an iterator method or is a
  308. sequence and ``False`` otherwise.
  309. Examples
  310. --------
  311. >>> import numpy as np
  312. >>> np.iterable([1, 2, 3])
  313. True
  314. >>> np.iterable(2)
  315. False
  316. Notes
  317. -----
  318. In most cases, the results of ``np.iterable(obj)`` are consistent with
  319. ``isinstance(obj, collections.abc.Iterable)``. One notable exception is
  320. the treatment of 0-dimensional arrays::
  321. >>> from collections.abc import Iterable
  322. >>> a = np.array(1.0) # 0-dimensional numpy array
  323. >>> isinstance(a, Iterable)
  324. True
  325. >>> np.iterable(a)
  326. False
  327. """
  328. try:
  329. iter(y)
  330. except TypeError:
  331. return False
  332. return True
  333. def _weights_are_valid(weights, a, axis):
  334. """Validate weights array.
  335. We assume, weights is not None.
  336. """
  337. wgt = np.asanyarray(weights)
  338. # Sanity checks
  339. if a.shape != wgt.shape:
  340. if axis is None:
  341. raise TypeError(
  342. "Axis must be specified when shapes of a and weights "
  343. "differ.")
  344. if wgt.shape != tuple(a.shape[ax] for ax in axis):
  345. raise ValueError(
  346. "Shape of weights must be consistent with "
  347. "shape of a along specified axis.")
  348. # setup wgt to broadcast along axis
  349. wgt = wgt.transpose(np.argsort(axis))
  350. wgt = wgt.reshape(tuple((s if ax in axis else 1)
  351. for ax, s in enumerate(a.shape)))
  352. return wgt
  353. def _average_dispatcher(a, axis=None, weights=None, returned=None, *,
  354. keepdims=None):
  355. return (a, weights)
  356. @array_function_dispatch(_average_dispatcher)
  357. def average(a, axis=None, weights=None, returned=False, *,
  358. keepdims=np._NoValue):
  359. """
  360. Compute the weighted average along the specified axis.
  361. Parameters
  362. ----------
  363. a : array_like
  364. Array containing data to be averaged. If `a` is not an array, a
  365. conversion is attempted.
  366. axis : None or int or tuple of ints, optional
  367. Axis or axes along which to average `a`. The default,
  368. `axis=None`, will average over all of the elements of the input array.
  369. If axis is negative it counts from the last to the first axis.
  370. If axis is a tuple of ints, averaging is performed on all of the axes
  371. specified in the tuple instead of a single axis or all the axes as
  372. before.
  373. weights : array_like, optional
  374. An array of weights associated with the values in `a`. Each value in
  375. `a` contributes to the average according to its associated weight.
  376. The array of weights must be the same shape as `a` if no axis is
  377. specified, otherwise the weights must have dimensions and shape
  378. consistent with `a` along the specified axis.
  379. If `weights=None`, then all data in `a` are assumed to have a
  380. weight equal to one.
  381. The calculation is::
  382. avg = sum(a * weights) / sum(weights)
  383. where the sum is over all included elements.
  384. The only constraint on the values of `weights` is that `sum(weights)`
  385. must not be 0.
  386. returned : bool, optional
  387. Default is `False`. If `True`, the tuple (`average`, `sum_of_weights`)
  388. is returned, otherwise only the average is returned.
  389. If `weights=None`, `sum_of_weights` is equivalent to the number of
  390. elements over which the average is taken.
  391. keepdims : bool, optional
  392. If this is set to True, the axes which are reduced are left
  393. in the result as dimensions with size one. With this option,
  394. the result will broadcast correctly against the original `a`.
  395. *Note:* `keepdims` will not work with instances of `numpy.matrix`
  396. or other classes whose methods do not support `keepdims`.
  397. .. versionadded:: 1.23.0
  398. Returns
  399. -------
  400. retval, [sum_of_weights] : array_type or double
  401. Return the average along the specified axis. When `returned` is `True`,
  402. return a tuple with the average as the first element and the sum
  403. of the weights as the second element. `sum_of_weights` is of the
  404. same type as `retval`. The result dtype follows a general pattern.
  405. If `weights` is None, the result dtype will be that of `a` , or ``float64``
  406. if `a` is integral. Otherwise, if `weights` is not None and `a` is non-
  407. integral, the result type will be the type of lowest precision capable of
  408. representing values of both `a` and `weights`. If `a` happens to be
  409. integral, the previous rules still applies but the result dtype will
  410. at least be ``float64``.
  411. Raises
  412. ------
  413. ZeroDivisionError
  414. When all weights along axis are zero. See `numpy.ma.average` for a
  415. version robust to this type of error.
  416. TypeError
  417. When `weights` does not have the same shape as `a`, and `axis=None`.
  418. ValueError
  419. When `weights` does not have dimensions and shape consistent with `a`
  420. along specified `axis`.
  421. See Also
  422. --------
  423. mean
  424. ma.average : average for masked arrays -- useful if your data contains
  425. "missing" values
  426. numpy.result_type : Returns the type that results from applying the
  427. numpy type promotion rules to the arguments.
  428. Examples
  429. --------
  430. >>> import numpy as np
  431. >>> data = np.arange(1, 5)
  432. >>> data
  433. array([1, 2, 3, 4])
  434. >>> np.average(data)
  435. 2.5
  436. >>> np.average(np.arange(1, 11), weights=np.arange(10, 0, -1))
  437. 4.0
  438. >>> data = np.arange(6).reshape((3, 2))
  439. >>> data
  440. array([[0, 1],
  441. [2, 3],
  442. [4, 5]])
  443. >>> np.average(data, axis=1, weights=[1./4, 3./4])
  444. array([0.75, 2.75, 4.75])
  445. >>> np.average(data, weights=[1./4, 3./4])
  446. Traceback (most recent call last):
  447. ...
  448. TypeError: Axis must be specified when shapes of a and weights differ.
  449. With ``keepdims=True``, the following result has shape (3, 1).
  450. >>> np.average(data, axis=1, keepdims=True)
  451. array([[0.5],
  452. [2.5],
  453. [4.5]])
  454. >>> data = np.arange(8).reshape((2, 2, 2))
  455. >>> data
  456. array([[[0, 1],
  457. [2, 3]],
  458. [[4, 5],
  459. [6, 7]]])
  460. >>> np.average(data, axis=(0, 1), weights=[[1./4, 3./4], [1., 1./2]])
  461. array([3.4, 4.4])
  462. >>> np.average(data, axis=0, weights=[[1./4, 3./4], [1., 1./2]])
  463. Traceback (most recent call last):
  464. ...
  465. ValueError: Shape of weights must be consistent
  466. with shape of a along specified axis.
  467. """
  468. a = np.asanyarray(a)
  469. if axis is not None:
  470. axis = _nx.normalize_axis_tuple(axis, a.ndim, argname="axis")
  471. if keepdims is np._NoValue:
  472. # Don't pass on the keepdims argument if one wasn't given.
  473. keepdims_kw = {}
  474. else:
  475. keepdims_kw = {'keepdims': keepdims}
  476. if weights is None:
  477. avg = a.mean(axis, **keepdims_kw)
  478. avg_as_array = np.asanyarray(avg)
  479. scl = avg_as_array.dtype.type(a.size/avg_as_array.size)
  480. else:
  481. wgt = _weights_are_valid(weights=weights, a=a, axis=axis)
  482. if issubclass(a.dtype.type, (np.integer, np.bool)):
  483. result_dtype = np.result_type(a.dtype, wgt.dtype, 'f8')
  484. else:
  485. result_dtype = np.result_type(a.dtype, wgt.dtype)
  486. scl = wgt.sum(axis=axis, dtype=result_dtype, **keepdims_kw)
  487. if np.any(scl == 0.0):
  488. raise ZeroDivisionError(
  489. "Weights sum to zero, can't be normalized")
  490. avg = avg_as_array = np.multiply(a, wgt,
  491. dtype=result_dtype).sum(axis, **keepdims_kw) / scl
  492. if returned:
  493. if scl.shape != avg_as_array.shape:
  494. scl = np.broadcast_to(scl, avg_as_array.shape).copy()
  495. return avg, scl
  496. else:
  497. return avg
  498. @set_module('numpy')
  499. def asarray_chkfinite(a, dtype=None, order=None):
  500. """Convert the input to an array, checking for NaNs or Infs.
  501. Parameters
  502. ----------
  503. a : array_like
  504. Input data, in any form that can be converted to an array. This
  505. includes lists, lists of tuples, tuples, tuples of tuples, tuples
  506. of lists and ndarrays. Success requires no NaNs or Infs.
  507. dtype : data-type, optional
  508. By default, the data-type is inferred from the input data.
  509. order : {'C', 'F', 'A', 'K'}, optional
  510. Memory layout. 'A' and 'K' depend on the order of input array a.
  511. 'C' row-major (C-style),
  512. 'F' column-major (Fortran-style) memory representation.
  513. 'A' (any) means 'F' if `a` is Fortran contiguous, 'C' otherwise
  514. 'K' (keep) preserve input order
  515. Defaults to 'C'.
  516. Returns
  517. -------
  518. out : ndarray
  519. Array interpretation of `a`. No copy is performed if the input
  520. is already an ndarray. If `a` is a subclass of ndarray, a base
  521. class ndarray is returned.
  522. Raises
  523. ------
  524. ValueError
  525. Raises ValueError if `a` contains NaN (Not a Number) or Inf (Infinity).
  526. See Also
  527. --------
  528. asarray : Create and array.
  529. asanyarray : Similar function which passes through subclasses.
  530. ascontiguousarray : Convert input to a contiguous array.
  531. asfortranarray : Convert input to an ndarray with column-major
  532. memory order.
  533. fromiter : Create an array from an iterator.
  534. fromfunction : Construct an array by executing a function on grid
  535. positions.
  536. Examples
  537. --------
  538. >>> import numpy as np
  539. Convert a list into an array. If all elements are finite, then
  540. ``asarray_chkfinite`` is identical to ``asarray``.
  541. >>> a = [1, 2]
  542. >>> np.asarray_chkfinite(a, dtype=float)
  543. array([1., 2.])
  544. Raises ValueError if array_like contains Nans or Infs.
  545. >>> a = [1, 2, np.inf]
  546. >>> try:
  547. ... np.asarray_chkfinite(a)
  548. ... except ValueError:
  549. ... print('ValueError')
  550. ...
  551. ValueError
  552. """
  553. a = asarray(a, dtype=dtype, order=order)
  554. if a.dtype.char in typecodes['AllFloat'] and not np.isfinite(a).all():
  555. raise ValueError(
  556. "array must not contain infs or NaNs")
  557. return a
  558. def _piecewise_dispatcher(x, condlist, funclist, *args, **kw):
  559. yield x
  560. # support the undocumented behavior of allowing scalars
  561. if np.iterable(condlist):
  562. yield from condlist
  563. @array_function_dispatch(_piecewise_dispatcher)
  564. def piecewise(x, condlist, funclist, *args, **kw):
  565. """
  566. Evaluate a piecewise-defined function.
  567. Given a set of conditions and corresponding functions, evaluate each
  568. function on the input data wherever its condition is true.
  569. Parameters
  570. ----------
  571. x : ndarray or scalar
  572. The input domain.
  573. condlist : list of bool arrays or bool scalars
  574. Each boolean array corresponds to a function in `funclist`. Wherever
  575. `condlist[i]` is True, `funclist[i](x)` is used as the output value.
  576. Each boolean array in `condlist` selects a piece of `x`,
  577. and should therefore be of the same shape as `x`.
  578. The length of `condlist` must correspond to that of `funclist`.
  579. If one extra function is given, i.e. if
  580. ``len(funclist) == len(condlist) + 1``, then that extra function
  581. is the default value, used wherever all conditions are false.
  582. funclist : list of callables, f(x,*args,**kw), or scalars
  583. Each function is evaluated over `x` wherever its corresponding
  584. condition is True. It should take a 1d array as input and give an 1d
  585. array or a scalar value as output. If, instead of a callable,
  586. a scalar is provided then a constant function (``lambda x: scalar``) is
  587. assumed.
  588. args : tuple, optional
  589. Any further arguments given to `piecewise` are passed to the functions
  590. upon execution, i.e., if called ``piecewise(..., ..., 1, 'a')``, then
  591. each function is called as ``f(x, 1, 'a')``.
  592. kw : dict, optional
  593. Keyword arguments used in calling `piecewise` are passed to the
  594. functions upon execution, i.e., if called
  595. ``piecewise(..., ..., alpha=1)``, then each function is called as
  596. ``f(x, alpha=1)``.
  597. Returns
  598. -------
  599. out : ndarray
  600. The output is the same shape and type as x and is found by
  601. calling the functions in `funclist` on the appropriate portions of `x`,
  602. as defined by the boolean arrays in `condlist`. Portions not covered
  603. by any condition have a default value of 0.
  604. See Also
  605. --------
  606. choose, select, where
  607. Notes
  608. -----
  609. This is similar to choose or select, except that functions are
  610. evaluated on elements of `x` that satisfy the corresponding condition from
  611. `condlist`.
  612. The result is::
  613. |--
  614. |funclist[0](x[condlist[0]])
  615. out = |funclist[1](x[condlist[1]])
  616. |...
  617. |funclist[n2](x[condlist[n2]])
  618. |--
  619. Examples
  620. --------
  621. >>> import numpy as np
  622. Define the signum function, which is -1 for ``x < 0`` and +1 for ``x >= 0``.
  623. >>> x = np.linspace(-2.5, 2.5, 6)
  624. >>> np.piecewise(x, [x < 0, x >= 0], [-1, 1])
  625. array([-1., -1., -1., 1., 1., 1.])
  626. Define the absolute value, which is ``-x`` for ``x <0`` and ``x`` for
  627. ``x >= 0``.
  628. >>> np.piecewise(x, [x < 0, x >= 0], [lambda x: -x, lambda x: x])
  629. array([2.5, 1.5, 0.5, 0.5, 1.5, 2.5])
  630. Apply the same function to a scalar value.
  631. >>> y = -2
  632. >>> np.piecewise(y, [y < 0, y >= 0], [lambda x: -x, lambda x: x])
  633. array(2)
  634. """
  635. x = asanyarray(x)
  636. n2 = len(funclist)
  637. # undocumented: single condition is promoted to a list of one condition
  638. if isscalar(condlist) or (
  639. not isinstance(condlist[0], (list, ndarray)) and x.ndim != 0):
  640. condlist = [condlist]
  641. condlist = asarray(condlist, dtype=bool)
  642. n = len(condlist)
  643. if n == n2 - 1: # compute the "otherwise" condition.
  644. condelse = ~np.any(condlist, axis=0, keepdims=True)
  645. condlist = np.concatenate([condlist, condelse], axis=0)
  646. n += 1
  647. elif n != n2:
  648. raise ValueError(
  649. "with {} condition(s), either {} or {} functions are expected"
  650. .format(n, n, n+1)
  651. )
  652. y = zeros_like(x)
  653. for cond, func in zip(condlist, funclist):
  654. if not isinstance(func, collections.abc.Callable):
  655. y[cond] = func
  656. else:
  657. vals = x[cond]
  658. if vals.size > 0:
  659. y[cond] = func(vals, *args, **kw)
  660. return y
  661. def _select_dispatcher(condlist, choicelist, default=None):
  662. yield from condlist
  663. yield from choicelist
  664. @array_function_dispatch(_select_dispatcher)
  665. def select(condlist, choicelist, default=0):
  666. """
  667. Return an array drawn from elements in choicelist, depending on conditions.
  668. Parameters
  669. ----------
  670. condlist : list of bool ndarrays
  671. The list of conditions which determine from which array in `choicelist`
  672. the output elements are taken. When multiple conditions are satisfied,
  673. the first one encountered in `condlist` is used.
  674. choicelist : list of ndarrays
  675. The list of arrays from which the output elements are taken. It has
  676. to be of the same length as `condlist`.
  677. default : scalar, optional
  678. The element inserted in `output` when all conditions evaluate to False.
  679. Returns
  680. -------
  681. output : ndarray
  682. The output at position m is the m-th element of the array in
  683. `choicelist` where the m-th element of the corresponding array in
  684. `condlist` is True.
  685. See Also
  686. --------
  687. where : Return elements from one of two arrays depending on condition.
  688. take, choose, compress, diag, diagonal
  689. Examples
  690. --------
  691. >>> import numpy as np
  692. Beginning with an array of integers from 0 to 5 (inclusive),
  693. elements less than ``3`` are negated, elements greater than ``3``
  694. are squared, and elements not meeting either of these conditions
  695. (exactly ``3``) are replaced with a `default` value of ``42``.
  696. >>> x = np.arange(6)
  697. >>> condlist = [x<3, x>3]
  698. >>> choicelist = [x, x**2]
  699. >>> np.select(condlist, choicelist, 42)
  700. array([ 0, 1, 2, 42, 16, 25])
  701. When multiple conditions are satisfied, the first one encountered in
  702. `condlist` is used.
  703. >>> condlist = [x<=4, x>3]
  704. >>> choicelist = [x, x**2]
  705. >>> np.select(condlist, choicelist, 55)
  706. array([ 0, 1, 2, 3, 4, 25])
  707. """
  708. # Check the size of condlist and choicelist are the same, or abort.
  709. if len(condlist) != len(choicelist):
  710. raise ValueError(
  711. 'list of cases must be same length as list of conditions')
  712. # Now that the dtype is known, handle the deprecated select([], []) case
  713. if len(condlist) == 0:
  714. raise ValueError("select with an empty condition list is not possible")
  715. # TODO: This preserves the Python int, float, complex manually to get the
  716. # right `result_type` with NEP 50. Most likely we will grow a better
  717. # way to spell this (and this can be replaced).
  718. choicelist = [
  719. choice if type(choice) in (int, float, complex) else np.asarray(choice)
  720. for choice in choicelist]
  721. choicelist.append(default if type(default) in (int, float, complex)
  722. else np.asarray(default))
  723. try:
  724. dtype = np.result_type(*choicelist)
  725. except TypeError as e:
  726. msg = f'Choicelist and default value do not have a common dtype: {e}'
  727. raise TypeError(msg) from None
  728. # Convert conditions to arrays and broadcast conditions and choices
  729. # as the shape is needed for the result. Doing it separately optimizes
  730. # for example when all choices are scalars.
  731. condlist = np.broadcast_arrays(*condlist)
  732. choicelist = np.broadcast_arrays(*choicelist)
  733. # If cond array is not an ndarray in boolean format or scalar bool, abort.
  734. for i, cond in enumerate(condlist):
  735. if cond.dtype.type is not np.bool:
  736. raise TypeError(
  737. 'invalid entry {} in condlist: should be boolean ndarray'.format(i))
  738. if choicelist[0].ndim == 0:
  739. # This may be common, so avoid the call.
  740. result_shape = condlist[0].shape
  741. else:
  742. result_shape = np.broadcast_arrays(condlist[0], choicelist[0])[0].shape
  743. result = np.full(result_shape, choicelist[-1], dtype)
  744. # Use np.copyto to burn each choicelist array onto result, using the
  745. # corresponding condlist as a boolean mask. This is done in reverse
  746. # order since the first choice should take precedence.
  747. choicelist = choicelist[-2::-1]
  748. condlist = condlist[::-1]
  749. for choice, cond in zip(choicelist, condlist):
  750. np.copyto(result, choice, where=cond)
  751. return result
  752. def _copy_dispatcher(a, order=None, subok=None):
  753. return (a,)
  754. @array_function_dispatch(_copy_dispatcher)
  755. def copy(a, order='K', subok=False):
  756. """
  757. Return an array copy of the given object.
  758. Parameters
  759. ----------
  760. a : array_like
  761. Input data.
  762. order : {'C', 'F', 'A', 'K'}, optional
  763. Controls the memory layout of the copy. 'C' means C-order,
  764. 'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous,
  765. 'C' otherwise. 'K' means match the layout of `a` as closely
  766. as possible. (Note that this function and :meth:`ndarray.copy` are very
  767. similar, but have different default values for their order=
  768. arguments.)
  769. subok : bool, optional
  770. If True, then sub-classes will be passed-through, otherwise the
  771. returned array will be forced to be a base-class array (defaults to False).
  772. Returns
  773. -------
  774. arr : ndarray
  775. Array interpretation of `a`.
  776. See Also
  777. --------
  778. ndarray.copy : Preferred method for creating an array copy
  779. Notes
  780. -----
  781. This is equivalent to:
  782. >>> np.array(a, copy=True) #doctest: +SKIP
  783. The copy made of the data is shallow, i.e., for arrays with object dtype,
  784. the new array will point to the same objects.
  785. See Examples from `ndarray.copy`.
  786. Examples
  787. --------
  788. >>> import numpy as np
  789. Create an array x, with a reference y and a copy z:
  790. >>> x = np.array([1, 2, 3])
  791. >>> y = x
  792. >>> z = np.copy(x)
  793. Note that, when we modify x, y changes, but not z:
  794. >>> x[0] = 10
  795. >>> x[0] == y[0]
  796. True
  797. >>> x[0] == z[0]
  798. False
  799. Note that, np.copy clears previously set WRITEABLE=False flag.
  800. >>> a = np.array([1, 2, 3])
  801. >>> a.flags["WRITEABLE"] = False
  802. >>> b = np.copy(a)
  803. >>> b.flags["WRITEABLE"]
  804. True
  805. >>> b[0] = 3
  806. >>> b
  807. array([3, 2, 3])
  808. """
  809. return array(a, order=order, subok=subok, copy=True)
  810. # Basic operations
  811. def _gradient_dispatcher(f, *varargs, axis=None, edge_order=None):
  812. yield f
  813. yield from varargs
  814. @array_function_dispatch(_gradient_dispatcher)
  815. def gradient(f, *varargs, axis=None, edge_order=1):
  816. """
  817. Return the gradient of an N-dimensional array.
  818. The gradient is computed using second order accurate central differences
  819. in the interior points and either first or second order accurate one-sides
  820. (forward or backwards) differences at the boundaries.
  821. The returned gradient hence has the same shape as the input array.
  822. Parameters
  823. ----------
  824. f : array_like
  825. An N-dimensional array containing samples of a scalar function.
  826. varargs : list of scalar or array, optional
  827. Spacing between f values. Default unitary spacing for all dimensions.
  828. Spacing can be specified using:
  829. 1. single scalar to specify a sample distance for all dimensions.
  830. 2. N scalars to specify a constant sample distance for each dimension.
  831. i.e. `dx`, `dy`, `dz`, ...
  832. 3. N arrays to specify the coordinates of the values along each
  833. dimension of F. The length of the array must match the size of
  834. the corresponding dimension
  835. 4. Any combination of N scalars/arrays with the meaning of 2. and 3.
  836. If `axis` is given, the number of varargs must equal the number of axes.
  837. Default: 1. (see Examples below).
  838. edge_order : {1, 2}, optional
  839. Gradient is calculated using N-th order accurate differences
  840. at the boundaries. Default: 1.
  841. axis : None or int or tuple of ints, optional
  842. Gradient is calculated only along the given axis or axes
  843. The default (axis = None) is to calculate the gradient for all the axes
  844. of the input array. axis may be negative, in which case it counts from
  845. the last to the first axis.
  846. Returns
  847. -------
  848. gradient : ndarray or tuple of ndarray
  849. A tuple of ndarrays (or a single ndarray if there is only one
  850. dimension) corresponding to the derivatives of f with respect
  851. to each dimension. Each derivative has the same shape as f.
  852. Examples
  853. --------
  854. >>> import numpy as np
  855. >>> f = np.array([1, 2, 4, 7, 11, 16])
  856. >>> np.gradient(f)
  857. array([1. , 1.5, 2.5, 3.5, 4.5, 5. ])
  858. >>> np.gradient(f, 2)
  859. array([0.5 , 0.75, 1.25, 1.75, 2.25, 2.5 ])
  860. Spacing can be also specified with an array that represents the coordinates
  861. of the values F along the dimensions.
  862. For instance a uniform spacing:
  863. >>> x = np.arange(f.size)
  864. >>> np.gradient(f, x)
  865. array([1. , 1.5, 2.5, 3.5, 4.5, 5. ])
  866. Or a non uniform one:
  867. >>> x = np.array([0., 1., 1.5, 3.5, 4., 6.])
  868. >>> np.gradient(f, x)
  869. array([1. , 3. , 3.5, 6.7, 6.9, 2.5])
  870. For two dimensional arrays, the return will be two arrays ordered by
  871. axis. In this example the first array stands for the gradient in
  872. rows and the second one in columns direction:
  873. >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]]))
  874. (array([[ 2., 2., -1.],
  875. [ 2., 2., -1.]]),
  876. array([[1. , 2.5, 4. ],
  877. [1. , 1. , 1. ]]))
  878. In this example the spacing is also specified:
  879. uniform for axis=0 and non uniform for axis=1
  880. >>> dx = 2.
  881. >>> y = [1., 1.5, 3.5]
  882. >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]]), dx, y)
  883. (array([[ 1. , 1. , -0.5],
  884. [ 1. , 1. , -0.5]]),
  885. array([[2. , 2. , 2. ],
  886. [2. , 1.7, 0.5]]))
  887. It is possible to specify how boundaries are treated using `edge_order`
  888. >>> x = np.array([0, 1, 2, 3, 4])
  889. >>> f = x**2
  890. >>> np.gradient(f, edge_order=1)
  891. array([1., 2., 4., 6., 7.])
  892. >>> np.gradient(f, edge_order=2)
  893. array([0., 2., 4., 6., 8.])
  894. The `axis` keyword can be used to specify a subset of axes of which the
  895. gradient is calculated
  896. >>> np.gradient(np.array([[1, 2, 6], [3, 4, 5]]), axis=0)
  897. array([[ 2., 2., -1.],
  898. [ 2., 2., -1.]])
  899. The `varargs` argument defines the spacing between sample points in the
  900. input array. It can take two forms:
  901. 1. An array, specifying coordinates, which may be unevenly spaced:
  902. >>> x = np.array([0., 2., 3., 6., 8.])
  903. >>> y = x ** 2
  904. >>> np.gradient(y, x, edge_order=2)
  905. array([ 0., 4., 6., 12., 16.])
  906. 2. A scalar, representing the fixed sample distance:
  907. >>> dx = 2
  908. >>> x = np.array([0., 2., 4., 6., 8.])
  909. >>> y = x ** 2
  910. >>> np.gradient(y, dx, edge_order=2)
  911. array([ 0., 4., 8., 12., 16.])
  912. It's possible to provide different data for spacing along each dimension.
  913. The number of arguments must match the number of dimensions in the input
  914. data.
  915. >>> dx = 2
  916. >>> dy = 3
  917. >>> x = np.arange(0, 6, dx)
  918. >>> y = np.arange(0, 9, dy)
  919. >>> xs, ys = np.meshgrid(x, y)
  920. >>> zs = xs + 2 * ys
  921. >>> np.gradient(zs, dy, dx) # Passing two scalars
  922. (array([[2., 2., 2.],
  923. [2., 2., 2.],
  924. [2., 2., 2.]]),
  925. array([[1., 1., 1.],
  926. [1., 1., 1.],
  927. [1., 1., 1.]]))
  928. Mixing scalars and arrays is also allowed:
  929. >>> np.gradient(zs, y, dx) # Passing one array and one scalar
  930. (array([[2., 2., 2.],
  931. [2., 2., 2.],
  932. [2., 2., 2.]]),
  933. array([[1., 1., 1.],
  934. [1., 1., 1.],
  935. [1., 1., 1.]]))
  936. Notes
  937. -----
  938. Assuming that :math:`f\\in C^{3}` (i.e., :math:`f` has at least 3 continuous
  939. derivatives) and let :math:`h_{*}` be a non-homogeneous stepsize, we
  940. minimize the "consistency error" :math:`\\eta_{i}` between the true gradient
  941. and its estimate from a linear combination of the neighboring grid-points:
  942. .. math::
  943. \\eta_{i} = f_{i}^{\\left(1\\right)} -
  944. \\left[ \\alpha f\\left(x_{i}\\right) +
  945. \\beta f\\left(x_{i} + h_{d}\\right) +
  946. \\gamma f\\left(x_{i}-h_{s}\\right)
  947. \\right]
  948. By substituting :math:`f(x_{i} + h_{d})` and :math:`f(x_{i} - h_{s})`
  949. with their Taylor series expansion, this translates into solving
  950. the following the linear system:
  951. .. math::
  952. \\left\\{
  953. \\begin{array}{r}
  954. \\alpha+\\beta+\\gamma=0 \\\\
  955. \\beta h_{d}-\\gamma h_{s}=1 \\\\
  956. \\beta h_{d}^{2}+\\gamma h_{s}^{2}=0
  957. \\end{array}
  958. \\right.
  959. The resulting approximation of :math:`f_{i}^{(1)}` is the following:
  960. .. math::
  961. \\hat f_{i}^{(1)} =
  962. \\frac{
  963. h_{s}^{2}f\\left(x_{i} + h_{d}\\right)
  964. + \\left(h_{d}^{2} - h_{s}^{2}\\right)f\\left(x_{i}\\right)
  965. - h_{d}^{2}f\\left(x_{i}-h_{s}\\right)}
  966. { h_{s}h_{d}\\left(h_{d} + h_{s}\\right)}
  967. + \\mathcal{O}\\left(\\frac{h_{d}h_{s}^{2}
  968. + h_{s}h_{d}^{2}}{h_{d}
  969. + h_{s}}\\right)
  970. It is worth noting that if :math:`h_{s}=h_{d}`
  971. (i.e., data are evenly spaced)
  972. we find the standard second order approximation:
  973. .. math::
  974. \\hat f_{i}^{(1)}=
  975. \\frac{f\\left(x_{i+1}\\right) - f\\left(x_{i-1}\\right)}{2h}
  976. + \\mathcal{O}\\left(h^{2}\\right)
  977. With a similar procedure the forward/backward approximations used for
  978. boundaries can be derived.
  979. References
  980. ----------
  981. .. [1] Quarteroni A., Sacco R., Saleri F. (2007) Numerical Mathematics
  982. (Texts in Applied Mathematics). New York: Springer.
  983. .. [2] Durran D. R. (1999) Numerical Methods for Wave Equations
  984. in Geophysical Fluid Dynamics. New York: Springer.
  985. .. [3] Fornberg B. (1988) Generation of Finite Difference Formulas on
  986. Arbitrarily Spaced Grids,
  987. Mathematics of Computation 51, no. 184 : 699-706.
  988. `PDF <https://www.ams.org/journals/mcom/1988-51-184/
  989. S0025-5718-1988-0935077-0/S0025-5718-1988-0935077-0.pdf>`_.
  990. """
  991. f = np.asanyarray(f)
  992. N = f.ndim # number of dimensions
  993. if axis is None:
  994. axes = tuple(range(N))
  995. else:
  996. axes = _nx.normalize_axis_tuple(axis, N)
  997. len_axes = len(axes)
  998. n = len(varargs)
  999. if n == 0:
  1000. # no spacing argument - use 1 in all axes
  1001. dx = [1.0] * len_axes
  1002. elif n == 1 and np.ndim(varargs[0]) == 0:
  1003. # single scalar for all axes
  1004. dx = varargs * len_axes
  1005. elif n == len_axes:
  1006. # scalar or 1d array for each axis
  1007. dx = list(varargs)
  1008. for i, distances in enumerate(dx):
  1009. distances = np.asanyarray(distances)
  1010. if distances.ndim == 0:
  1011. continue
  1012. elif distances.ndim != 1:
  1013. raise ValueError("distances must be either scalars or 1d")
  1014. if len(distances) != f.shape[axes[i]]:
  1015. raise ValueError("when 1d, distances must match "
  1016. "the length of the corresponding dimension")
  1017. if np.issubdtype(distances.dtype, np.integer):
  1018. # Convert numpy integer types to float64 to avoid modular
  1019. # arithmetic in np.diff(distances).
  1020. distances = distances.astype(np.float64)
  1021. diffx = np.diff(distances)
  1022. # if distances are constant reduce to the scalar case
  1023. # since it brings a consistent speedup
  1024. if (diffx == diffx[0]).all():
  1025. diffx = diffx[0]
  1026. dx[i] = diffx
  1027. else:
  1028. raise TypeError("invalid number of arguments")
  1029. if edge_order > 2:
  1030. raise ValueError("'edge_order' greater than 2 not supported")
  1031. # use central differences on interior and one-sided differences on the
  1032. # endpoints. This preserves second order-accuracy over the full domain.
  1033. outvals = []
  1034. # create slice objects --- initially all are [:, :, ..., :]
  1035. slice1 = [slice(None)]*N
  1036. slice2 = [slice(None)]*N
  1037. slice3 = [slice(None)]*N
  1038. slice4 = [slice(None)]*N
  1039. otype = f.dtype
  1040. if otype.type is np.datetime64:
  1041. # the timedelta dtype with the same unit information
  1042. otype = np.dtype(otype.name.replace('datetime', 'timedelta'))
  1043. # view as timedelta to allow addition
  1044. f = f.view(otype)
  1045. elif otype.type is np.timedelta64:
  1046. pass
  1047. elif np.issubdtype(otype, np.inexact):
  1048. pass
  1049. else:
  1050. # All other types convert to floating point.
  1051. # First check if f is a numpy integer type; if so, convert f to float64
  1052. # to avoid modular arithmetic when computing the changes in f.
  1053. if np.issubdtype(otype, np.integer):
  1054. f = f.astype(np.float64)
  1055. otype = np.float64
  1056. for axis, ax_dx in zip(axes, dx):
  1057. if f.shape[axis] < edge_order + 1:
  1058. raise ValueError(
  1059. "Shape of array too small to calculate a numerical gradient, "
  1060. "at least (edge_order + 1) elements are required.")
  1061. # result allocation
  1062. out = np.empty_like(f, dtype=otype)
  1063. # spacing for the current axis
  1064. uniform_spacing = np.ndim(ax_dx) == 0
  1065. # Numerical differentiation: 2nd order interior
  1066. slice1[axis] = slice(1, -1)
  1067. slice2[axis] = slice(None, -2)
  1068. slice3[axis] = slice(1, -1)
  1069. slice4[axis] = slice(2, None)
  1070. if uniform_spacing:
  1071. out[tuple(slice1)] = (f[tuple(slice4)] - f[tuple(slice2)]) / (2. * ax_dx)
  1072. else:
  1073. dx1 = ax_dx[0:-1]
  1074. dx2 = ax_dx[1:]
  1075. a = -(dx2)/(dx1 * (dx1 + dx2))
  1076. b = (dx2 - dx1) / (dx1 * dx2)
  1077. c = dx1 / (dx2 * (dx1 + dx2))
  1078. # fix the shape for broadcasting
  1079. shape = np.ones(N, dtype=int)
  1080. shape[axis] = -1
  1081. a.shape = b.shape = c.shape = shape
  1082. # 1D equivalent -- out[1:-1] = a * f[:-2] + b * f[1:-1] + c * f[2:]
  1083. out[tuple(slice1)] = a * f[tuple(slice2)] + b * f[tuple(slice3)] + c * f[tuple(slice4)]
  1084. # Numerical differentiation: 1st order edges
  1085. if edge_order == 1:
  1086. slice1[axis] = 0
  1087. slice2[axis] = 1
  1088. slice3[axis] = 0
  1089. dx_0 = ax_dx if uniform_spacing else ax_dx[0]
  1090. # 1D equivalent -- out[0] = (f[1] - f[0]) / (x[1] - x[0])
  1091. out[tuple(slice1)] = (f[tuple(slice2)] - f[tuple(slice3)]) / dx_0
  1092. slice1[axis] = -1
  1093. slice2[axis] = -1
  1094. slice3[axis] = -2
  1095. dx_n = ax_dx if uniform_spacing else ax_dx[-1]
  1096. # 1D equivalent -- out[-1] = (f[-1] - f[-2]) / (x[-1] - x[-2])
  1097. out[tuple(slice1)] = (f[tuple(slice2)] - f[tuple(slice3)]) / dx_n
  1098. # Numerical differentiation: 2nd order edges
  1099. else:
  1100. slice1[axis] = 0
  1101. slice2[axis] = 0
  1102. slice3[axis] = 1
  1103. slice4[axis] = 2
  1104. if uniform_spacing:
  1105. a = -1.5 / ax_dx
  1106. b = 2. / ax_dx
  1107. c = -0.5 / ax_dx
  1108. else:
  1109. dx1 = ax_dx[0]
  1110. dx2 = ax_dx[1]
  1111. a = -(2. * dx1 + dx2)/(dx1 * (dx1 + dx2))
  1112. b = (dx1 + dx2) / (dx1 * dx2)
  1113. c = - dx1 / (dx2 * (dx1 + dx2))
  1114. # 1D equivalent -- out[0] = a * f[0] + b * f[1] + c * f[2]
  1115. out[tuple(slice1)] = a * f[tuple(slice2)] + b * f[tuple(slice3)] + c * f[tuple(slice4)]
  1116. slice1[axis] = -1
  1117. slice2[axis] = -3
  1118. slice3[axis] = -2
  1119. slice4[axis] = -1
  1120. if uniform_spacing:
  1121. a = 0.5 / ax_dx
  1122. b = -2. / ax_dx
  1123. c = 1.5 / ax_dx
  1124. else:
  1125. dx1 = ax_dx[-2]
  1126. dx2 = ax_dx[-1]
  1127. a = (dx2) / (dx1 * (dx1 + dx2))
  1128. b = - (dx2 + dx1) / (dx1 * dx2)
  1129. c = (2. * dx2 + dx1) / (dx2 * (dx1 + dx2))
  1130. # 1D equivalent -- out[-1] = a * f[-3] + b * f[-2] + c * f[-1]
  1131. out[tuple(slice1)] = a * f[tuple(slice2)] + b * f[tuple(slice3)] + c * f[tuple(slice4)]
  1132. outvals.append(out)
  1133. # reset the slice object in this dimension to ":"
  1134. slice1[axis] = slice(None)
  1135. slice2[axis] = slice(None)
  1136. slice3[axis] = slice(None)
  1137. slice4[axis] = slice(None)
  1138. if len_axes == 1:
  1139. return outvals[0]
  1140. return tuple(outvals)
  1141. def _diff_dispatcher(a, n=None, axis=None, prepend=None, append=None):
  1142. return (a, prepend, append)
  1143. @array_function_dispatch(_diff_dispatcher)
  1144. def diff(a, n=1, axis=-1, prepend=np._NoValue, append=np._NoValue):
  1145. """
  1146. Calculate the n-th discrete difference along the given axis.
  1147. The first difference is given by ``out[i] = a[i+1] - a[i]`` along
  1148. the given axis, higher differences are calculated by using `diff`
  1149. recursively.
  1150. Parameters
  1151. ----------
  1152. a : array_like
  1153. Input array
  1154. n : int, optional
  1155. The number of times values are differenced. If zero, the input
  1156. is returned as-is.
  1157. axis : int, optional
  1158. The axis along which the difference is taken, default is the
  1159. last axis.
  1160. prepend, append : array_like, optional
  1161. Values to prepend or append to `a` along axis prior to
  1162. performing the difference. Scalar values are expanded to
  1163. arrays with length 1 in the direction of axis and the shape
  1164. of the input array in along all other axes. Otherwise the
  1165. dimension and shape must match `a` except along axis.
  1166. Returns
  1167. -------
  1168. diff : ndarray
  1169. The n-th differences. The shape of the output is the same as `a`
  1170. except along `axis` where the dimension is smaller by `n`. The
  1171. type of the output is the same as the type of the difference
  1172. between any two elements of `a`. This is the same as the type of
  1173. `a` in most cases. A notable exception is `datetime64`, which
  1174. results in a `timedelta64` output array.
  1175. See Also
  1176. --------
  1177. gradient, ediff1d, cumsum
  1178. Notes
  1179. -----
  1180. Type is preserved for boolean arrays, so the result will contain
  1181. `False` when consecutive elements are the same and `True` when they
  1182. differ.
  1183. For unsigned integer arrays, the results will also be unsigned. This
  1184. should not be surprising, as the result is consistent with
  1185. calculating the difference directly:
  1186. >>> u8_arr = np.array([1, 0], dtype=np.uint8)
  1187. >>> np.diff(u8_arr)
  1188. array([255], dtype=uint8)
  1189. >>> u8_arr[1,...] - u8_arr[0,...]
  1190. np.uint8(255)
  1191. If this is not desirable, then the array should be cast to a larger
  1192. integer type first:
  1193. >>> i16_arr = u8_arr.astype(np.int16)
  1194. >>> np.diff(i16_arr)
  1195. array([-1], dtype=int16)
  1196. Examples
  1197. --------
  1198. >>> import numpy as np
  1199. >>> x = np.array([1, 2, 4, 7, 0])
  1200. >>> np.diff(x)
  1201. array([ 1, 2, 3, -7])
  1202. >>> np.diff(x, n=2)
  1203. array([ 1, 1, -10])
  1204. >>> x = np.array([[1, 3, 6, 10], [0, 5, 6, 8]])
  1205. >>> np.diff(x)
  1206. array([[2, 3, 4],
  1207. [5, 1, 2]])
  1208. >>> np.diff(x, axis=0)
  1209. array([[-1, 2, 0, -2]])
  1210. >>> x = np.arange('1066-10-13', '1066-10-16', dtype=np.datetime64)
  1211. >>> np.diff(x)
  1212. array([1, 1], dtype='timedelta64[D]')
  1213. """
  1214. if n == 0:
  1215. return a
  1216. if n < 0:
  1217. raise ValueError(
  1218. "order must be non-negative but got " + repr(n))
  1219. a = asanyarray(a)
  1220. nd = a.ndim
  1221. if nd == 0:
  1222. raise ValueError("diff requires input that is at least one dimensional")
  1223. axis = normalize_axis_index(axis, nd)
  1224. combined = []
  1225. if prepend is not np._NoValue:
  1226. prepend = np.asanyarray(prepend)
  1227. if prepend.ndim == 0:
  1228. shape = list(a.shape)
  1229. shape[axis] = 1
  1230. prepend = np.broadcast_to(prepend, tuple(shape))
  1231. combined.append(prepend)
  1232. combined.append(a)
  1233. if append is not np._NoValue:
  1234. append = np.asanyarray(append)
  1235. if append.ndim == 0:
  1236. shape = list(a.shape)
  1237. shape[axis] = 1
  1238. append = np.broadcast_to(append, tuple(shape))
  1239. combined.append(append)
  1240. if len(combined) > 1:
  1241. a = np.concatenate(combined, axis)
  1242. slice1 = [slice(None)] * nd
  1243. slice2 = [slice(None)] * nd
  1244. slice1[axis] = slice(1, None)
  1245. slice2[axis] = slice(None, -1)
  1246. slice1 = tuple(slice1)
  1247. slice2 = tuple(slice2)
  1248. op = not_equal if a.dtype == np.bool else subtract
  1249. for _ in range(n):
  1250. a = op(a[slice1], a[slice2])
  1251. return a
  1252. def _interp_dispatcher(x, xp, fp, left=None, right=None, period=None):
  1253. return (x, xp, fp)
  1254. @array_function_dispatch(_interp_dispatcher)
  1255. def interp(x, xp, fp, left=None, right=None, period=None):
  1256. """
  1257. One-dimensional linear interpolation for monotonically increasing sample points.
  1258. Returns the one-dimensional piecewise linear interpolant to a function
  1259. with given discrete data points (`xp`, `fp`), evaluated at `x`.
  1260. Parameters
  1261. ----------
  1262. x : array_like
  1263. The x-coordinates at which to evaluate the interpolated values.
  1264. xp : 1-D sequence of floats
  1265. The x-coordinates of the data points, must be increasing if argument
  1266. `period` is not specified. Otherwise, `xp` is internally sorted after
  1267. normalizing the periodic boundaries with ``xp = xp % period``.
  1268. fp : 1-D sequence of float or complex
  1269. The y-coordinates of the data points, same length as `xp`.
  1270. left : optional float or complex corresponding to fp
  1271. Value to return for `x < xp[0]`, default is `fp[0]`.
  1272. right : optional float or complex corresponding to fp
  1273. Value to return for `x > xp[-1]`, default is `fp[-1]`.
  1274. period : None or float, optional
  1275. A period for the x-coordinates. This parameter allows the proper
  1276. interpolation of angular x-coordinates. Parameters `left` and `right`
  1277. are ignored if `period` is specified.
  1278. Returns
  1279. -------
  1280. y : float or complex (corresponding to fp) or ndarray
  1281. The interpolated values, same shape as `x`.
  1282. Raises
  1283. ------
  1284. ValueError
  1285. If `xp` and `fp` have different length
  1286. If `xp` or `fp` are not 1-D sequences
  1287. If `period == 0`
  1288. See Also
  1289. --------
  1290. scipy.interpolate
  1291. Warnings
  1292. --------
  1293. The x-coordinate sequence is expected to be increasing, but this is not
  1294. explicitly enforced. However, if the sequence `xp` is non-increasing,
  1295. interpolation results are meaningless.
  1296. Note that, since NaN is unsortable, `xp` also cannot contain NaNs.
  1297. A simple check for `xp` being strictly increasing is::
  1298. np.all(np.diff(xp) > 0)
  1299. Examples
  1300. --------
  1301. >>> import numpy as np
  1302. >>> xp = [1, 2, 3]
  1303. >>> fp = [3, 2, 0]
  1304. >>> np.interp(2.5, xp, fp)
  1305. 1.0
  1306. >>> np.interp([0, 1, 1.5, 2.72, 3.14], xp, fp)
  1307. array([3. , 3. , 2.5 , 0.56, 0. ])
  1308. >>> UNDEF = -99.0
  1309. >>> np.interp(3.14, xp, fp, right=UNDEF)
  1310. -99.0
  1311. Plot an interpolant to the sine function:
  1312. >>> x = np.linspace(0, 2*np.pi, 10)
  1313. >>> y = np.sin(x)
  1314. >>> xvals = np.linspace(0, 2*np.pi, 50)
  1315. >>> yinterp = np.interp(xvals, x, y)
  1316. >>> import matplotlib.pyplot as plt
  1317. >>> plt.plot(x, y, 'o')
  1318. [<matplotlib.lines.Line2D object at 0x...>]
  1319. >>> plt.plot(xvals, yinterp, '-x')
  1320. [<matplotlib.lines.Line2D object at 0x...>]
  1321. >>> plt.show()
  1322. Interpolation with periodic x-coordinates:
  1323. >>> x = [-180, -170, -185, 185, -10, -5, 0, 365]
  1324. >>> xp = [190, -190, 350, -350]
  1325. >>> fp = [5, 10, 3, 4]
  1326. >>> np.interp(x, xp, fp, period=360)
  1327. array([7.5 , 5. , 8.75, 6.25, 3. , 3.25, 3.5 , 3.75])
  1328. Complex interpolation:
  1329. >>> x = [1.5, 4.0]
  1330. >>> xp = [2,3,5]
  1331. >>> fp = [1.0j, 0, 2+3j]
  1332. >>> np.interp(x, xp, fp)
  1333. array([0.+1.j , 1.+1.5j])
  1334. """
  1335. fp = np.asarray(fp)
  1336. if np.iscomplexobj(fp):
  1337. interp_func = compiled_interp_complex
  1338. input_dtype = np.complex128
  1339. else:
  1340. interp_func = compiled_interp
  1341. input_dtype = np.float64
  1342. if period is not None:
  1343. if period == 0:
  1344. raise ValueError("period must be a non-zero value")
  1345. period = abs(period)
  1346. left = None
  1347. right = None
  1348. x = np.asarray(x, dtype=np.float64)
  1349. xp = np.asarray(xp, dtype=np.float64)
  1350. fp = np.asarray(fp, dtype=input_dtype)
  1351. if xp.ndim != 1 or fp.ndim != 1:
  1352. raise ValueError("Data points must be 1-D sequences")
  1353. if xp.shape[0] != fp.shape[0]:
  1354. raise ValueError("fp and xp are not of the same length")
  1355. # normalizing periodic boundaries
  1356. x = x % period
  1357. xp = xp % period
  1358. asort_xp = np.argsort(xp)
  1359. xp = xp[asort_xp]
  1360. fp = fp[asort_xp]
  1361. xp = np.concatenate((xp[-1:]-period, xp, xp[0:1]+period))
  1362. fp = np.concatenate((fp[-1:], fp, fp[0:1]))
  1363. return interp_func(x, xp, fp, left, right)
  1364. def _angle_dispatcher(z, deg=None):
  1365. return (z,)
  1366. @array_function_dispatch(_angle_dispatcher)
  1367. def angle(z, deg=False):
  1368. """
  1369. Return the angle of the complex argument.
  1370. Parameters
  1371. ----------
  1372. z : array_like
  1373. A complex number or sequence of complex numbers.
  1374. deg : bool, optional
  1375. Return angle in degrees if True, radians if False (default).
  1376. Returns
  1377. -------
  1378. angle : ndarray or scalar
  1379. The counterclockwise angle from the positive real axis on the complex
  1380. plane in the range ``(-pi, pi]``, with dtype as numpy.float64.
  1381. See Also
  1382. --------
  1383. arctan2
  1384. absolute
  1385. Notes
  1386. -----
  1387. This function passes the imaginary and real parts of the argument to
  1388. `arctan2` to compute the result; consequently, it follows the convention
  1389. of `arctan2` when the magnitude of the argument is zero. See example.
  1390. Examples
  1391. --------
  1392. >>> import numpy as np
  1393. >>> np.angle([1.0, 1.0j, 1+1j]) # in radians
  1394. array([ 0. , 1.57079633, 0.78539816]) # may vary
  1395. >>> np.angle(1+1j, deg=True) # in degrees
  1396. 45.0
  1397. >>> np.angle([0., -0., complex(0., -0.), complex(-0., -0.)]) # convention
  1398. array([ 0. , 3.14159265, -0. , -3.14159265])
  1399. """
  1400. z = asanyarray(z)
  1401. if issubclass(z.dtype.type, _nx.complexfloating):
  1402. zimag = z.imag
  1403. zreal = z.real
  1404. else:
  1405. zimag = 0
  1406. zreal = z
  1407. a = arctan2(zimag, zreal)
  1408. if deg:
  1409. a *= 180/pi
  1410. return a
  1411. def _unwrap_dispatcher(p, discont=None, axis=None, *, period=None):
  1412. return (p,)
  1413. @array_function_dispatch(_unwrap_dispatcher)
  1414. def unwrap(p, discont=None, axis=-1, *, period=2*pi):
  1415. r"""
  1416. Unwrap by taking the complement of large deltas with respect to the period.
  1417. This unwraps a signal `p` by changing elements which have an absolute
  1418. difference from their predecessor of more than ``max(discont, period/2)``
  1419. to their `period`-complementary values.
  1420. For the default case where `period` is :math:`2\pi` and `discont` is
  1421. :math:`\pi`, this unwraps a radian phase `p` such that adjacent differences
  1422. are never greater than :math:`\pi` by adding :math:`2k\pi` for some
  1423. integer :math:`k`.
  1424. Parameters
  1425. ----------
  1426. p : array_like
  1427. Input array.
  1428. discont : float, optional
  1429. Maximum discontinuity between values, default is ``period/2``.
  1430. Values below ``period/2`` are treated as if they were ``period/2``.
  1431. To have an effect different from the default, `discont` should be
  1432. larger than ``period/2``.
  1433. axis : int, optional
  1434. Axis along which unwrap will operate, default is the last axis.
  1435. period : float, optional
  1436. Size of the range over which the input wraps. By default, it is
  1437. ``2 pi``.
  1438. .. versionadded:: 1.21.0
  1439. Returns
  1440. -------
  1441. out : ndarray
  1442. Output array.
  1443. See Also
  1444. --------
  1445. rad2deg, deg2rad
  1446. Notes
  1447. -----
  1448. If the discontinuity in `p` is smaller than ``period/2``,
  1449. but larger than `discont`, no unwrapping is done because taking
  1450. the complement would only make the discontinuity larger.
  1451. Examples
  1452. --------
  1453. >>> import numpy as np
  1454. >>> phase = np.linspace(0, np.pi, num=5)
  1455. >>> phase[3:] += np.pi
  1456. >>> phase
  1457. array([ 0. , 0.78539816, 1.57079633, 5.49778714, 6.28318531]) # may vary
  1458. >>> np.unwrap(phase)
  1459. array([ 0. , 0.78539816, 1.57079633, -0.78539816, 0. ]) # may vary
  1460. >>> np.unwrap([0, 1, 2, -1, 0], period=4)
  1461. array([0, 1, 2, 3, 4])
  1462. >>> np.unwrap([ 1, 2, 3, 4, 5, 6, 1, 2, 3], period=6)
  1463. array([1, 2, 3, 4, 5, 6, 7, 8, 9])
  1464. >>> np.unwrap([2, 3, 4, 5, 2, 3, 4, 5], period=4)
  1465. array([2, 3, 4, 5, 6, 7, 8, 9])
  1466. >>> phase_deg = np.mod(np.linspace(0 ,720, 19), 360) - 180
  1467. >>> np.unwrap(phase_deg, period=360)
  1468. array([-180., -140., -100., -60., -20., 20., 60., 100., 140.,
  1469. 180., 220., 260., 300., 340., 380., 420., 460., 500.,
  1470. 540.])
  1471. """
  1472. p = asarray(p)
  1473. nd = p.ndim
  1474. dd = diff(p, axis=axis)
  1475. if discont is None:
  1476. discont = period/2
  1477. slice1 = [slice(None, None)]*nd # full slices
  1478. slice1[axis] = slice(1, None)
  1479. slice1 = tuple(slice1)
  1480. dtype = np.result_type(dd, period)
  1481. if _nx.issubdtype(dtype, _nx.integer):
  1482. interval_high, rem = divmod(period, 2)
  1483. boundary_ambiguous = rem == 0
  1484. else:
  1485. interval_high = period / 2
  1486. boundary_ambiguous = True
  1487. interval_low = -interval_high
  1488. ddmod = mod(dd - interval_low, period) + interval_low
  1489. if boundary_ambiguous:
  1490. # for `mask = (abs(dd) == period/2)`, the above line made
  1491. # `ddmod[mask] == -period/2`. correct these such that
  1492. # `ddmod[mask] == sign(dd[mask])*period/2`.
  1493. _nx.copyto(ddmod, interval_high,
  1494. where=(ddmod == interval_low) & (dd > 0))
  1495. ph_correct = ddmod - dd
  1496. _nx.copyto(ph_correct, 0, where=abs(dd) < discont)
  1497. up = array(p, copy=True, dtype=dtype)
  1498. up[slice1] = p[slice1] + ph_correct.cumsum(axis)
  1499. return up
  1500. def _sort_complex(a):
  1501. return (a,)
  1502. @array_function_dispatch(_sort_complex)
  1503. def sort_complex(a):
  1504. """
  1505. Sort a complex array using the real part first, then the imaginary part.
  1506. Parameters
  1507. ----------
  1508. a : array_like
  1509. Input array
  1510. Returns
  1511. -------
  1512. out : complex ndarray
  1513. Always returns a sorted complex array.
  1514. Examples
  1515. --------
  1516. >>> import numpy as np
  1517. >>> np.sort_complex([5, 3, 6, 2, 1])
  1518. array([1.+0.j, 2.+0.j, 3.+0.j, 5.+0.j, 6.+0.j])
  1519. >>> np.sort_complex([1 + 2j, 2 - 1j, 3 - 2j, 3 - 3j, 3 + 5j])
  1520. array([1.+2.j, 2.-1.j, 3.-3.j, 3.-2.j, 3.+5.j])
  1521. """
  1522. b = array(a, copy=True)
  1523. b.sort()
  1524. if not issubclass(b.dtype.type, _nx.complexfloating):
  1525. if b.dtype.char in 'bhBH':
  1526. return b.astype('F')
  1527. elif b.dtype.char == 'g':
  1528. return b.astype('G')
  1529. else:
  1530. return b.astype('D')
  1531. else:
  1532. return b
  1533. def _arg_trim_zeros(filt):
  1534. """Return indices of the first and last non-zero element.
  1535. Parameters
  1536. ----------
  1537. filt : array_like
  1538. Input array.
  1539. Returns
  1540. -------
  1541. start, stop : ndarray
  1542. Two arrays containing the indices of the first and last non-zero
  1543. element in each dimension.
  1544. See also
  1545. --------
  1546. trim_zeros
  1547. Examples
  1548. --------
  1549. >>> import numpy as np
  1550. >>> _arg_trim_zeros(np.array([0, 0, 1, 1, 0]))
  1551. (array([2]), array([3]))
  1552. """
  1553. nonzero = (
  1554. np.argwhere(filt)
  1555. if filt.dtype != np.object_
  1556. # Historically, `trim_zeros` treats `None` in an object array
  1557. # as non-zero while argwhere doesn't, account for that
  1558. else np.argwhere(filt != 0)
  1559. )
  1560. if nonzero.size == 0:
  1561. start = stop = np.array([], dtype=np.intp)
  1562. else:
  1563. start = nonzero.min(axis=0)
  1564. stop = nonzero.max(axis=0)
  1565. return start, stop
  1566. def _trim_zeros(filt, trim=None, axis=None):
  1567. return (filt,)
  1568. @array_function_dispatch(_trim_zeros)
  1569. def trim_zeros(filt, trim='fb', axis=None):
  1570. """Remove values along a dimension which are zero along all other.
  1571. Parameters
  1572. ----------
  1573. filt : array_like
  1574. Input array.
  1575. trim : {"fb", "f", "b"}, optional
  1576. A string with 'f' representing trim from front and 'b' to trim from
  1577. back. By default, zeros are trimmed on both sides.
  1578. Front and back refer to the edges of a dimension, with "front" refering
  1579. to the side with the lowest index 0, and "back" refering to the highest
  1580. index (or index -1).
  1581. axis : int or sequence, optional
  1582. If None, `filt` is cropped such, that the smallest bounding box is
  1583. returned that still contains all values which are not zero.
  1584. If an axis is specified, `filt` will be sliced in that dimension only
  1585. on the sides specified by `trim`. The remaining area will be the
  1586. smallest that still contains all values wich are not zero.
  1587. Returns
  1588. -------
  1589. trimmed : ndarray or sequence
  1590. The result of trimming the input. The number of dimensions and the
  1591. input data type are preserved.
  1592. Notes
  1593. -----
  1594. For all-zero arrays, the first axis is trimmed first.
  1595. Examples
  1596. --------
  1597. >>> import numpy as np
  1598. >>> a = np.array((0, 0, 0, 1, 2, 3, 0, 2, 1, 0))
  1599. >>> np.trim_zeros(a)
  1600. array([1, 2, 3, 0, 2, 1])
  1601. >>> np.trim_zeros(a, trim='b')
  1602. array([0, 0, 0, ..., 0, 2, 1])
  1603. Multiple dimensions are supported.
  1604. >>> b = np.array([[0, 0, 2, 3, 0, 0],
  1605. ... [0, 1, 0, 3, 0, 0],
  1606. ... [0, 0, 0, 0, 0, 0]])
  1607. >>> np.trim_zeros(b)
  1608. array([[0, 2, 3],
  1609. [1, 0, 3]])
  1610. >>> np.trim_zeros(b, axis=-1)
  1611. array([[0, 2, 3],
  1612. [1, 0, 3],
  1613. [0, 0, 0]])
  1614. The input data type is preserved, list/tuple in means list/tuple out.
  1615. >>> np.trim_zeros([0, 1, 2, 0])
  1616. [1, 2]
  1617. """
  1618. filt_ = np.asarray(filt)
  1619. trim = trim.lower()
  1620. if trim not in {"fb", "bf", "f", "b"}:
  1621. raise ValueError(f"unexpected character(s) in `trim`: {trim!r}")
  1622. start, stop = _arg_trim_zeros(filt_)
  1623. stop += 1 # Adjust for slicing
  1624. if start.size == 0:
  1625. # filt is all-zero -> assign same values to start and stop so that
  1626. # resulting slice will be empty
  1627. start = stop = np.zeros(filt_.ndim, dtype=np.intp)
  1628. else:
  1629. if 'f' not in trim:
  1630. start = (None,) * filt_.ndim
  1631. if 'b' not in trim:
  1632. stop = (None,) * filt_.ndim
  1633. if len(start) == 1:
  1634. # filt is 1D -> don't use multi-dimensional slicing to preserve
  1635. # non-array input types
  1636. sl = slice(start[0], stop[0])
  1637. elif axis is None:
  1638. # trim all axes
  1639. sl = tuple(slice(*x) for x in zip(start, stop))
  1640. else:
  1641. # only trim single axis
  1642. axis = normalize_axis_index(axis, filt_.ndim)
  1643. sl = (slice(None),) * axis + (slice(start[axis], stop[axis]),) + (...,)
  1644. trimmed = filt[sl]
  1645. return trimmed
  1646. def _extract_dispatcher(condition, arr):
  1647. return (condition, arr)
  1648. @array_function_dispatch(_extract_dispatcher)
  1649. def extract(condition, arr):
  1650. """
  1651. Return the elements of an array that satisfy some condition.
  1652. This is equivalent to ``np.compress(ravel(condition), ravel(arr))``. If
  1653. `condition` is boolean ``np.extract`` is equivalent to ``arr[condition]``.
  1654. Note that `place` does the exact opposite of `extract`.
  1655. Parameters
  1656. ----------
  1657. condition : array_like
  1658. An array whose nonzero or True entries indicate the elements of `arr`
  1659. to extract.
  1660. arr : array_like
  1661. Input array of the same size as `condition`.
  1662. Returns
  1663. -------
  1664. extract : ndarray
  1665. Rank 1 array of values from `arr` where `condition` is True.
  1666. See Also
  1667. --------
  1668. take, put, copyto, compress, place
  1669. Examples
  1670. --------
  1671. >>> import numpy as np
  1672. >>> arr = np.arange(12).reshape((3, 4))
  1673. >>> arr
  1674. array([[ 0, 1, 2, 3],
  1675. [ 4, 5, 6, 7],
  1676. [ 8, 9, 10, 11]])
  1677. >>> condition = np.mod(arr, 3)==0
  1678. >>> condition
  1679. array([[ True, False, False, True],
  1680. [False, False, True, False],
  1681. [False, True, False, False]])
  1682. >>> np.extract(condition, arr)
  1683. array([0, 3, 6, 9])
  1684. If `condition` is boolean:
  1685. >>> arr[condition]
  1686. array([0, 3, 6, 9])
  1687. """
  1688. return _nx.take(ravel(arr), nonzero(ravel(condition))[0])
  1689. def _place_dispatcher(arr, mask, vals):
  1690. return (arr, mask, vals)
  1691. @array_function_dispatch(_place_dispatcher)
  1692. def place(arr, mask, vals):
  1693. """
  1694. Change elements of an array based on conditional and input values.
  1695. Similar to ``np.copyto(arr, vals, where=mask)``, the difference is that
  1696. `place` uses the first N elements of `vals`, where N is the number of
  1697. True values in `mask`, while `copyto` uses the elements where `mask`
  1698. is True.
  1699. Note that `extract` does the exact opposite of `place`.
  1700. Parameters
  1701. ----------
  1702. arr : ndarray
  1703. Array to put data into.
  1704. mask : array_like
  1705. Boolean mask array. Must have the same size as `a`.
  1706. vals : 1-D sequence
  1707. Values to put into `a`. Only the first N elements are used, where
  1708. N is the number of True values in `mask`. If `vals` is smaller
  1709. than N, it will be repeated, and if elements of `a` are to be masked,
  1710. this sequence must be non-empty.
  1711. See Also
  1712. --------
  1713. copyto, put, take, extract
  1714. Examples
  1715. --------
  1716. >>> import numpy as np
  1717. >>> arr = np.arange(6).reshape(2, 3)
  1718. >>> np.place(arr, arr>2, [44, 55])
  1719. >>> arr
  1720. array([[ 0, 1, 2],
  1721. [44, 55, 44]])
  1722. """
  1723. return _place(arr, mask, vals)
  1724. def disp(mesg, device=None, linefeed=True):
  1725. """
  1726. Display a message on a device.
  1727. .. deprecated:: 2.0
  1728. Use your own printing function instead.
  1729. Parameters
  1730. ----------
  1731. mesg : str
  1732. Message to display.
  1733. device : object
  1734. Device to write message. If None, defaults to ``sys.stdout`` which is
  1735. very similar to ``print``. `device` needs to have ``write()`` and
  1736. ``flush()`` methods.
  1737. linefeed : bool, optional
  1738. Option whether to print a line feed or not. Defaults to True.
  1739. Raises
  1740. ------
  1741. AttributeError
  1742. If `device` does not have a ``write()`` or ``flush()`` method.
  1743. Examples
  1744. --------
  1745. >>> import numpy as np
  1746. Besides ``sys.stdout``, a file-like object can also be used as it has
  1747. both required methods:
  1748. >>> from io import StringIO
  1749. >>> buf = StringIO()
  1750. >>> np.disp('"Display" in a file', device=buf)
  1751. >>> buf.getvalue()
  1752. '"Display" in a file\\n'
  1753. """
  1754. # Deprecated in NumPy 2.0, 2023-07-11
  1755. warnings.warn(
  1756. "`disp` is deprecated, "
  1757. "use your own printing function instead. "
  1758. "(deprecated in NumPy 2.0)",
  1759. DeprecationWarning,
  1760. stacklevel=2
  1761. )
  1762. if device is None:
  1763. device = sys.stdout
  1764. if linefeed:
  1765. device.write('%s\n' % mesg)
  1766. else:
  1767. device.write('%s' % mesg)
  1768. device.flush()
  1769. return
  1770. # See https://docs.scipy.org/doc/numpy/reference/c-api.generalized-ufuncs.html
  1771. _DIMENSION_NAME = r'\w+'
  1772. _CORE_DIMENSION_LIST = '(?:{0:}(?:,{0:})*)?'.format(_DIMENSION_NAME)
  1773. _ARGUMENT = r'\({}\)'.format(_CORE_DIMENSION_LIST)
  1774. _ARGUMENT_LIST = '{0:}(?:,{0:})*'.format(_ARGUMENT)
  1775. _SIGNATURE = '^{0:}->{0:}$'.format(_ARGUMENT_LIST)
  1776. def _parse_gufunc_signature(signature):
  1777. """
  1778. Parse string signatures for a generalized universal function.
  1779. Arguments
  1780. ---------
  1781. signature : string
  1782. Generalized universal function signature, e.g., ``(m,n),(n,p)->(m,p)``
  1783. for ``np.matmul``.
  1784. Returns
  1785. -------
  1786. Tuple of input and output core dimensions parsed from the signature, each
  1787. of the form List[Tuple[str, ...]].
  1788. """
  1789. signature = re.sub(r'\s+', '', signature)
  1790. if not re.match(_SIGNATURE, signature):
  1791. raise ValueError(
  1792. 'not a valid gufunc signature: {}'.format(signature))
  1793. return tuple([tuple(re.findall(_DIMENSION_NAME, arg))
  1794. for arg in re.findall(_ARGUMENT, arg_list)]
  1795. for arg_list in signature.split('->'))
  1796. def _update_dim_sizes(dim_sizes, arg, core_dims):
  1797. """
  1798. Incrementally check and update core dimension sizes for a single argument.
  1799. Arguments
  1800. ---------
  1801. dim_sizes : Dict[str, int]
  1802. Sizes of existing core dimensions. Will be updated in-place.
  1803. arg : ndarray
  1804. Argument to examine.
  1805. core_dims : Tuple[str, ...]
  1806. Core dimensions for this argument.
  1807. """
  1808. if not core_dims:
  1809. return
  1810. num_core_dims = len(core_dims)
  1811. if arg.ndim < num_core_dims:
  1812. raise ValueError(
  1813. '%d-dimensional argument does not have enough '
  1814. 'dimensions for all core dimensions %r'
  1815. % (arg.ndim, core_dims))
  1816. core_shape = arg.shape[-num_core_dims:]
  1817. for dim, size in zip(core_dims, core_shape):
  1818. if dim in dim_sizes:
  1819. if size != dim_sizes[dim]:
  1820. raise ValueError(
  1821. 'inconsistent size for core dimension %r: %r vs %r'
  1822. % (dim, size, dim_sizes[dim]))
  1823. else:
  1824. dim_sizes[dim] = size
  1825. def _parse_input_dimensions(args, input_core_dims):
  1826. """
  1827. Parse broadcast and core dimensions for vectorize with a signature.
  1828. Arguments
  1829. ---------
  1830. args : Tuple[ndarray, ...]
  1831. Tuple of input arguments to examine.
  1832. input_core_dims : List[Tuple[str, ...]]
  1833. List of core dimensions corresponding to each input.
  1834. Returns
  1835. -------
  1836. broadcast_shape : Tuple[int, ...]
  1837. Common shape to broadcast all non-core dimensions to.
  1838. dim_sizes : Dict[str, int]
  1839. Common sizes for named core dimensions.
  1840. """
  1841. broadcast_args = []
  1842. dim_sizes = {}
  1843. for arg, core_dims in zip(args, input_core_dims):
  1844. _update_dim_sizes(dim_sizes, arg, core_dims)
  1845. ndim = arg.ndim - len(core_dims)
  1846. dummy_array = np.lib.stride_tricks.as_strided(0, arg.shape[:ndim])
  1847. broadcast_args.append(dummy_array)
  1848. broadcast_shape = np.lib._stride_tricks_impl._broadcast_shape(
  1849. *broadcast_args
  1850. )
  1851. return broadcast_shape, dim_sizes
  1852. def _calculate_shapes(broadcast_shape, dim_sizes, list_of_core_dims):
  1853. """Helper for calculating broadcast shapes with core dimensions."""
  1854. return [broadcast_shape + tuple(dim_sizes[dim] for dim in core_dims)
  1855. for core_dims in list_of_core_dims]
  1856. def _create_arrays(broadcast_shape, dim_sizes, list_of_core_dims, dtypes,
  1857. results=None):
  1858. """Helper for creating output arrays in vectorize."""
  1859. shapes = _calculate_shapes(broadcast_shape, dim_sizes, list_of_core_dims)
  1860. if dtypes is None:
  1861. dtypes = [None] * len(shapes)
  1862. if results is None:
  1863. arrays = tuple(np.empty(shape=shape, dtype=dtype)
  1864. for shape, dtype in zip(shapes, dtypes))
  1865. else:
  1866. arrays = tuple(np.empty_like(result, shape=shape, dtype=dtype)
  1867. for result, shape, dtype
  1868. in zip(results, shapes, dtypes))
  1869. return arrays
  1870. def _get_vectorize_dtype(dtype):
  1871. if dtype.char in "SU":
  1872. return dtype.char
  1873. return dtype
  1874. @set_module('numpy')
  1875. class vectorize:
  1876. """
  1877. vectorize(pyfunc=np._NoValue, otypes=None, doc=None, excluded=None,
  1878. cache=False, signature=None)
  1879. Returns an object that acts like pyfunc, but takes arrays as input.
  1880. Define a vectorized function which takes a nested sequence of objects or
  1881. numpy arrays as inputs and returns a single numpy array or a tuple of numpy
  1882. arrays. The vectorized function evaluates `pyfunc` over successive tuples
  1883. of the input arrays like the python map function, except it uses the
  1884. broadcasting rules of numpy.
  1885. The data type of the output of `vectorized` is determined by calling
  1886. the function with the first element of the input. This can be avoided
  1887. by specifying the `otypes` argument.
  1888. Parameters
  1889. ----------
  1890. pyfunc : callable, optional
  1891. A python function or method.
  1892. Can be omitted to produce a decorator with keyword arguments.
  1893. otypes : str or list of dtypes, optional
  1894. The output data type. It must be specified as either a string of
  1895. typecode characters or a list of data type specifiers. There should
  1896. be one data type specifier for each output.
  1897. doc : str, optional
  1898. The docstring for the function. If None, the docstring will be the
  1899. ``pyfunc.__doc__``.
  1900. excluded : set, optional
  1901. Set of strings or integers representing the positional or keyword
  1902. arguments for which the function will not be vectorized. These will be
  1903. passed directly to `pyfunc` unmodified.
  1904. cache : bool, optional
  1905. If `True`, then cache the first function call that determines the number
  1906. of outputs if `otypes` is not provided.
  1907. signature : string, optional
  1908. Generalized universal function signature, e.g., ``(m,n),(n)->(m)`` for
  1909. vectorized matrix-vector multiplication. If provided, ``pyfunc`` will
  1910. be called with (and expected to return) arrays with shapes given by the
  1911. size of corresponding core dimensions. By default, ``pyfunc`` is
  1912. assumed to take scalars as input and output.
  1913. Returns
  1914. -------
  1915. out : callable
  1916. A vectorized function if ``pyfunc`` was provided,
  1917. a decorator otherwise.
  1918. See Also
  1919. --------
  1920. frompyfunc : Takes an arbitrary Python function and returns a ufunc
  1921. Notes
  1922. -----
  1923. The `vectorize` function is provided primarily for convenience, not for
  1924. performance. The implementation is essentially a for loop.
  1925. If `otypes` is not specified, then a call to the function with the
  1926. first argument will be used to determine the number of outputs. The
  1927. results of this call will be cached if `cache` is `True` to prevent
  1928. calling the function twice. However, to implement the cache, the
  1929. original function must be wrapped which will slow down subsequent
  1930. calls, so only do this if your function is expensive.
  1931. The new keyword argument interface and `excluded` argument support
  1932. further degrades performance.
  1933. References
  1934. ----------
  1935. .. [1] :doc:`/reference/c-api/generalized-ufuncs`
  1936. Examples
  1937. --------
  1938. >>> import numpy as np
  1939. >>> def myfunc(a, b):
  1940. ... "Return a-b if a>b, otherwise return a+b"
  1941. ... if a > b:
  1942. ... return a - b
  1943. ... else:
  1944. ... return a + b
  1945. >>> vfunc = np.vectorize(myfunc)
  1946. >>> vfunc([1, 2, 3, 4], 2)
  1947. array([3, 4, 1, 2])
  1948. The docstring is taken from the input function to `vectorize` unless it
  1949. is specified:
  1950. >>> vfunc.__doc__
  1951. 'Return a-b if a>b, otherwise return a+b'
  1952. >>> vfunc = np.vectorize(myfunc, doc='Vectorized `myfunc`')
  1953. >>> vfunc.__doc__
  1954. 'Vectorized `myfunc`'
  1955. The output type is determined by evaluating the first element of the input,
  1956. unless it is specified:
  1957. >>> out = vfunc([1, 2, 3, 4], 2)
  1958. >>> type(out[0])
  1959. <class 'numpy.int64'>
  1960. >>> vfunc = np.vectorize(myfunc, otypes=[float])
  1961. >>> out = vfunc([1, 2, 3, 4], 2)
  1962. >>> type(out[0])
  1963. <class 'numpy.float64'>
  1964. The `excluded` argument can be used to prevent vectorizing over certain
  1965. arguments. This can be useful for array-like arguments of a fixed length
  1966. such as the coefficients for a polynomial as in `polyval`:
  1967. >>> def mypolyval(p, x):
  1968. ... _p = list(p)
  1969. ... res = _p.pop(0)
  1970. ... while _p:
  1971. ... res = res*x + _p.pop(0)
  1972. ... return res
  1973. Here, we exclude the zeroth argument from vectorization whether it is
  1974. passed by position or keyword.
  1975. >>> vpolyval = np.vectorize(mypolyval, excluded={0, 'p'})
  1976. >>> vpolyval([1, 2, 3], x=[0, 1])
  1977. array([3, 6])
  1978. >>> vpolyval(p=[1, 2, 3], x=[0, 1])
  1979. array([3, 6])
  1980. The `signature` argument allows for vectorizing functions that act on
  1981. non-scalar arrays of fixed length. For example, you can use it for a
  1982. vectorized calculation of Pearson correlation coefficient and its p-value:
  1983. >>> import scipy.stats
  1984. >>> pearsonr = np.vectorize(scipy.stats.pearsonr,
  1985. ... signature='(n),(n)->(),()')
  1986. >>> pearsonr([[0, 1, 2, 3]], [[1, 2, 3, 4], [4, 3, 2, 1]])
  1987. (array([ 1., -1.]), array([ 0., 0.]))
  1988. Or for a vectorized convolution:
  1989. >>> convolve = np.vectorize(np.convolve, signature='(n),(m)->(k)')
  1990. >>> convolve(np.eye(4), [1, 2, 1])
  1991. array([[1., 2., 1., 0., 0., 0.],
  1992. [0., 1., 2., 1., 0., 0.],
  1993. [0., 0., 1., 2., 1., 0.],
  1994. [0., 0., 0., 1., 2., 1.]])
  1995. Decorator syntax is supported. The decorator can be called as
  1996. a function to provide keyword arguments:
  1997. >>> @np.vectorize
  1998. ... def identity(x):
  1999. ... return x
  2000. ...
  2001. >>> identity([0, 1, 2])
  2002. array([0, 1, 2])
  2003. >>> @np.vectorize(otypes=[float])
  2004. ... def as_float(x):
  2005. ... return x
  2006. ...
  2007. >>> as_float([0, 1, 2])
  2008. array([0., 1., 2.])
  2009. """
  2010. def __init__(self, pyfunc=np._NoValue, otypes=None, doc=None,
  2011. excluded=None, cache=False, signature=None):
  2012. if (pyfunc != np._NoValue) and (not callable(pyfunc)):
  2013. #Splitting the error message to keep
  2014. #the length below 79 characters.
  2015. part1 = "When used as a decorator, "
  2016. part2 = "only accepts keyword arguments."
  2017. raise TypeError(part1 + part2)
  2018. self.pyfunc = pyfunc
  2019. self.cache = cache
  2020. self.signature = signature
  2021. if pyfunc != np._NoValue and hasattr(pyfunc, '__name__'):
  2022. self.__name__ = pyfunc.__name__
  2023. self._ufunc = {} # Caching to improve default performance
  2024. self._doc = None
  2025. self.__doc__ = doc
  2026. if doc is None and hasattr(pyfunc, '__doc__'):
  2027. self.__doc__ = pyfunc.__doc__
  2028. else:
  2029. self._doc = doc
  2030. if isinstance(otypes, str):
  2031. for char in otypes:
  2032. if char not in typecodes['All']:
  2033. raise ValueError("Invalid otype specified: %s" % (char,))
  2034. elif iterable(otypes):
  2035. otypes = [_get_vectorize_dtype(_nx.dtype(x)) for x in otypes]
  2036. elif otypes is not None:
  2037. raise ValueError("Invalid otype specification")
  2038. self.otypes = otypes
  2039. # Excluded variable support
  2040. if excluded is None:
  2041. excluded = set()
  2042. self.excluded = set(excluded)
  2043. if signature is not None:
  2044. self._in_and_out_core_dims = _parse_gufunc_signature(signature)
  2045. else:
  2046. self._in_and_out_core_dims = None
  2047. def _init_stage_2(self, pyfunc, *args, **kwargs):
  2048. self.__name__ = pyfunc.__name__
  2049. self.pyfunc = pyfunc
  2050. if self._doc is None:
  2051. self.__doc__ = pyfunc.__doc__
  2052. else:
  2053. self.__doc__ = self._doc
  2054. def _call_as_normal(self, *args, **kwargs):
  2055. """
  2056. Return arrays with the results of `pyfunc` broadcast (vectorized) over
  2057. `args` and `kwargs` not in `excluded`.
  2058. """
  2059. excluded = self.excluded
  2060. if not kwargs and not excluded:
  2061. func = self.pyfunc
  2062. vargs = args
  2063. else:
  2064. # The wrapper accepts only positional arguments: we use `names` and
  2065. # `inds` to mutate `the_args` and `kwargs` to pass to the original
  2066. # function.
  2067. nargs = len(args)
  2068. names = [_n for _n in kwargs if _n not in excluded]
  2069. inds = [_i for _i in range(nargs) if _i not in excluded]
  2070. the_args = list(args)
  2071. def func(*vargs):
  2072. for _n, _i in enumerate(inds):
  2073. the_args[_i] = vargs[_n]
  2074. kwargs.update(zip(names, vargs[len(inds):]))
  2075. return self.pyfunc(*the_args, **kwargs)
  2076. vargs = [args[_i] for _i in inds]
  2077. vargs.extend([kwargs[_n] for _n in names])
  2078. return self._vectorize_call(func=func, args=vargs)
  2079. def __call__(self, *args, **kwargs):
  2080. if self.pyfunc is np._NoValue:
  2081. self._init_stage_2(*args, **kwargs)
  2082. return self
  2083. return self._call_as_normal(*args, **kwargs)
  2084. def _get_ufunc_and_otypes(self, func, args):
  2085. """Return (ufunc, otypes)."""
  2086. # frompyfunc will fail if args is empty
  2087. if not args:
  2088. raise ValueError('args can not be empty')
  2089. if self.otypes is not None:
  2090. otypes = self.otypes
  2091. # self._ufunc is a dictionary whose keys are the number of
  2092. # arguments (i.e. len(args)) and whose values are ufuncs created
  2093. # by frompyfunc. len(args) can be different for different calls if
  2094. # self.pyfunc has parameters with default values. We only use the
  2095. # cache when func is self.pyfunc, which occurs when the call uses
  2096. # only positional arguments and no arguments are excluded.
  2097. nin = len(args)
  2098. nout = len(self.otypes)
  2099. if func is not self.pyfunc or nin not in self._ufunc:
  2100. ufunc = frompyfunc(func, nin, nout)
  2101. else:
  2102. ufunc = None # We'll get it from self._ufunc
  2103. if func is self.pyfunc:
  2104. ufunc = self._ufunc.setdefault(nin, ufunc)
  2105. else:
  2106. # Get number of outputs and output types by calling the function on
  2107. # the first entries of args. We also cache the result to prevent
  2108. # the subsequent call when the ufunc is evaluated.
  2109. # Assumes that ufunc first evaluates the 0th elements in the input
  2110. # arrays (the input values are not checked to ensure this)
  2111. args = [asarray(arg) for arg in args]
  2112. if builtins.any(arg.size == 0 for arg in args):
  2113. raise ValueError('cannot call `vectorize` on size 0 inputs '
  2114. 'unless `otypes` is set')
  2115. inputs = [arg.flat[0] for arg in args]
  2116. outputs = func(*inputs)
  2117. # Performance note: profiling indicates that -- for simple
  2118. # functions at least -- this wrapping can almost double the
  2119. # execution time.
  2120. # Hence we make it optional.
  2121. if self.cache:
  2122. _cache = [outputs]
  2123. def _func(*vargs):
  2124. if _cache:
  2125. return _cache.pop()
  2126. else:
  2127. return func(*vargs)
  2128. else:
  2129. _func = func
  2130. if isinstance(outputs, tuple):
  2131. nout = len(outputs)
  2132. else:
  2133. nout = 1
  2134. outputs = (outputs,)
  2135. otypes = ''.join([asarray(outputs[_k]).dtype.char
  2136. for _k in range(nout)])
  2137. # Performance note: profiling indicates that creating the ufunc is
  2138. # not a significant cost compared with wrapping so it seems not
  2139. # worth trying to cache this.
  2140. ufunc = frompyfunc(_func, len(args), nout)
  2141. return ufunc, otypes
  2142. def _vectorize_call(self, func, args):
  2143. """Vectorized call to `func` over positional `args`."""
  2144. if self.signature is not None:
  2145. res = self._vectorize_call_with_signature(func, args)
  2146. elif not args:
  2147. res = func()
  2148. else:
  2149. ufunc, otypes = self._get_ufunc_and_otypes(func=func, args=args)
  2150. # Convert args to object arrays first
  2151. inputs = [asanyarray(a, dtype=object) for a in args]
  2152. outputs = ufunc(*inputs)
  2153. if ufunc.nout == 1:
  2154. res = asanyarray(outputs, dtype=otypes[0])
  2155. else:
  2156. res = tuple([asanyarray(x, dtype=t)
  2157. for x, t in zip(outputs, otypes)])
  2158. return res
  2159. def _vectorize_call_with_signature(self, func, args):
  2160. """Vectorized call over positional arguments with a signature."""
  2161. input_core_dims, output_core_dims = self._in_and_out_core_dims
  2162. if len(args) != len(input_core_dims):
  2163. raise TypeError('wrong number of positional arguments: '
  2164. 'expected %r, got %r'
  2165. % (len(input_core_dims), len(args)))
  2166. args = tuple(asanyarray(arg) for arg in args)
  2167. broadcast_shape, dim_sizes = _parse_input_dimensions(
  2168. args, input_core_dims)
  2169. input_shapes = _calculate_shapes(broadcast_shape, dim_sizes,
  2170. input_core_dims)
  2171. args = [np.broadcast_to(arg, shape, subok=True)
  2172. for arg, shape in zip(args, input_shapes)]
  2173. outputs = None
  2174. otypes = self.otypes
  2175. nout = len(output_core_dims)
  2176. for index in np.ndindex(*broadcast_shape):
  2177. results = func(*(arg[index] for arg in args))
  2178. n_results = len(results) if isinstance(results, tuple) else 1
  2179. if nout != n_results:
  2180. raise ValueError(
  2181. 'wrong number of outputs from pyfunc: expected %r, got %r'
  2182. % (nout, n_results))
  2183. if nout == 1:
  2184. results = (results,)
  2185. if outputs is None:
  2186. for result, core_dims in zip(results, output_core_dims):
  2187. _update_dim_sizes(dim_sizes, result, core_dims)
  2188. outputs = _create_arrays(broadcast_shape, dim_sizes,
  2189. output_core_dims, otypes, results)
  2190. for output, result in zip(outputs, results):
  2191. output[index] = result
  2192. if outputs is None:
  2193. # did not call the function even once
  2194. if otypes is None:
  2195. raise ValueError('cannot call `vectorize` on size 0 inputs '
  2196. 'unless `otypes` is set')
  2197. if builtins.any(dim not in dim_sizes
  2198. for dims in output_core_dims
  2199. for dim in dims):
  2200. raise ValueError('cannot call `vectorize` with a signature '
  2201. 'including new output dimensions on size 0 '
  2202. 'inputs')
  2203. outputs = _create_arrays(broadcast_shape, dim_sizes,
  2204. output_core_dims, otypes)
  2205. return outputs[0] if nout == 1 else outputs
  2206. def _cov_dispatcher(m, y=None, rowvar=None, bias=None, ddof=None,
  2207. fweights=None, aweights=None, *, dtype=None):
  2208. return (m, y, fweights, aweights)
  2209. @array_function_dispatch(_cov_dispatcher)
  2210. def cov(m, y=None, rowvar=True, bias=False, ddof=None, fweights=None,
  2211. aweights=None, *, dtype=None):
  2212. """
  2213. Estimate a covariance matrix, given data and weights.
  2214. Covariance indicates the level to which two variables vary together.
  2215. If we examine N-dimensional samples, :math:`X = [x_1, x_2, ... x_N]^T`,
  2216. then the covariance matrix element :math:`C_{ij}` is the covariance of
  2217. :math:`x_i` and :math:`x_j`. The element :math:`C_{ii}` is the variance
  2218. of :math:`x_i`.
  2219. See the notes for an outline of the algorithm.
  2220. Parameters
  2221. ----------
  2222. m : array_like
  2223. A 1-D or 2-D array containing multiple variables and observations.
  2224. Each row of `m` represents a variable, and each column a single
  2225. observation of all those variables. Also see `rowvar` below.
  2226. y : array_like, optional
  2227. An additional set of variables and observations. `y` has the same form
  2228. as that of `m`.
  2229. rowvar : bool, optional
  2230. If `rowvar` is True (default), then each row represents a
  2231. variable, with observations in the columns. Otherwise, the relationship
  2232. is transposed: each column represents a variable, while the rows
  2233. contain observations.
  2234. bias : bool, optional
  2235. Default normalization (False) is by ``(N - 1)``, where ``N`` is the
  2236. number of observations given (unbiased estimate). If `bias` is True,
  2237. then normalization is by ``N``. These values can be overridden by using
  2238. the keyword ``ddof`` in numpy versions >= 1.5.
  2239. ddof : int, optional
  2240. If not ``None`` the default value implied by `bias` is overridden.
  2241. Note that ``ddof=1`` will return the unbiased estimate, even if both
  2242. `fweights` and `aweights` are specified, and ``ddof=0`` will return
  2243. the simple average. See the notes for the details. The default value
  2244. is ``None``.
  2245. fweights : array_like, int, optional
  2246. 1-D array of integer frequency weights; the number of times each
  2247. observation vector should be repeated.
  2248. aweights : array_like, optional
  2249. 1-D array of observation vector weights. These relative weights are
  2250. typically large for observations considered "important" and smaller for
  2251. observations considered less "important". If ``ddof=0`` the array of
  2252. weights can be used to assign probabilities to observation vectors.
  2253. dtype : data-type, optional
  2254. Data-type of the result. By default, the return data-type will have
  2255. at least `numpy.float64` precision.
  2256. .. versionadded:: 1.20
  2257. Returns
  2258. -------
  2259. out : ndarray
  2260. The covariance matrix of the variables.
  2261. See Also
  2262. --------
  2263. corrcoef : Normalized covariance matrix
  2264. Notes
  2265. -----
  2266. Assume that the observations are in the columns of the observation
  2267. array `m` and let ``f = fweights`` and ``a = aweights`` for brevity. The
  2268. steps to compute the weighted covariance are as follows::
  2269. >>> m = np.arange(10, dtype=np.float64)
  2270. >>> f = np.arange(10) * 2
  2271. >>> a = np.arange(10) ** 2.
  2272. >>> ddof = 1
  2273. >>> w = f * a
  2274. >>> v1 = np.sum(w)
  2275. >>> v2 = np.sum(w * a)
  2276. >>> m -= np.sum(m * w, axis=None, keepdims=True) / v1
  2277. >>> cov = np.dot(m * w, m.T) * v1 / (v1**2 - ddof * v2)
  2278. Note that when ``a == 1``, the normalization factor
  2279. ``v1 / (v1**2 - ddof * v2)`` goes over to ``1 / (np.sum(f) - ddof)``
  2280. as it should.
  2281. Examples
  2282. --------
  2283. >>> import numpy as np
  2284. Consider two variables, :math:`x_0` and :math:`x_1`, which
  2285. correlate perfectly, but in opposite directions:
  2286. >>> x = np.array([[0, 2], [1, 1], [2, 0]]).T
  2287. >>> x
  2288. array([[0, 1, 2],
  2289. [2, 1, 0]])
  2290. Note how :math:`x_0` increases while :math:`x_1` decreases. The covariance
  2291. matrix shows this clearly:
  2292. >>> np.cov(x)
  2293. array([[ 1., -1.],
  2294. [-1., 1.]])
  2295. Note that element :math:`C_{0,1}`, which shows the correlation between
  2296. :math:`x_0` and :math:`x_1`, is negative.
  2297. Further, note how `x` and `y` are combined:
  2298. >>> x = [-2.1, -1, 4.3]
  2299. >>> y = [3, 1.1, 0.12]
  2300. >>> X = np.stack((x, y), axis=0)
  2301. >>> np.cov(X)
  2302. array([[11.71 , -4.286 ], # may vary
  2303. [-4.286 , 2.144133]])
  2304. >>> np.cov(x, y)
  2305. array([[11.71 , -4.286 ], # may vary
  2306. [-4.286 , 2.144133]])
  2307. >>> np.cov(x)
  2308. array(11.71)
  2309. """
  2310. # Check inputs
  2311. if ddof is not None and ddof != int(ddof):
  2312. raise ValueError(
  2313. "ddof must be integer")
  2314. # Handles complex arrays too
  2315. m = np.asarray(m)
  2316. if m.ndim > 2:
  2317. raise ValueError("m has more than 2 dimensions")
  2318. if y is not None:
  2319. y = np.asarray(y)
  2320. if y.ndim > 2:
  2321. raise ValueError("y has more than 2 dimensions")
  2322. if dtype is None:
  2323. if y is None:
  2324. dtype = np.result_type(m, np.float64)
  2325. else:
  2326. dtype = np.result_type(m, y, np.float64)
  2327. X = array(m, ndmin=2, dtype=dtype)
  2328. if not rowvar and m.ndim != 1:
  2329. X = X.T
  2330. if X.shape[0] == 0:
  2331. return np.array([]).reshape(0, 0)
  2332. if y is not None:
  2333. y = array(y, copy=None, ndmin=2, dtype=dtype)
  2334. if not rowvar and y.shape[0] != 1:
  2335. y = y.T
  2336. X = np.concatenate((X, y), axis=0)
  2337. if ddof is None:
  2338. if bias == 0:
  2339. ddof = 1
  2340. else:
  2341. ddof = 0
  2342. # Get the product of frequencies and weights
  2343. w = None
  2344. if fweights is not None:
  2345. fweights = np.asarray(fweights, dtype=float)
  2346. if not np.all(fweights == np.around(fweights)):
  2347. raise TypeError(
  2348. "fweights must be integer")
  2349. if fweights.ndim > 1:
  2350. raise RuntimeError(
  2351. "cannot handle multidimensional fweights")
  2352. if fweights.shape[0] != X.shape[1]:
  2353. raise RuntimeError(
  2354. "incompatible numbers of samples and fweights")
  2355. if any(fweights < 0):
  2356. raise ValueError(
  2357. "fweights cannot be negative")
  2358. w = fweights
  2359. if aweights is not None:
  2360. aweights = np.asarray(aweights, dtype=float)
  2361. if aweights.ndim > 1:
  2362. raise RuntimeError(
  2363. "cannot handle multidimensional aweights")
  2364. if aweights.shape[0] != X.shape[1]:
  2365. raise RuntimeError(
  2366. "incompatible numbers of samples and aweights")
  2367. if any(aweights < 0):
  2368. raise ValueError(
  2369. "aweights cannot be negative")
  2370. if w is None:
  2371. w = aweights
  2372. else:
  2373. w *= aweights
  2374. avg, w_sum = average(X, axis=1, weights=w, returned=True)
  2375. w_sum = w_sum[0]
  2376. # Determine the normalization
  2377. if w is None:
  2378. fact = X.shape[1] - ddof
  2379. elif ddof == 0:
  2380. fact = w_sum
  2381. elif aweights is None:
  2382. fact = w_sum - ddof
  2383. else:
  2384. fact = w_sum - ddof*sum(w*aweights)/w_sum
  2385. if fact <= 0:
  2386. warnings.warn("Degrees of freedom <= 0 for slice",
  2387. RuntimeWarning, stacklevel=2)
  2388. fact = 0.0
  2389. X -= avg[:, None]
  2390. if w is None:
  2391. X_T = X.T
  2392. else:
  2393. X_T = (X*w).T
  2394. c = dot(X, X_T.conj())
  2395. c *= np.true_divide(1, fact)
  2396. return c.squeeze()
  2397. def _corrcoef_dispatcher(x, y=None, rowvar=None, bias=None, ddof=None, *,
  2398. dtype=None):
  2399. return (x, y)
  2400. @array_function_dispatch(_corrcoef_dispatcher)
  2401. def corrcoef(x, y=None, rowvar=True, bias=np._NoValue, ddof=np._NoValue, *,
  2402. dtype=None):
  2403. """
  2404. Return Pearson product-moment correlation coefficients.
  2405. Please refer to the documentation for `cov` for more detail. The
  2406. relationship between the correlation coefficient matrix, `R`, and the
  2407. covariance matrix, `C`, is
  2408. .. math:: R_{ij} = \\frac{ C_{ij} } { \\sqrt{ C_{ii} C_{jj} } }
  2409. The values of `R` are between -1 and 1, inclusive.
  2410. Parameters
  2411. ----------
  2412. x : array_like
  2413. A 1-D or 2-D array containing multiple variables and observations.
  2414. Each row of `x` represents a variable, and each column a single
  2415. observation of all those variables. Also see `rowvar` below.
  2416. y : array_like, optional
  2417. An additional set of variables and observations. `y` has the same
  2418. shape as `x`.
  2419. rowvar : bool, optional
  2420. If `rowvar` is True (default), then each row represents a
  2421. variable, with observations in the columns. Otherwise, the relationship
  2422. is transposed: each column represents a variable, while the rows
  2423. contain observations.
  2424. bias : _NoValue, optional
  2425. Has no effect, do not use.
  2426. .. deprecated:: 1.10.0
  2427. ddof : _NoValue, optional
  2428. Has no effect, do not use.
  2429. .. deprecated:: 1.10.0
  2430. dtype : data-type, optional
  2431. Data-type of the result. By default, the return data-type will have
  2432. at least `numpy.float64` precision.
  2433. .. versionadded:: 1.20
  2434. Returns
  2435. -------
  2436. R : ndarray
  2437. The correlation coefficient matrix of the variables.
  2438. See Also
  2439. --------
  2440. cov : Covariance matrix
  2441. Notes
  2442. -----
  2443. Due to floating point rounding the resulting array may not be Hermitian,
  2444. the diagonal elements may not be 1, and the elements may not satisfy the
  2445. inequality abs(a) <= 1. The real and imaginary parts are clipped to the
  2446. interval [-1, 1] in an attempt to improve on that situation but is not
  2447. much help in the complex case.
  2448. This function accepts but discards arguments `bias` and `ddof`. This is
  2449. for backwards compatibility with previous versions of this function. These
  2450. arguments had no effect on the return values of the function and can be
  2451. safely ignored in this and previous versions of numpy.
  2452. Examples
  2453. --------
  2454. >>> import numpy as np
  2455. In this example we generate two random arrays, ``xarr`` and ``yarr``, and
  2456. compute the row-wise and column-wise Pearson correlation coefficients,
  2457. ``R``. Since ``rowvar`` is true by default, we first find the row-wise
  2458. Pearson correlation coefficients between the variables of ``xarr``.
  2459. >>> import numpy as np
  2460. >>> rng = np.random.default_rng(seed=42)
  2461. >>> xarr = rng.random((3, 3))
  2462. >>> xarr
  2463. array([[0.77395605, 0.43887844, 0.85859792],
  2464. [0.69736803, 0.09417735, 0.97562235],
  2465. [0.7611397 , 0.78606431, 0.12811363]])
  2466. >>> R1 = np.corrcoef(xarr)
  2467. >>> R1
  2468. array([[ 1. , 0.99256089, -0.68080986],
  2469. [ 0.99256089, 1. , -0.76492172],
  2470. [-0.68080986, -0.76492172, 1. ]])
  2471. If we add another set of variables and observations ``yarr``, we can
  2472. compute the row-wise Pearson correlation coefficients between the
  2473. variables in ``xarr`` and ``yarr``.
  2474. >>> yarr = rng.random((3, 3))
  2475. >>> yarr
  2476. array([[0.45038594, 0.37079802, 0.92676499],
  2477. [0.64386512, 0.82276161, 0.4434142 ],
  2478. [0.22723872, 0.55458479, 0.06381726]])
  2479. >>> R2 = np.corrcoef(xarr, yarr)
  2480. >>> R2
  2481. array([[ 1. , 0.99256089, -0.68080986, 0.75008178, -0.934284 ,
  2482. -0.99004057],
  2483. [ 0.99256089, 1. , -0.76492172, 0.82502011, -0.97074098,
  2484. -0.99981569],
  2485. [-0.68080986, -0.76492172, 1. , -0.99507202, 0.89721355,
  2486. 0.77714685],
  2487. [ 0.75008178, 0.82502011, -0.99507202, 1. , -0.93657855,
  2488. -0.83571711],
  2489. [-0.934284 , -0.97074098, 0.89721355, -0.93657855, 1. ,
  2490. 0.97517215],
  2491. [-0.99004057, -0.99981569, 0.77714685, -0.83571711, 0.97517215,
  2492. 1. ]])
  2493. Finally if we use the option ``rowvar=False``, the columns are now
  2494. being treated as the variables and we will find the column-wise Pearson
  2495. correlation coefficients between variables in ``xarr`` and ``yarr``.
  2496. >>> R3 = np.corrcoef(xarr, yarr, rowvar=False)
  2497. >>> R3
  2498. array([[ 1. , 0.77598074, -0.47458546, -0.75078643, -0.9665554 ,
  2499. 0.22423734],
  2500. [ 0.77598074, 1. , -0.92346708, -0.99923895, -0.58826587,
  2501. -0.44069024],
  2502. [-0.47458546, -0.92346708, 1. , 0.93773029, 0.23297648,
  2503. 0.75137473],
  2504. [-0.75078643, -0.99923895, 0.93773029, 1. , 0.55627469,
  2505. 0.47536961],
  2506. [-0.9665554 , -0.58826587, 0.23297648, 0.55627469, 1. ,
  2507. -0.46666491],
  2508. [ 0.22423734, -0.44069024, 0.75137473, 0.47536961, -0.46666491,
  2509. 1. ]])
  2510. """
  2511. if bias is not np._NoValue or ddof is not np._NoValue:
  2512. # 2015-03-15, 1.10
  2513. warnings.warn('bias and ddof have no effect and are deprecated',
  2514. DeprecationWarning, stacklevel=2)
  2515. c = cov(x, y, rowvar, dtype=dtype)
  2516. try:
  2517. d = diag(c)
  2518. except ValueError:
  2519. # scalar covariance
  2520. # nan if incorrect value (nan, inf, 0), 1 otherwise
  2521. return c / c
  2522. stddev = sqrt(d.real)
  2523. c /= stddev[:, None]
  2524. c /= stddev[None, :]
  2525. # Clip real and imaginary parts to [-1, 1]. This does not guarantee
  2526. # abs(a[i,j]) <= 1 for complex arrays, but is the best we can do without
  2527. # excessive work.
  2528. np.clip(c.real, -1, 1, out=c.real)
  2529. if np.iscomplexobj(c):
  2530. np.clip(c.imag, -1, 1, out=c.imag)
  2531. return c
  2532. @set_module('numpy')
  2533. def blackman(M):
  2534. """
  2535. Return the Blackman window.
  2536. The Blackman window is a taper formed by using the first three
  2537. terms of a summation of cosines. It was designed to have close to the
  2538. minimal leakage possible. It is close to optimal, only slightly worse
  2539. than a Kaiser window.
  2540. Parameters
  2541. ----------
  2542. M : int
  2543. Number of points in the output window. If zero or less, an empty
  2544. array is returned.
  2545. Returns
  2546. -------
  2547. out : ndarray
  2548. The window, with the maximum value normalized to one (the value one
  2549. appears only if the number of samples is odd).
  2550. See Also
  2551. --------
  2552. bartlett, hamming, hanning, kaiser
  2553. Notes
  2554. -----
  2555. The Blackman window is defined as
  2556. .. math:: w(n) = 0.42 - 0.5 \\cos(2\\pi n/M) + 0.08 \\cos(4\\pi n/M)
  2557. Most references to the Blackman window come from the signal processing
  2558. literature, where it is used as one of many windowing functions for
  2559. smoothing values. It is also known as an apodization (which means
  2560. "removing the foot", i.e. smoothing discontinuities at the beginning
  2561. and end of the sampled signal) or tapering function. It is known as a
  2562. "near optimal" tapering function, almost as good (by some measures)
  2563. as the kaiser window.
  2564. References
  2565. ----------
  2566. Blackman, R.B. and Tukey, J.W., (1958) The measurement of power spectra,
  2567. Dover Publications, New York.
  2568. Oppenheim, A.V., and R.W. Schafer. Discrete-Time Signal Processing.
  2569. Upper Saddle River, NJ: Prentice-Hall, 1999, pp. 468-471.
  2570. Examples
  2571. --------
  2572. >>> import numpy as np
  2573. >>> import matplotlib.pyplot as plt
  2574. >>> np.blackman(12)
  2575. array([-1.38777878e-17, 3.26064346e-02, 1.59903635e-01, # may vary
  2576. 4.14397981e-01, 7.36045180e-01, 9.67046769e-01,
  2577. 9.67046769e-01, 7.36045180e-01, 4.14397981e-01,
  2578. 1.59903635e-01, 3.26064346e-02, -1.38777878e-17])
  2579. Plot the window and the frequency response.
  2580. .. plot::
  2581. :include-source:
  2582. import matplotlib.pyplot as plt
  2583. from numpy.fft import fft, fftshift
  2584. window = np.blackman(51)
  2585. plt.plot(window)
  2586. plt.title("Blackman window")
  2587. plt.ylabel("Amplitude")
  2588. plt.xlabel("Sample")
  2589. plt.show() # doctest: +SKIP
  2590. plt.figure()
  2591. A = fft(window, 2048) / 25.5
  2592. mag = np.abs(fftshift(A))
  2593. freq = np.linspace(-0.5, 0.5, len(A))
  2594. with np.errstate(divide='ignore', invalid='ignore'):
  2595. response = 20 * np.log10(mag)
  2596. response = np.clip(response, -100, 100)
  2597. plt.plot(freq, response)
  2598. plt.title("Frequency response of Blackman window")
  2599. plt.ylabel("Magnitude [dB]")
  2600. plt.xlabel("Normalized frequency [cycles per sample]")
  2601. plt.axis('tight')
  2602. plt.show()
  2603. """
  2604. # Ensures at least float64 via 0.0. M should be an integer, but conversion
  2605. # to double is safe for a range.
  2606. values = np.array([0.0, M])
  2607. M = values[1]
  2608. if M < 1:
  2609. return array([], dtype=values.dtype)
  2610. if M == 1:
  2611. return ones(1, dtype=values.dtype)
  2612. n = arange(1-M, M, 2)
  2613. return 0.42 + 0.5*cos(pi*n/(M-1)) + 0.08*cos(2.0*pi*n/(M-1))
  2614. @set_module('numpy')
  2615. def bartlett(M):
  2616. """
  2617. Return the Bartlett window.
  2618. The Bartlett window is very similar to a triangular window, except
  2619. that the end points are at zero. It is often used in signal
  2620. processing for tapering a signal, without generating too much
  2621. ripple in the frequency domain.
  2622. Parameters
  2623. ----------
  2624. M : int
  2625. Number of points in the output window. If zero or less, an
  2626. empty array is returned.
  2627. Returns
  2628. -------
  2629. out : array
  2630. The triangular window, with the maximum value normalized to one
  2631. (the value one appears only if the number of samples is odd), with
  2632. the first and last samples equal to zero.
  2633. See Also
  2634. --------
  2635. blackman, hamming, hanning, kaiser
  2636. Notes
  2637. -----
  2638. The Bartlett window is defined as
  2639. .. math:: w(n) = \\frac{2}{M-1} \\left(
  2640. \\frac{M-1}{2} - \\left|n - \\frac{M-1}{2}\\right|
  2641. \\right)
  2642. Most references to the Bartlett window come from the signal processing
  2643. literature, where it is used as one of many windowing functions for
  2644. smoothing values. Note that convolution with this window produces linear
  2645. interpolation. It is also known as an apodization (which means "removing
  2646. the foot", i.e. smoothing discontinuities at the beginning and end of the
  2647. sampled signal) or tapering function. The Fourier transform of the
  2648. Bartlett window is the product of two sinc functions. Note the excellent
  2649. discussion in Kanasewich [2]_.
  2650. References
  2651. ----------
  2652. .. [1] M.S. Bartlett, "Periodogram Analysis and Continuous Spectra",
  2653. Biometrika 37, 1-16, 1950.
  2654. .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics",
  2655. The University of Alberta Press, 1975, pp. 109-110.
  2656. .. [3] A.V. Oppenheim and R.W. Schafer, "Discrete-Time Signal
  2657. Processing", Prentice-Hall, 1999, pp. 468-471.
  2658. .. [4] Wikipedia, "Window function",
  2659. https://en.wikipedia.org/wiki/Window_function
  2660. .. [5] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling,
  2661. "Numerical Recipes", Cambridge University Press, 1986, page 429.
  2662. Examples
  2663. --------
  2664. >>> import numpy as np
  2665. >>> import matplotlib.pyplot as plt
  2666. >>> np.bartlett(12)
  2667. array([ 0. , 0.18181818, 0.36363636, 0.54545455, 0.72727273, # may vary
  2668. 0.90909091, 0.90909091, 0.72727273, 0.54545455, 0.36363636,
  2669. 0.18181818, 0. ])
  2670. Plot the window and its frequency response (requires SciPy and matplotlib).
  2671. .. plot::
  2672. :include-source:
  2673. import matplotlib.pyplot as plt
  2674. from numpy.fft import fft, fftshift
  2675. window = np.bartlett(51)
  2676. plt.plot(window)
  2677. plt.title("Bartlett window")
  2678. plt.ylabel("Amplitude")
  2679. plt.xlabel("Sample")
  2680. plt.show()
  2681. plt.figure()
  2682. A = fft(window, 2048) / 25.5
  2683. mag = np.abs(fftshift(A))
  2684. freq = np.linspace(-0.5, 0.5, len(A))
  2685. with np.errstate(divide='ignore', invalid='ignore'):
  2686. response = 20 * np.log10(mag)
  2687. response = np.clip(response, -100, 100)
  2688. plt.plot(freq, response)
  2689. plt.title("Frequency response of Bartlett window")
  2690. plt.ylabel("Magnitude [dB]")
  2691. plt.xlabel("Normalized frequency [cycles per sample]")
  2692. plt.axis('tight')
  2693. plt.show()
  2694. """
  2695. # Ensures at least float64 via 0.0. M should be an integer, but conversion
  2696. # to double is safe for a range.
  2697. values = np.array([0.0, M])
  2698. M = values[1]
  2699. if M < 1:
  2700. return array([], dtype=values.dtype)
  2701. if M == 1:
  2702. return ones(1, dtype=values.dtype)
  2703. n = arange(1-M, M, 2)
  2704. return where(less_equal(n, 0), 1 + n/(M-1), 1 - n/(M-1))
  2705. @set_module('numpy')
  2706. def hanning(M):
  2707. """
  2708. Return the Hanning window.
  2709. The Hanning window is a taper formed by using a weighted cosine.
  2710. Parameters
  2711. ----------
  2712. M : int
  2713. Number of points in the output window. If zero or less, an
  2714. empty array is returned.
  2715. Returns
  2716. -------
  2717. out : ndarray, shape(M,)
  2718. The window, with the maximum value normalized to one (the value
  2719. one appears only if `M` is odd).
  2720. See Also
  2721. --------
  2722. bartlett, blackman, hamming, kaiser
  2723. Notes
  2724. -----
  2725. The Hanning window is defined as
  2726. .. math:: w(n) = 0.5 - 0.5\\cos\\left(\\frac{2\\pi{n}}{M-1}\\right)
  2727. \\qquad 0 \\leq n \\leq M-1
  2728. The Hanning was named for Julius von Hann, an Austrian meteorologist.
  2729. It is also known as the Cosine Bell. Some authors prefer that it be
  2730. called a Hann window, to help avoid confusion with the very similar
  2731. Hamming window.
  2732. Most references to the Hanning window come from the signal processing
  2733. literature, where it is used as one of many windowing functions for
  2734. smoothing values. It is also known as an apodization (which means
  2735. "removing the foot", i.e. smoothing discontinuities at the beginning
  2736. and end of the sampled signal) or tapering function.
  2737. References
  2738. ----------
  2739. .. [1] Blackman, R.B. and Tukey, J.W., (1958) The measurement of power
  2740. spectra, Dover Publications, New York.
  2741. .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics",
  2742. The University of Alberta Press, 1975, pp. 106-108.
  2743. .. [3] Wikipedia, "Window function",
  2744. https://en.wikipedia.org/wiki/Window_function
  2745. .. [4] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling,
  2746. "Numerical Recipes", Cambridge University Press, 1986, page 425.
  2747. Examples
  2748. --------
  2749. >>> import numpy as np
  2750. >>> np.hanning(12)
  2751. array([0. , 0.07937323, 0.29229249, 0.57115742, 0.82743037,
  2752. 0.97974649, 0.97974649, 0.82743037, 0.57115742, 0.29229249,
  2753. 0.07937323, 0. ])
  2754. Plot the window and its frequency response.
  2755. .. plot::
  2756. :include-source:
  2757. import matplotlib.pyplot as plt
  2758. from numpy.fft import fft, fftshift
  2759. window = np.hanning(51)
  2760. plt.plot(window)
  2761. plt.title("Hann window")
  2762. plt.ylabel("Amplitude")
  2763. plt.xlabel("Sample")
  2764. plt.show()
  2765. plt.figure()
  2766. A = fft(window, 2048) / 25.5
  2767. mag = np.abs(fftshift(A))
  2768. freq = np.linspace(-0.5, 0.5, len(A))
  2769. with np.errstate(divide='ignore', invalid='ignore'):
  2770. response = 20 * np.log10(mag)
  2771. response = np.clip(response, -100, 100)
  2772. plt.plot(freq, response)
  2773. plt.title("Frequency response of the Hann window")
  2774. plt.ylabel("Magnitude [dB]")
  2775. plt.xlabel("Normalized frequency [cycles per sample]")
  2776. plt.axis('tight')
  2777. plt.show()
  2778. """
  2779. # Ensures at least float64 via 0.0. M should be an integer, but conversion
  2780. # to double is safe for a range.
  2781. values = np.array([0.0, M])
  2782. M = values[1]
  2783. if M < 1:
  2784. return array([], dtype=values.dtype)
  2785. if M == 1:
  2786. return ones(1, dtype=values.dtype)
  2787. n = arange(1-M, M, 2)
  2788. return 0.5 + 0.5*cos(pi*n/(M-1))
  2789. @set_module('numpy')
  2790. def hamming(M):
  2791. """
  2792. Return the Hamming window.
  2793. The Hamming window is a taper formed by using a weighted cosine.
  2794. Parameters
  2795. ----------
  2796. M : int
  2797. Number of points in the output window. If zero or less, an
  2798. empty array is returned.
  2799. Returns
  2800. -------
  2801. out : ndarray
  2802. The window, with the maximum value normalized to one (the value
  2803. one appears only if the number of samples is odd).
  2804. See Also
  2805. --------
  2806. bartlett, blackman, hanning, kaiser
  2807. Notes
  2808. -----
  2809. The Hamming window is defined as
  2810. .. math:: w(n) = 0.54 - 0.46\\cos\\left(\\frac{2\\pi{n}}{M-1}\\right)
  2811. \\qquad 0 \\leq n \\leq M-1
  2812. The Hamming was named for R. W. Hamming, an associate of J. W. Tukey
  2813. and is described in Blackman and Tukey. It was recommended for
  2814. smoothing the truncated autocovariance function in the time domain.
  2815. Most references to the Hamming window come from the signal processing
  2816. literature, where it is used as one of many windowing functions for
  2817. smoothing values. It is also known as an apodization (which means
  2818. "removing the foot", i.e. smoothing discontinuities at the beginning
  2819. and end of the sampled signal) or tapering function.
  2820. References
  2821. ----------
  2822. .. [1] Blackman, R.B. and Tukey, J.W., (1958) The measurement of power
  2823. spectra, Dover Publications, New York.
  2824. .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", The
  2825. University of Alberta Press, 1975, pp. 109-110.
  2826. .. [3] Wikipedia, "Window function",
  2827. https://en.wikipedia.org/wiki/Window_function
  2828. .. [4] W.H. Press, B.P. Flannery, S.A. Teukolsky, and W.T. Vetterling,
  2829. "Numerical Recipes", Cambridge University Press, 1986, page 425.
  2830. Examples
  2831. --------
  2832. >>> import numpy as np
  2833. >>> np.hamming(12)
  2834. array([ 0.08 , 0.15302337, 0.34890909, 0.60546483, 0.84123594, # may vary
  2835. 0.98136677, 0.98136677, 0.84123594, 0.60546483, 0.34890909,
  2836. 0.15302337, 0.08 ])
  2837. Plot the window and the frequency response.
  2838. .. plot::
  2839. :include-source:
  2840. import matplotlib.pyplot as plt
  2841. from numpy.fft import fft, fftshift
  2842. window = np.hamming(51)
  2843. plt.plot(window)
  2844. plt.title("Hamming window")
  2845. plt.ylabel("Amplitude")
  2846. plt.xlabel("Sample")
  2847. plt.show()
  2848. plt.figure()
  2849. A = fft(window, 2048) / 25.5
  2850. mag = np.abs(fftshift(A))
  2851. freq = np.linspace(-0.5, 0.5, len(A))
  2852. response = 20 * np.log10(mag)
  2853. response = np.clip(response, -100, 100)
  2854. plt.plot(freq, response)
  2855. plt.title("Frequency response of Hamming window")
  2856. plt.ylabel("Magnitude [dB]")
  2857. plt.xlabel("Normalized frequency [cycles per sample]")
  2858. plt.axis('tight')
  2859. plt.show()
  2860. """
  2861. # Ensures at least float64 via 0.0. M should be an integer, but conversion
  2862. # to double is safe for a range.
  2863. values = np.array([0.0, M])
  2864. M = values[1]
  2865. if M < 1:
  2866. return array([], dtype=values.dtype)
  2867. if M == 1:
  2868. return ones(1, dtype=values.dtype)
  2869. n = arange(1-M, M, 2)
  2870. return 0.54 + 0.46*cos(pi*n/(M-1))
  2871. ## Code from cephes for i0
  2872. _i0A = [
  2873. -4.41534164647933937950E-18,
  2874. 3.33079451882223809783E-17,
  2875. -2.43127984654795469359E-16,
  2876. 1.71539128555513303061E-15,
  2877. -1.16853328779934516808E-14,
  2878. 7.67618549860493561688E-14,
  2879. -4.85644678311192946090E-13,
  2880. 2.95505266312963983461E-12,
  2881. -1.72682629144155570723E-11,
  2882. 9.67580903537323691224E-11,
  2883. -5.18979560163526290666E-10,
  2884. 2.65982372468238665035E-9,
  2885. -1.30002500998624804212E-8,
  2886. 6.04699502254191894932E-8,
  2887. -2.67079385394061173391E-7,
  2888. 1.11738753912010371815E-6,
  2889. -4.41673835845875056359E-6,
  2890. 1.64484480707288970893E-5,
  2891. -5.75419501008210370398E-5,
  2892. 1.88502885095841655729E-4,
  2893. -5.76375574538582365885E-4,
  2894. 1.63947561694133579842E-3,
  2895. -4.32430999505057594430E-3,
  2896. 1.05464603945949983183E-2,
  2897. -2.37374148058994688156E-2,
  2898. 4.93052842396707084878E-2,
  2899. -9.49010970480476444210E-2,
  2900. 1.71620901522208775349E-1,
  2901. -3.04682672343198398683E-1,
  2902. 6.76795274409476084995E-1
  2903. ]
  2904. _i0B = [
  2905. -7.23318048787475395456E-18,
  2906. -4.83050448594418207126E-18,
  2907. 4.46562142029675999901E-17,
  2908. 3.46122286769746109310E-17,
  2909. -2.82762398051658348494E-16,
  2910. -3.42548561967721913462E-16,
  2911. 1.77256013305652638360E-15,
  2912. 3.81168066935262242075E-15,
  2913. -9.55484669882830764870E-15,
  2914. -4.15056934728722208663E-14,
  2915. 1.54008621752140982691E-14,
  2916. 3.85277838274214270114E-13,
  2917. 7.18012445138366623367E-13,
  2918. -1.79417853150680611778E-12,
  2919. -1.32158118404477131188E-11,
  2920. -3.14991652796324136454E-11,
  2921. 1.18891471078464383424E-11,
  2922. 4.94060238822496958910E-10,
  2923. 3.39623202570838634515E-9,
  2924. 2.26666899049817806459E-8,
  2925. 2.04891858946906374183E-7,
  2926. 2.89137052083475648297E-6,
  2927. 6.88975834691682398426E-5,
  2928. 3.36911647825569408990E-3,
  2929. 8.04490411014108831608E-1
  2930. ]
  2931. def _chbevl(x, vals):
  2932. b0 = vals[0]
  2933. b1 = 0.0
  2934. for i in range(1, len(vals)):
  2935. b2 = b1
  2936. b1 = b0
  2937. b0 = x*b1 - b2 + vals[i]
  2938. return 0.5*(b0 - b2)
  2939. def _i0_1(x):
  2940. return exp(x) * _chbevl(x/2.0-2, _i0A)
  2941. def _i0_2(x):
  2942. return exp(x) * _chbevl(32.0/x - 2.0, _i0B) / sqrt(x)
  2943. def _i0_dispatcher(x):
  2944. return (x,)
  2945. @array_function_dispatch(_i0_dispatcher)
  2946. def i0(x):
  2947. """
  2948. Modified Bessel function of the first kind, order 0.
  2949. Usually denoted :math:`I_0`.
  2950. Parameters
  2951. ----------
  2952. x : array_like of float
  2953. Argument of the Bessel function.
  2954. Returns
  2955. -------
  2956. out : ndarray, shape = x.shape, dtype = float
  2957. The modified Bessel function evaluated at each of the elements of `x`.
  2958. See Also
  2959. --------
  2960. scipy.special.i0, scipy.special.iv, scipy.special.ive
  2961. Notes
  2962. -----
  2963. The scipy implementation is recommended over this function: it is a
  2964. proper ufunc written in C, and more than an order of magnitude faster.
  2965. We use the algorithm published by Clenshaw [1]_ and referenced by
  2966. Abramowitz and Stegun [2]_, for which the function domain is
  2967. partitioned into the two intervals [0,8] and (8,inf), and Chebyshev
  2968. polynomial expansions are employed in each interval. Relative error on
  2969. the domain [0,30] using IEEE arithmetic is documented [3]_ as having a
  2970. peak of 5.8e-16 with an rms of 1.4e-16 (n = 30000).
  2971. References
  2972. ----------
  2973. .. [1] C. W. Clenshaw, "Chebyshev series for mathematical functions", in
  2974. *National Physical Laboratory Mathematical Tables*, vol. 5, London:
  2975. Her Majesty's Stationery Office, 1962.
  2976. .. [2] M. Abramowitz and I. A. Stegun, *Handbook of Mathematical
  2977. Functions*, 10th printing, New York: Dover, 1964, pp. 379.
  2978. https://personal.math.ubc.ca/~cbm/aands/page_379.htm
  2979. .. [3] https://metacpan.org/pod/distribution/Math-Cephes/lib/Math/Cephes.pod#i0:-Modified-Bessel-function-of-order-zero
  2980. Examples
  2981. --------
  2982. >>> import numpy as np
  2983. >>> np.i0(0.)
  2984. array(1.0)
  2985. >>> np.i0([0, 1, 2, 3])
  2986. array([1. , 1.26606588, 2.2795853 , 4.88079259])
  2987. """
  2988. x = np.asanyarray(x)
  2989. if x.dtype.kind == 'c':
  2990. raise TypeError("i0 not supported for complex values")
  2991. if x.dtype.kind != 'f':
  2992. x = x.astype(float)
  2993. x = np.abs(x)
  2994. return piecewise(x, [x <= 8.0], [_i0_1, _i0_2])
  2995. ## End of cephes code for i0
  2996. @set_module('numpy')
  2997. def kaiser(M, beta):
  2998. """
  2999. Return the Kaiser window.
  3000. The Kaiser window is a taper formed by using a Bessel function.
  3001. Parameters
  3002. ----------
  3003. M : int
  3004. Number of points in the output window. If zero or less, an
  3005. empty array is returned.
  3006. beta : float
  3007. Shape parameter for window.
  3008. Returns
  3009. -------
  3010. out : array
  3011. The window, with the maximum value normalized to one (the value
  3012. one appears only if the number of samples is odd).
  3013. See Also
  3014. --------
  3015. bartlett, blackman, hamming, hanning
  3016. Notes
  3017. -----
  3018. The Kaiser window is defined as
  3019. .. math:: w(n) = I_0\\left( \\beta \\sqrt{1-\\frac{4n^2}{(M-1)^2}}
  3020. \\right)/I_0(\\beta)
  3021. with
  3022. .. math:: \\quad -\\frac{M-1}{2} \\leq n \\leq \\frac{M-1}{2},
  3023. where :math:`I_0` is the modified zeroth-order Bessel function.
  3024. The Kaiser was named for Jim Kaiser, who discovered a simple
  3025. approximation to the DPSS window based on Bessel functions. The Kaiser
  3026. window is a very good approximation to the Digital Prolate Spheroidal
  3027. Sequence, or Slepian window, which is the transform which maximizes the
  3028. energy in the main lobe of the window relative to total energy.
  3029. The Kaiser can approximate many other windows by varying the beta
  3030. parameter.
  3031. ==== =======================
  3032. beta Window shape
  3033. ==== =======================
  3034. 0 Rectangular
  3035. 5 Similar to a Hamming
  3036. 6 Similar to a Hanning
  3037. 8.6 Similar to a Blackman
  3038. ==== =======================
  3039. A beta value of 14 is probably a good starting point. Note that as beta
  3040. gets large, the window narrows, and so the number of samples needs to be
  3041. large enough to sample the increasingly narrow spike, otherwise NaNs will
  3042. get returned.
  3043. Most references to the Kaiser window come from the signal processing
  3044. literature, where it is used as one of many windowing functions for
  3045. smoothing values. It is also known as an apodization (which means
  3046. "removing the foot", i.e. smoothing discontinuities at the beginning
  3047. and end of the sampled signal) or tapering function.
  3048. References
  3049. ----------
  3050. .. [1] J. F. Kaiser, "Digital Filters" - Ch 7 in "Systems analysis by
  3051. digital computer", Editors: F.F. Kuo and J.F. Kaiser, p 218-285.
  3052. John Wiley and Sons, New York, (1966).
  3053. .. [2] E.R. Kanasewich, "Time Sequence Analysis in Geophysics", The
  3054. University of Alberta Press, 1975, pp. 177-178.
  3055. .. [3] Wikipedia, "Window function",
  3056. https://en.wikipedia.org/wiki/Window_function
  3057. Examples
  3058. --------
  3059. >>> import numpy as np
  3060. >>> import matplotlib.pyplot as plt
  3061. >>> np.kaiser(12, 14)
  3062. array([7.72686684e-06, 3.46009194e-03, 4.65200189e-02, # may vary
  3063. 2.29737120e-01, 5.99885316e-01, 9.45674898e-01,
  3064. 9.45674898e-01, 5.99885316e-01, 2.29737120e-01,
  3065. 4.65200189e-02, 3.46009194e-03, 7.72686684e-06])
  3066. Plot the window and the frequency response.
  3067. .. plot::
  3068. :include-source:
  3069. import matplotlib.pyplot as plt
  3070. from numpy.fft import fft, fftshift
  3071. window = np.kaiser(51, 14)
  3072. plt.plot(window)
  3073. plt.title("Kaiser window")
  3074. plt.ylabel("Amplitude")
  3075. plt.xlabel("Sample")
  3076. plt.show()
  3077. plt.figure()
  3078. A = fft(window, 2048) / 25.5
  3079. mag = np.abs(fftshift(A))
  3080. freq = np.linspace(-0.5, 0.5, len(A))
  3081. response = 20 * np.log10(mag)
  3082. response = np.clip(response, -100, 100)
  3083. plt.plot(freq, response)
  3084. plt.title("Frequency response of Kaiser window")
  3085. plt.ylabel("Magnitude [dB]")
  3086. plt.xlabel("Normalized frequency [cycles per sample]")
  3087. plt.axis('tight')
  3088. plt.show()
  3089. """
  3090. # Ensures at least float64 via 0.0. M should be an integer, but conversion
  3091. # to double is safe for a range. (Simplified result_type with 0.0
  3092. # strongly typed. result-type is not/less order sensitive, but that mainly
  3093. # matters for integers anyway.)
  3094. values = np.array([0.0, M, beta])
  3095. M = values[1]
  3096. beta = values[2]
  3097. if M == 1:
  3098. return np.ones(1, dtype=values.dtype)
  3099. n = arange(0, M)
  3100. alpha = (M-1)/2.0
  3101. return i0(beta * sqrt(1-((n-alpha)/alpha)**2.0))/i0(beta)
  3102. def _sinc_dispatcher(x):
  3103. return (x,)
  3104. @array_function_dispatch(_sinc_dispatcher)
  3105. def sinc(x):
  3106. r"""
  3107. Return the normalized sinc function.
  3108. The sinc function is equal to :math:`\sin(\pi x)/(\pi x)` for any argument
  3109. :math:`x\ne 0`. ``sinc(0)`` takes the limit value 1, making ``sinc`` not
  3110. only everywhere continuous but also infinitely differentiable.
  3111. .. note::
  3112. Note the normalization factor of ``pi`` used in the definition.
  3113. This is the most commonly used definition in signal processing.
  3114. Use ``sinc(x / np.pi)`` to obtain the unnormalized sinc function
  3115. :math:`\sin(x)/x` that is more common in mathematics.
  3116. Parameters
  3117. ----------
  3118. x : ndarray
  3119. Array (possibly multi-dimensional) of values for which to calculate
  3120. ``sinc(x)``.
  3121. Returns
  3122. -------
  3123. out : ndarray
  3124. ``sinc(x)``, which has the same shape as the input.
  3125. Notes
  3126. -----
  3127. The name sinc is short for "sine cardinal" or "sinus cardinalis".
  3128. The sinc function is used in various signal processing applications,
  3129. including in anti-aliasing, in the construction of a Lanczos resampling
  3130. filter, and in interpolation.
  3131. For bandlimited interpolation of discrete-time signals, the ideal
  3132. interpolation kernel is proportional to the sinc function.
  3133. References
  3134. ----------
  3135. .. [1] Weisstein, Eric W. "Sinc Function." From MathWorld--A Wolfram Web
  3136. Resource. https://mathworld.wolfram.com/SincFunction.html
  3137. .. [2] Wikipedia, "Sinc function",
  3138. https://en.wikipedia.org/wiki/Sinc_function
  3139. Examples
  3140. --------
  3141. >>> import numpy as np
  3142. >>> import matplotlib.pyplot as plt
  3143. >>> x = np.linspace(-4, 4, 41)
  3144. >>> np.sinc(x)
  3145. array([-3.89804309e-17, -4.92362781e-02, -8.40918587e-02, # may vary
  3146. -8.90384387e-02, -5.84680802e-02, 3.89804309e-17,
  3147. 6.68206631e-02, 1.16434881e-01, 1.26137788e-01,
  3148. 8.50444803e-02, -3.89804309e-17, -1.03943254e-01,
  3149. -1.89206682e-01, -2.16236208e-01, -1.55914881e-01,
  3150. 3.89804309e-17, 2.33872321e-01, 5.04551152e-01,
  3151. 7.56826729e-01, 9.35489284e-01, 1.00000000e+00,
  3152. 9.35489284e-01, 7.56826729e-01, 5.04551152e-01,
  3153. 2.33872321e-01, 3.89804309e-17, -1.55914881e-01,
  3154. -2.16236208e-01, -1.89206682e-01, -1.03943254e-01,
  3155. -3.89804309e-17, 8.50444803e-02, 1.26137788e-01,
  3156. 1.16434881e-01, 6.68206631e-02, 3.89804309e-17,
  3157. -5.84680802e-02, -8.90384387e-02, -8.40918587e-02,
  3158. -4.92362781e-02, -3.89804309e-17])
  3159. >>> plt.plot(x, np.sinc(x))
  3160. [<matplotlib.lines.Line2D object at 0x...>]
  3161. >>> plt.title("Sinc Function")
  3162. Text(0.5, 1.0, 'Sinc Function')
  3163. >>> plt.ylabel("Amplitude")
  3164. Text(0, 0.5, 'Amplitude')
  3165. >>> plt.xlabel("X")
  3166. Text(0.5, 0, 'X')
  3167. >>> plt.show()
  3168. """
  3169. x = np.asanyarray(x)
  3170. y = pi * where(x == 0, 1.0e-20, x)
  3171. return sin(y)/y
  3172. def _ureduce(a, func, keepdims=False, **kwargs):
  3173. """
  3174. Internal Function.
  3175. Call `func` with `a` as first argument swapping the axes to use extended
  3176. axis on functions that don't support it natively.
  3177. Returns result and a.shape with axis dims set to 1.
  3178. Parameters
  3179. ----------
  3180. a : array_like
  3181. Input array or object that can be converted to an array.
  3182. func : callable
  3183. Reduction function capable of receiving a single axis argument.
  3184. It is called with `a` as first argument followed by `kwargs`.
  3185. kwargs : keyword arguments
  3186. additional keyword arguments to pass to `func`.
  3187. Returns
  3188. -------
  3189. result : tuple
  3190. Result of func(a, **kwargs) and a.shape with axis dims set to 1
  3191. which can be used to reshape the result to the same shape a ufunc with
  3192. keepdims=True would produce.
  3193. """
  3194. a = np.asanyarray(a)
  3195. axis = kwargs.get('axis', None)
  3196. out = kwargs.get('out', None)
  3197. if keepdims is np._NoValue:
  3198. keepdims = False
  3199. nd = a.ndim
  3200. if axis is not None:
  3201. axis = _nx.normalize_axis_tuple(axis, nd)
  3202. if keepdims:
  3203. if out is not None:
  3204. index_out = tuple(
  3205. 0 if i in axis else slice(None) for i in range(nd))
  3206. kwargs['out'] = out[(Ellipsis, ) + index_out]
  3207. if len(axis) == 1:
  3208. kwargs['axis'] = axis[0]
  3209. else:
  3210. keep = set(range(nd)) - set(axis)
  3211. nkeep = len(keep)
  3212. # swap axis that should not be reduced to front
  3213. for i, s in enumerate(sorted(keep)):
  3214. a = a.swapaxes(i, s)
  3215. # merge reduced axis
  3216. a = a.reshape(a.shape[:nkeep] + (-1,))
  3217. kwargs['axis'] = -1
  3218. else:
  3219. if keepdims:
  3220. if out is not None:
  3221. index_out = (0, ) * nd
  3222. kwargs['out'] = out[(Ellipsis, ) + index_out]
  3223. r = func(a, **kwargs)
  3224. if out is not None:
  3225. return out
  3226. if keepdims:
  3227. if axis is None:
  3228. index_r = (np.newaxis, ) * nd
  3229. else:
  3230. index_r = tuple(
  3231. np.newaxis if i in axis else slice(None)
  3232. for i in range(nd))
  3233. r = r[(Ellipsis, ) + index_r]
  3234. return r
  3235. def _median_dispatcher(
  3236. a, axis=None, out=None, overwrite_input=None, keepdims=None):
  3237. return (a, out)
  3238. @array_function_dispatch(_median_dispatcher)
  3239. def median(a, axis=None, out=None, overwrite_input=False, keepdims=False):
  3240. """
  3241. Compute the median along the specified axis.
  3242. Returns the median of the array elements.
  3243. Parameters
  3244. ----------
  3245. a : array_like
  3246. Input array or object that can be converted to an array.
  3247. axis : {int, sequence of int, None}, optional
  3248. Axis or axes along which the medians are computed. The default,
  3249. axis=None, will compute the median along a flattened version of
  3250. the array. If a sequence of axes, the array is first flattened
  3251. along the given axes, then the median is computed along the
  3252. resulting flattened axis.
  3253. out : ndarray, optional
  3254. Alternative output array in which to place the result. It must
  3255. have the same shape and buffer length as the expected output,
  3256. but the type (of the output) will be cast if necessary.
  3257. overwrite_input : bool, optional
  3258. If True, then allow use of memory of input array `a` for
  3259. calculations. The input array will be modified by the call to
  3260. `median`. This will save memory when you do not need to preserve
  3261. the contents of the input array. Treat the input as undefined,
  3262. but it will probably be fully or partially sorted. Default is
  3263. False. If `overwrite_input` is ``True`` and `a` is not already an
  3264. `ndarray`, an error will be raised.
  3265. keepdims : bool, optional
  3266. If this is set to True, the axes which are reduced are left
  3267. in the result as dimensions with size one. With this option,
  3268. the result will broadcast correctly against the original `arr`.
  3269. Returns
  3270. -------
  3271. median : ndarray
  3272. A new array holding the result. If the input contains integers
  3273. or floats smaller than ``float64``, then the output data-type is
  3274. ``np.float64``. Otherwise, the data-type of the output is the
  3275. same as that of the input. If `out` is specified, that array is
  3276. returned instead.
  3277. See Also
  3278. --------
  3279. mean, percentile
  3280. Notes
  3281. -----
  3282. Given a vector ``V`` of length ``N``, the median of ``V`` is the
  3283. middle value of a sorted copy of ``V``, ``V_sorted`` - i
  3284. e., ``V_sorted[(N-1)/2]``, when ``N`` is odd, and the average of the
  3285. two middle values of ``V_sorted`` when ``N`` is even.
  3286. Examples
  3287. --------
  3288. >>> import numpy as np
  3289. >>> a = np.array([[10, 7, 4], [3, 2, 1]])
  3290. >>> a
  3291. array([[10, 7, 4],
  3292. [ 3, 2, 1]])
  3293. >>> np.median(a)
  3294. np.float64(3.5)
  3295. >>> np.median(a, axis=0)
  3296. array([6.5, 4.5, 2.5])
  3297. >>> np.median(a, axis=1)
  3298. array([7., 2.])
  3299. >>> np.median(a, axis=(0, 1))
  3300. np.float64(3.5)
  3301. >>> m = np.median(a, axis=0)
  3302. >>> out = np.zeros_like(m)
  3303. >>> np.median(a, axis=0, out=m)
  3304. array([6.5, 4.5, 2.5])
  3305. >>> m
  3306. array([6.5, 4.5, 2.5])
  3307. >>> b = a.copy()
  3308. >>> np.median(b, axis=1, overwrite_input=True)
  3309. array([7., 2.])
  3310. >>> assert not np.all(a==b)
  3311. >>> b = a.copy()
  3312. >>> np.median(b, axis=None, overwrite_input=True)
  3313. np.float64(3.5)
  3314. >>> assert not np.all(a==b)
  3315. """
  3316. return _ureduce(a, func=_median, keepdims=keepdims, axis=axis, out=out,
  3317. overwrite_input=overwrite_input)
  3318. def _median(a, axis=None, out=None, overwrite_input=False):
  3319. # can't be reasonably be implemented in terms of percentile as we have to
  3320. # call mean to not break astropy
  3321. a = np.asanyarray(a)
  3322. # Set the partition indexes
  3323. if axis is None:
  3324. sz = a.size
  3325. else:
  3326. sz = a.shape[axis]
  3327. if sz % 2 == 0:
  3328. szh = sz // 2
  3329. kth = [szh - 1, szh]
  3330. else:
  3331. kth = [(sz - 1) // 2]
  3332. # We have to check for NaNs (as of writing 'M' doesn't actually work).
  3333. supports_nans = np.issubdtype(a.dtype, np.inexact) or a.dtype.kind in 'Mm'
  3334. if supports_nans:
  3335. kth.append(-1)
  3336. if overwrite_input:
  3337. if axis is None:
  3338. part = a.ravel()
  3339. part.partition(kth)
  3340. else:
  3341. a.partition(kth, axis=axis)
  3342. part = a
  3343. else:
  3344. part = partition(a, kth, axis=axis)
  3345. if part.shape == ():
  3346. # make 0-D arrays work
  3347. return part.item()
  3348. if axis is None:
  3349. axis = 0
  3350. indexer = [slice(None)] * part.ndim
  3351. index = part.shape[axis] // 2
  3352. if part.shape[axis] % 2 == 1:
  3353. # index with slice to allow mean (below) to work
  3354. indexer[axis] = slice(index, index+1)
  3355. else:
  3356. indexer[axis] = slice(index-1, index+1)
  3357. indexer = tuple(indexer)
  3358. # Use mean in both odd and even case to coerce data type,
  3359. # using out array if needed.
  3360. rout = mean(part[indexer], axis=axis, out=out)
  3361. if supports_nans and sz > 0:
  3362. # If nans are possible, warn and replace by nans like mean would.
  3363. rout = np.lib._utils_impl._median_nancheck(part, rout, axis)
  3364. return rout
  3365. def _percentile_dispatcher(a, q, axis=None, out=None, overwrite_input=None,
  3366. method=None, keepdims=None, *, weights=None,
  3367. interpolation=None):
  3368. return (a, q, out, weights)
  3369. @array_function_dispatch(_percentile_dispatcher)
  3370. def percentile(a,
  3371. q,
  3372. axis=None,
  3373. out=None,
  3374. overwrite_input=False,
  3375. method="linear",
  3376. keepdims=False,
  3377. *,
  3378. weights=None,
  3379. interpolation=None):
  3380. """
  3381. Compute the q-th percentile of the data along the specified axis.
  3382. Returns the q-th percentile(s) of the array elements.
  3383. Parameters
  3384. ----------
  3385. a : array_like of real numbers
  3386. Input array or object that can be converted to an array.
  3387. q : array_like of float
  3388. Percentage or sequence of percentages for the percentiles to compute.
  3389. Values must be between 0 and 100 inclusive.
  3390. axis : {int, tuple of int, None}, optional
  3391. Axis or axes along which the percentiles are computed. The
  3392. default is to compute the percentile(s) along a flattened
  3393. version of the array.
  3394. out : ndarray, optional
  3395. Alternative output array in which to place the result. It must
  3396. have the same shape and buffer length as the expected output,
  3397. but the type (of the output) will be cast if necessary.
  3398. overwrite_input : bool, optional
  3399. If True, then allow the input array `a` to be modified by intermediate
  3400. calculations, to save memory. In this case, the contents of the input
  3401. `a` after this function completes is undefined.
  3402. method : str, optional
  3403. This parameter specifies the method to use for estimating the
  3404. percentile. There are many different methods, some unique to NumPy.
  3405. See the notes for explanation. The options sorted by their R type
  3406. as summarized in the H&F paper [1]_ are:
  3407. 1. 'inverted_cdf'
  3408. 2. 'averaged_inverted_cdf'
  3409. 3. 'closest_observation'
  3410. 4. 'interpolated_inverted_cdf'
  3411. 5. 'hazen'
  3412. 6. 'weibull'
  3413. 7. 'linear' (default)
  3414. 8. 'median_unbiased'
  3415. 9. 'normal_unbiased'
  3416. The first three methods are discontinuous. NumPy further defines the
  3417. following discontinuous variations of the default 'linear' (7.) option:
  3418. * 'lower'
  3419. * 'higher',
  3420. * 'midpoint'
  3421. * 'nearest'
  3422. .. versionchanged:: 1.22.0
  3423. This argument was previously called "interpolation" and only
  3424. offered the "linear" default and last four options.
  3425. keepdims : bool, optional
  3426. If this is set to True, the axes which are reduced are left in
  3427. the result as dimensions with size one. With this option, the
  3428. result will broadcast correctly against the original array `a`.
  3429. weights : array_like, optional
  3430. An array of weights associated with the values in `a`. Each value in
  3431. `a` contributes to the percentile according to its associated weight.
  3432. The weights array can either be 1-D (in which case its length must be
  3433. the size of `a` along the given axis) or of the same shape as `a`.
  3434. If `weights=None`, then all data in `a` are assumed to have a
  3435. weight equal to one.
  3436. Only `method="inverted_cdf"` supports weights.
  3437. See the notes for more details.
  3438. .. versionadded:: 2.0.0
  3439. interpolation : str, optional
  3440. Deprecated name for the method keyword argument.
  3441. .. deprecated:: 1.22.0
  3442. Returns
  3443. -------
  3444. percentile : scalar or ndarray
  3445. If `q` is a single percentile and `axis=None`, then the result
  3446. is a scalar. If multiple percentiles are given, first axis of
  3447. the result corresponds to the percentiles. The other axes are
  3448. the axes that remain after the reduction of `a`. If the input
  3449. contains integers or floats smaller than ``float64``, the output
  3450. data-type is ``float64``. Otherwise, the output data-type is the
  3451. same as that of the input. If `out` is specified, that array is
  3452. returned instead.
  3453. See Also
  3454. --------
  3455. mean
  3456. median : equivalent to ``percentile(..., 50)``
  3457. nanpercentile
  3458. quantile : equivalent to percentile, except q in the range [0, 1].
  3459. Notes
  3460. -----
  3461. The behavior of `numpy.percentile` with percentage `q` is
  3462. that of `numpy.quantile` with argument ``q/100``.
  3463. For more information, please see `numpy.quantile`.
  3464. Examples
  3465. --------
  3466. >>> import numpy as np
  3467. >>> a = np.array([[10, 7, 4], [3, 2, 1]])
  3468. >>> a
  3469. array([[10, 7, 4],
  3470. [ 3, 2, 1]])
  3471. >>> np.percentile(a, 50)
  3472. 3.5
  3473. >>> np.percentile(a, 50, axis=0)
  3474. array([6.5, 4.5, 2.5])
  3475. >>> np.percentile(a, 50, axis=1)
  3476. array([7., 2.])
  3477. >>> np.percentile(a, 50, axis=1, keepdims=True)
  3478. array([[7.],
  3479. [2.]])
  3480. >>> m = np.percentile(a, 50, axis=0)
  3481. >>> out = np.zeros_like(m)
  3482. >>> np.percentile(a, 50, axis=0, out=out)
  3483. array([6.5, 4.5, 2.5])
  3484. >>> m
  3485. array([6.5, 4.5, 2.5])
  3486. >>> b = a.copy()
  3487. >>> np.percentile(b, 50, axis=1, overwrite_input=True)
  3488. array([7., 2.])
  3489. >>> assert not np.all(a == b)
  3490. The different methods can be visualized graphically:
  3491. .. plot::
  3492. import matplotlib.pyplot as plt
  3493. a = np.arange(4)
  3494. p = np.linspace(0, 100, 6001)
  3495. ax = plt.gca()
  3496. lines = [
  3497. ('linear', '-', 'C0'),
  3498. ('inverted_cdf', ':', 'C1'),
  3499. # Almost the same as `inverted_cdf`:
  3500. ('averaged_inverted_cdf', '-.', 'C1'),
  3501. ('closest_observation', ':', 'C2'),
  3502. ('interpolated_inverted_cdf', '--', 'C1'),
  3503. ('hazen', '--', 'C3'),
  3504. ('weibull', '-.', 'C4'),
  3505. ('median_unbiased', '--', 'C5'),
  3506. ('normal_unbiased', '-.', 'C6'),
  3507. ]
  3508. for method, style, color in lines:
  3509. ax.plot(
  3510. p, np.percentile(a, p, method=method),
  3511. label=method, linestyle=style, color=color)
  3512. ax.set(
  3513. title='Percentiles for different methods and data: ' + str(a),
  3514. xlabel='Percentile',
  3515. ylabel='Estimated percentile value',
  3516. yticks=a)
  3517. ax.legend(bbox_to_anchor=(1.03, 1))
  3518. plt.tight_layout()
  3519. plt.show()
  3520. References
  3521. ----------
  3522. .. [1] R. J. Hyndman and Y. Fan,
  3523. "Sample quantiles in statistical packages,"
  3524. The American Statistician, 50(4), pp. 361-365, 1996
  3525. """
  3526. if interpolation is not None:
  3527. method = _check_interpolation_as_method(
  3528. method, interpolation, "percentile")
  3529. a = np.asanyarray(a)
  3530. if a.dtype.kind == "c":
  3531. raise TypeError("a must be an array of real numbers")
  3532. # Use dtype of array if possible (e.g., if q is a python int or float)
  3533. # by making the divisor have the dtype of the data array.
  3534. q = np.true_divide(q, a.dtype.type(100) if a.dtype.kind == "f" else 100)
  3535. q = asanyarray(q) # undo any decay that the ufunc performed (see gh-13105)
  3536. if not _quantile_is_valid(q):
  3537. raise ValueError("Percentiles must be in the range [0, 100]")
  3538. if weights is not None:
  3539. if method != "inverted_cdf":
  3540. msg = ("Only method 'inverted_cdf' supports weights. "
  3541. f"Got: {method}.")
  3542. raise ValueError(msg)
  3543. if axis is not None:
  3544. axis = _nx.normalize_axis_tuple(axis, a.ndim, argname="axis")
  3545. weights = _weights_are_valid(weights=weights, a=a, axis=axis)
  3546. if np.any(weights < 0):
  3547. raise ValueError("Weights must be non-negative.")
  3548. return _quantile_unchecked(
  3549. a, q, axis, out, overwrite_input, method, keepdims, weights)
  3550. def _quantile_dispatcher(a, q, axis=None, out=None, overwrite_input=None,
  3551. method=None, keepdims=None, *, weights=None,
  3552. interpolation=None):
  3553. return (a, q, out, weights)
  3554. @array_function_dispatch(_quantile_dispatcher)
  3555. def quantile(a,
  3556. q,
  3557. axis=None,
  3558. out=None,
  3559. overwrite_input=False,
  3560. method="linear",
  3561. keepdims=False,
  3562. *,
  3563. weights=None,
  3564. interpolation=None):
  3565. """
  3566. Compute the q-th quantile of the data along the specified axis.
  3567. Parameters
  3568. ----------
  3569. a : array_like of real numbers
  3570. Input array or object that can be converted to an array.
  3571. q : array_like of float
  3572. Probability or sequence of probabilities of the quantiles to compute.
  3573. Values must be between 0 and 1 inclusive.
  3574. axis : {int, tuple of int, None}, optional
  3575. Axis or axes along which the quantiles are computed. The default is
  3576. to compute the quantile(s) along a flattened version of the array.
  3577. out : ndarray, optional
  3578. Alternative output array in which to place the result. It must have
  3579. the same shape and buffer length as the expected output, but the
  3580. type (of the output) will be cast if necessary.
  3581. overwrite_input : bool, optional
  3582. If True, then allow the input array `a` to be modified by
  3583. intermediate calculations, to save memory. In this case, the
  3584. contents of the input `a` after this function completes is
  3585. undefined.
  3586. method : str, optional
  3587. This parameter specifies the method to use for estimating the
  3588. quantile. There are many different methods, some unique to NumPy.
  3589. The recommended options, numbered as they appear in [1]_, are:
  3590. 1. 'inverted_cdf'
  3591. 2. 'averaged_inverted_cdf'
  3592. 3. 'closest_observation'
  3593. 4. 'interpolated_inverted_cdf'
  3594. 5. 'hazen'
  3595. 6. 'weibull'
  3596. 7. 'linear' (default)
  3597. 8. 'median_unbiased'
  3598. 9. 'normal_unbiased'
  3599. The first three methods are discontinuous. For backward compatibility
  3600. with previous versions of NumPy, the following discontinuous variations
  3601. of the default 'linear' (7.) option are available:
  3602. * 'lower'
  3603. * 'higher',
  3604. * 'midpoint'
  3605. * 'nearest'
  3606. See Notes for details.
  3607. .. versionchanged:: 1.22.0
  3608. This argument was previously called "interpolation" and only
  3609. offered the "linear" default and last four options.
  3610. keepdims : bool, optional
  3611. If this is set to True, the axes which are reduced are left in
  3612. the result as dimensions with size one. With this option, the
  3613. result will broadcast correctly against the original array `a`.
  3614. weights : array_like, optional
  3615. An array of weights associated with the values in `a`. Each value in
  3616. `a` contributes to the quantile according to its associated weight.
  3617. The weights array can either be 1-D (in which case its length must be
  3618. the size of `a` along the given axis) or of the same shape as `a`.
  3619. If `weights=None`, then all data in `a` are assumed to have a
  3620. weight equal to one.
  3621. Only `method="inverted_cdf"` supports weights.
  3622. See the notes for more details.
  3623. .. versionadded:: 2.0.0
  3624. interpolation : str, optional
  3625. Deprecated name for the method keyword argument.
  3626. .. deprecated:: 1.22.0
  3627. Returns
  3628. -------
  3629. quantile : scalar or ndarray
  3630. If `q` is a single probability and `axis=None`, then the result
  3631. is a scalar. If multiple probability levels are given, first axis
  3632. of the result corresponds to the quantiles. The other axes are
  3633. the axes that remain after the reduction of `a`. If the input
  3634. contains integers or floats smaller than ``float64``, the output
  3635. data-type is ``float64``. Otherwise, the output data-type is the
  3636. same as that of the input. If `out` is specified, that array is
  3637. returned instead.
  3638. See Also
  3639. --------
  3640. mean
  3641. percentile : equivalent to quantile, but with q in the range [0, 100].
  3642. median : equivalent to ``quantile(..., 0.5)``
  3643. nanquantile
  3644. Notes
  3645. -----
  3646. Given a sample `a` from an underlying distribution, `quantile` provides a
  3647. nonparametric estimate of the inverse cumulative distribution function.
  3648. By default, this is done by interpolating between adjacent elements in
  3649. ``y``, a sorted copy of `a`::
  3650. (1-g)*y[j] + g*y[j+1]
  3651. where the index ``j`` and coefficient ``g`` are the integral and
  3652. fractional components of ``q * (n-1)``, and ``n`` is the number of
  3653. elements in the sample.
  3654. This is a special case of Equation 1 of H&F [1]_. More generally,
  3655. - ``j = (q*n + m - 1) // 1``, and
  3656. - ``g = (q*n + m - 1) % 1``,
  3657. where ``m`` may be defined according to several different conventions.
  3658. The preferred convention may be selected using the ``method`` parameter:
  3659. =============================== =============== ===============
  3660. ``method`` number in H&F ``m``
  3661. =============================== =============== ===============
  3662. ``interpolated_inverted_cdf`` 4 ``0``
  3663. ``hazen`` 5 ``1/2``
  3664. ``weibull`` 6 ``q``
  3665. ``linear`` (default) 7 ``1 - q``
  3666. ``median_unbiased`` 8 ``q/3 + 1/3``
  3667. ``normal_unbiased`` 9 ``q/4 + 3/8``
  3668. =============================== =============== ===============
  3669. Note that indices ``j`` and ``j + 1`` are clipped to the range ``0`` to
  3670. ``n - 1`` when the results of the formula would be outside the allowed
  3671. range of non-negative indices. The ``- 1`` in the formulas for ``j`` and
  3672. ``g`` accounts for Python's 0-based indexing.
  3673. The table above includes only the estimators from H&F that are continuous
  3674. functions of probability `q` (estimators 4-9). NumPy also provides the
  3675. three discontinuous estimators from H&F (estimators 1-3), where ``j`` is
  3676. defined as above, ``m`` is defined as follows, and ``g`` is a function
  3677. of the real-valued ``index = q*n + m - 1`` and ``j``.
  3678. 1. ``inverted_cdf``: ``m = 0`` and ``g = int(index - j > 0)``
  3679. 2. ``averaged_inverted_cdf``: ``m = 0`` and
  3680. ``g = (1 + int(index - j > 0)) / 2``
  3681. 3. ``closest_observation``: ``m = -1/2`` and
  3682. ``g = 1 - int((index == j) & (j%2 == 1))``
  3683. For backward compatibility with previous versions of NumPy, `quantile`
  3684. provides four additional discontinuous estimators. Like
  3685. ``method='linear'``, all have ``m = 1 - q`` so that ``j = q*(n-1) // 1``,
  3686. but ``g`` is defined as follows.
  3687. - ``lower``: ``g = 0``
  3688. - ``midpoint``: ``g = 0.5``
  3689. - ``higher``: ``g = 1``
  3690. - ``nearest``: ``g = (q*(n-1) % 1) > 0.5``
  3691. **Weighted quantiles:**
  3692. More formally, the quantile at probability level :math:`q` of a cumulative
  3693. distribution function :math:`F(y)=P(Y \\leq y)` with probability measure
  3694. :math:`P` is defined as any number :math:`x` that fulfills the
  3695. *coverage conditions*
  3696. .. math:: P(Y < x) \\leq q \\quad\\text{and}\\quad P(Y \\leq x) \\geq q
  3697. with random variable :math:`Y\\sim P`.
  3698. Sample quantiles, the result of `quantile`, provide nonparametric
  3699. estimation of the underlying population counterparts, represented by the
  3700. unknown :math:`F`, given a data vector `a` of length ``n``.
  3701. Some of the estimators above arise when one considers :math:`F` as the
  3702. empirical distribution function of the data, i.e.
  3703. :math:`F(y) = \\frac{1}{n} \\sum_i 1_{a_i \\leq y}`.
  3704. Then, different methods correspond to different choices of :math:`x` that
  3705. fulfill the above coverage conditions. Methods that follow this approach
  3706. are ``inverted_cdf`` and ``averaged_inverted_cdf``.
  3707. For weighted quantiles, the coverage conditions still hold. The
  3708. empirical cumulative distribution is simply replaced by its weighted
  3709. version, i.e.
  3710. :math:`P(Y \\leq t) = \\frac{1}{\\sum_i w_i} \\sum_i w_i 1_{x_i \\leq t}`.
  3711. Only ``method="inverted_cdf"`` supports weights.
  3712. Examples
  3713. --------
  3714. >>> import numpy as np
  3715. >>> a = np.array([[10, 7, 4], [3, 2, 1]])
  3716. >>> a
  3717. array([[10, 7, 4],
  3718. [ 3, 2, 1]])
  3719. >>> np.quantile(a, 0.5)
  3720. 3.5
  3721. >>> np.quantile(a, 0.5, axis=0)
  3722. array([6.5, 4.5, 2.5])
  3723. >>> np.quantile(a, 0.5, axis=1)
  3724. array([7., 2.])
  3725. >>> np.quantile(a, 0.5, axis=1, keepdims=True)
  3726. array([[7.],
  3727. [2.]])
  3728. >>> m = np.quantile(a, 0.5, axis=0)
  3729. >>> out = np.zeros_like(m)
  3730. >>> np.quantile(a, 0.5, axis=0, out=out)
  3731. array([6.5, 4.5, 2.5])
  3732. >>> m
  3733. array([6.5, 4.5, 2.5])
  3734. >>> b = a.copy()
  3735. >>> np.quantile(b, 0.5, axis=1, overwrite_input=True)
  3736. array([7., 2.])
  3737. >>> assert not np.all(a == b)
  3738. See also `numpy.percentile` for a visualization of most methods.
  3739. References
  3740. ----------
  3741. .. [1] R. J. Hyndman and Y. Fan,
  3742. "Sample quantiles in statistical packages,"
  3743. The American Statistician, 50(4), pp. 361-365, 1996
  3744. """
  3745. if interpolation is not None:
  3746. method = _check_interpolation_as_method(
  3747. method, interpolation, "quantile")
  3748. a = np.asanyarray(a)
  3749. if a.dtype.kind == "c":
  3750. raise TypeError("a must be an array of real numbers")
  3751. # Use dtype of array if possible (e.g., if q is a python int or float).
  3752. if isinstance(q, (int, float)) and a.dtype.kind == "f":
  3753. q = np.asanyarray(q, dtype=a.dtype)
  3754. else:
  3755. q = np.asanyarray(q)
  3756. if not _quantile_is_valid(q):
  3757. raise ValueError("Quantiles must be in the range [0, 1]")
  3758. if weights is not None:
  3759. if method != "inverted_cdf":
  3760. msg = ("Only method 'inverted_cdf' supports weights. "
  3761. f"Got: {method}.")
  3762. raise ValueError(msg)
  3763. if axis is not None:
  3764. axis = _nx.normalize_axis_tuple(axis, a.ndim, argname="axis")
  3765. weights = _weights_are_valid(weights=weights, a=a, axis=axis)
  3766. if np.any(weights < 0):
  3767. raise ValueError("Weights must be non-negative.")
  3768. return _quantile_unchecked(
  3769. a, q, axis, out, overwrite_input, method, keepdims, weights)
  3770. def _quantile_unchecked(a,
  3771. q,
  3772. axis=None,
  3773. out=None,
  3774. overwrite_input=False,
  3775. method="linear",
  3776. keepdims=False,
  3777. weights=None):
  3778. """Assumes that q is in [0, 1], and is an ndarray"""
  3779. return _ureduce(a,
  3780. func=_quantile_ureduce_func,
  3781. q=q,
  3782. weights=weights,
  3783. keepdims=keepdims,
  3784. axis=axis,
  3785. out=out,
  3786. overwrite_input=overwrite_input,
  3787. method=method)
  3788. def _quantile_is_valid(q):
  3789. # avoid expensive reductions, relevant for arrays with < O(1000) elements
  3790. if q.ndim == 1 and q.size < 10:
  3791. for i in range(q.size):
  3792. if not (0.0 <= q[i] <= 1.0):
  3793. return False
  3794. else:
  3795. if not (q.min() >= 0 and q.max() <= 1):
  3796. return False
  3797. return True
  3798. def _check_interpolation_as_method(method, interpolation, fname):
  3799. # Deprecated NumPy 1.22, 2021-11-08
  3800. warnings.warn(
  3801. f"the `interpolation=` argument to {fname} was renamed to "
  3802. "`method=`, which has additional options.\n"
  3803. "Users of the modes 'nearest', 'lower', 'higher', or "
  3804. "'midpoint' are encouraged to review the method they used. "
  3805. "(Deprecated NumPy 1.22)",
  3806. DeprecationWarning, stacklevel=4)
  3807. if method != "linear":
  3808. # sanity check, we assume this basically never happens
  3809. raise TypeError(
  3810. "You shall not pass both `method` and `interpolation`!\n"
  3811. "(`interpolation` is Deprecated in favor of `method`)")
  3812. return interpolation
  3813. def _compute_virtual_index(n, quantiles, alpha: float, beta: float):
  3814. """
  3815. Compute the floating point indexes of an array for the linear
  3816. interpolation of quantiles.
  3817. n : array_like
  3818. The sample sizes.
  3819. quantiles : array_like
  3820. The quantiles values.
  3821. alpha : float
  3822. A constant used to correct the index computed.
  3823. beta : float
  3824. A constant used to correct the index computed.
  3825. alpha and beta values depend on the chosen method
  3826. (see quantile documentation)
  3827. Reference:
  3828. Hyndman&Fan paper "Sample Quantiles in Statistical Packages",
  3829. DOI: 10.1080/00031305.1996.10473566
  3830. """
  3831. return n * quantiles + (
  3832. alpha + quantiles * (1 - alpha - beta)
  3833. ) - 1
  3834. def _get_gamma(virtual_indexes, previous_indexes, method):
  3835. """
  3836. Compute gamma (a.k.a 'm' or 'weight') for the linear interpolation
  3837. of quantiles.
  3838. virtual_indexes : array_like
  3839. The indexes where the percentile is supposed to be found in the sorted
  3840. sample.
  3841. previous_indexes : array_like
  3842. The floor values of virtual_indexes.
  3843. interpolation : dict
  3844. The interpolation method chosen, which may have a specific rule
  3845. modifying gamma.
  3846. gamma is usually the fractional part of virtual_indexes but can be modified
  3847. by the interpolation method.
  3848. """
  3849. gamma = np.asanyarray(virtual_indexes - previous_indexes)
  3850. gamma = method["fix_gamma"](gamma, virtual_indexes)
  3851. # Ensure both that we have an array, and that we keep the dtype
  3852. # (which may have been matched to the input array).
  3853. return np.asanyarray(gamma, dtype=virtual_indexes.dtype)
  3854. def _lerp(a, b, t, out=None):
  3855. """
  3856. Compute the linear interpolation weighted by gamma on each point of
  3857. two same shape array.
  3858. a : array_like
  3859. Left bound.
  3860. b : array_like
  3861. Right bound.
  3862. t : array_like
  3863. The interpolation weight.
  3864. out : array_like
  3865. Output array.
  3866. """
  3867. diff_b_a = subtract(b, a)
  3868. # asanyarray is a stop-gap until gh-13105
  3869. lerp_interpolation = asanyarray(add(a, diff_b_a * t, out=out))
  3870. subtract(b, diff_b_a * (1 - t), out=lerp_interpolation, where=t >= 0.5,
  3871. casting='unsafe', dtype=type(lerp_interpolation.dtype))
  3872. if lerp_interpolation.ndim == 0 and out is None:
  3873. lerp_interpolation = lerp_interpolation[()] # unpack 0d arrays
  3874. return lerp_interpolation
  3875. def _get_gamma_mask(shape, default_value, conditioned_value, where):
  3876. out = np.full(shape, default_value)
  3877. np.copyto(out, conditioned_value, where=where, casting="unsafe")
  3878. return out
  3879. def _discrete_interpolation_to_boundaries(index, gamma_condition_fun):
  3880. previous = np.floor(index)
  3881. next = previous + 1
  3882. gamma = index - previous
  3883. res = _get_gamma_mask(shape=index.shape,
  3884. default_value=next,
  3885. conditioned_value=previous,
  3886. where=gamma_condition_fun(gamma, index)
  3887. ).astype(np.intp)
  3888. # Some methods can lead to out-of-bound integers, clip them:
  3889. res[res < 0] = 0
  3890. return res
  3891. def _closest_observation(n, quantiles):
  3892. # "choose the nearest even order statistic at g=0" (H&F (1996) pp. 362).
  3893. # Order is 1-based so for zero-based indexing round to nearest odd index.
  3894. gamma_fun = lambda gamma, index: (gamma == 0) & (np.floor(index) % 2 == 1)
  3895. return _discrete_interpolation_to_boundaries((n * quantiles) - 1 - 0.5,
  3896. gamma_fun)
  3897. def _inverted_cdf(n, quantiles):
  3898. gamma_fun = lambda gamma, _: (gamma == 0)
  3899. return _discrete_interpolation_to_boundaries((n * quantiles) - 1,
  3900. gamma_fun)
  3901. def _quantile_ureduce_func(
  3902. a: np.array,
  3903. q: np.array,
  3904. weights: np.array,
  3905. axis: int | None = None,
  3906. out=None,
  3907. overwrite_input: bool = False,
  3908. method="linear",
  3909. ) -> np.array:
  3910. if q.ndim > 2:
  3911. # The code below works fine for nd, but it might not have useful
  3912. # semantics. For now, keep the supported dimensions the same as it was
  3913. # before.
  3914. raise ValueError("q must be a scalar or 1d")
  3915. if overwrite_input:
  3916. if axis is None:
  3917. axis = 0
  3918. arr = a.ravel()
  3919. wgt = None if weights is None else weights.ravel()
  3920. else:
  3921. arr = a
  3922. wgt = weights
  3923. else:
  3924. if axis is None:
  3925. axis = 0
  3926. arr = a.flatten()
  3927. wgt = None if weights is None else weights.flatten()
  3928. else:
  3929. arr = a.copy()
  3930. wgt = weights
  3931. result = _quantile(arr,
  3932. quantiles=q,
  3933. axis=axis,
  3934. method=method,
  3935. out=out,
  3936. weights=wgt)
  3937. return result
  3938. def _get_indexes(arr, virtual_indexes, valid_values_count):
  3939. """
  3940. Get the valid indexes of arr neighbouring virtual_indexes.
  3941. Note
  3942. This is a companion function to linear interpolation of
  3943. Quantiles
  3944. Returns
  3945. -------
  3946. (previous_indexes, next_indexes): Tuple
  3947. A Tuple of virtual_indexes neighbouring indexes
  3948. """
  3949. previous_indexes = np.asanyarray(np.floor(virtual_indexes))
  3950. next_indexes = np.asanyarray(previous_indexes + 1)
  3951. indexes_above_bounds = virtual_indexes >= valid_values_count - 1
  3952. # When indexes is above max index, take the max value of the array
  3953. if indexes_above_bounds.any():
  3954. previous_indexes[indexes_above_bounds] = -1
  3955. next_indexes[indexes_above_bounds] = -1
  3956. # When indexes is below min index, take the min value of the array
  3957. indexes_below_bounds = virtual_indexes < 0
  3958. if indexes_below_bounds.any():
  3959. previous_indexes[indexes_below_bounds] = 0
  3960. next_indexes[indexes_below_bounds] = 0
  3961. if np.issubdtype(arr.dtype, np.inexact):
  3962. # After the sort, slices having NaNs will have for last element a NaN
  3963. virtual_indexes_nans = np.isnan(virtual_indexes)
  3964. if virtual_indexes_nans.any():
  3965. previous_indexes[virtual_indexes_nans] = -1
  3966. next_indexes[virtual_indexes_nans] = -1
  3967. previous_indexes = previous_indexes.astype(np.intp)
  3968. next_indexes = next_indexes.astype(np.intp)
  3969. return previous_indexes, next_indexes
  3970. def _quantile(
  3971. arr: np.array,
  3972. quantiles: np.array,
  3973. axis: int = -1,
  3974. method="linear",
  3975. out=None,
  3976. weights=None,
  3977. ):
  3978. """
  3979. Private function that doesn't support extended axis or keepdims.
  3980. These methods are extended to this function using _ureduce
  3981. See nanpercentile for parameter usage
  3982. It computes the quantiles of the array for the given axis.
  3983. A linear interpolation is performed based on the `interpolation`.
  3984. By default, the method is "linear" where alpha == beta == 1 which
  3985. performs the 7th method of Hyndman&Fan.
  3986. With "median_unbiased" we get alpha == beta == 1/3
  3987. thus the 8th method of Hyndman&Fan.
  3988. """
  3989. # --- Setup
  3990. arr = np.asanyarray(arr)
  3991. values_count = arr.shape[axis]
  3992. # The dimensions of `q` are prepended to the output shape, so we need the
  3993. # axis being sampled from `arr` to be last.
  3994. if axis != 0: # But moveaxis is slow, so only call it if necessary.
  3995. arr = np.moveaxis(arr, axis, destination=0)
  3996. supports_nans = (
  3997. np.issubdtype(arr.dtype, np.inexact) or arr.dtype.kind in 'Mm'
  3998. )
  3999. if weights is None:
  4000. # --- Computation of indexes
  4001. # Index where to find the value in the sorted array.
  4002. # Virtual because it is a floating point value, not an valid index.
  4003. # The nearest neighbours are used for interpolation
  4004. try:
  4005. method_props = _QuantileMethods[method]
  4006. except KeyError:
  4007. raise ValueError(
  4008. f"{method!r} is not a valid method. Use one of: "
  4009. f"{_QuantileMethods.keys()}") from None
  4010. virtual_indexes = method_props["get_virtual_index"](values_count,
  4011. quantiles)
  4012. virtual_indexes = np.asanyarray(virtual_indexes)
  4013. if method_props["fix_gamma"] is None:
  4014. supports_integers = True
  4015. else:
  4016. int_virtual_indices = np.issubdtype(virtual_indexes.dtype,
  4017. np.integer)
  4018. supports_integers = method == 'linear' and int_virtual_indices
  4019. if supports_integers:
  4020. # No interpolation needed, take the points along axis
  4021. if supports_nans:
  4022. # may contain nan, which would sort to the end
  4023. arr.partition(
  4024. concatenate((virtual_indexes.ravel(), [-1])), axis=0,
  4025. )
  4026. slices_having_nans = np.isnan(arr[-1, ...])
  4027. else:
  4028. # cannot contain nan
  4029. arr.partition(virtual_indexes.ravel(), axis=0)
  4030. slices_having_nans = np.array(False, dtype=bool)
  4031. result = take(arr, virtual_indexes, axis=0, out=out)
  4032. else:
  4033. previous_indexes, next_indexes = _get_indexes(arr,
  4034. virtual_indexes,
  4035. values_count)
  4036. # --- Sorting
  4037. arr.partition(
  4038. np.unique(np.concatenate(([0, -1],
  4039. previous_indexes.ravel(),
  4040. next_indexes.ravel(),
  4041. ))),
  4042. axis=0)
  4043. if supports_nans:
  4044. slices_having_nans = np.isnan(arr[-1, ...])
  4045. else:
  4046. slices_having_nans = None
  4047. # --- Get values from indexes
  4048. previous = arr[previous_indexes]
  4049. next = arr[next_indexes]
  4050. # --- Linear interpolation
  4051. gamma = _get_gamma(virtual_indexes, previous_indexes, method_props)
  4052. result_shape = virtual_indexes.shape + (1,) * (arr.ndim - 1)
  4053. gamma = gamma.reshape(result_shape)
  4054. result = _lerp(previous,
  4055. next,
  4056. gamma,
  4057. out=out)
  4058. else:
  4059. # Weighted case
  4060. # This implements method="inverted_cdf", the only supported weighted
  4061. # method, which needs to sort anyway.
  4062. weights = np.asanyarray(weights)
  4063. if axis != 0:
  4064. weights = np.moveaxis(weights, axis, destination=0)
  4065. index_array = np.argsort(arr, axis=0, kind="stable")
  4066. # arr = arr[index_array, ...] # but this adds trailing dimensions of
  4067. # 1.
  4068. arr = np.take_along_axis(arr, index_array, axis=0)
  4069. if weights.shape == arr.shape:
  4070. weights = np.take_along_axis(weights, index_array, axis=0)
  4071. else:
  4072. # weights is 1d
  4073. weights = weights.reshape(-1)[index_array, ...]
  4074. if supports_nans:
  4075. # may contain nan, which would sort to the end
  4076. slices_having_nans = np.isnan(arr[-1, ...])
  4077. else:
  4078. # cannot contain nan
  4079. slices_having_nans = np.array(False, dtype=bool)
  4080. # We use the weights to calculate the empirical cumulative
  4081. # distribution function cdf
  4082. cdf = weights.cumsum(axis=0, dtype=np.float64)
  4083. cdf /= cdf[-1, ...] # normalization to 1
  4084. # Search index i such that
  4085. # sum(weights[j], j=0..i-1) < quantile <= sum(weights[j], j=0..i)
  4086. # is then equivalent to
  4087. # cdf[i-1] < quantile <= cdf[i]
  4088. # Unfortunately, searchsorted only accepts 1-d arrays as first
  4089. # argument, so we will need to iterate over dimensions.
  4090. # Without the following cast, searchsorted can return surprising
  4091. # results, e.g.
  4092. # np.searchsorted(np.array([0.2, 0.4, 0.6, 0.8, 1.]),
  4093. # np.array(0.4, dtype=np.float32), side="left")
  4094. # returns 2 instead of 1 because 0.4 is not binary representable.
  4095. if quantiles.dtype.kind == "f":
  4096. cdf = cdf.astype(quantiles.dtype)
  4097. # Weights must be non-negative, so we might have zero weights at the
  4098. # beginning leading to some leading zeros in cdf. The call to
  4099. # np.searchsorted for quantiles=0 will then pick the first element,
  4100. # but should pick the first one larger than zero. We
  4101. # therefore simply set 0 values in cdf to -1.
  4102. if np.any(cdf[0, ...] == 0):
  4103. cdf[cdf == 0] = -1
  4104. def find_cdf_1d(arr, cdf):
  4105. indices = np.searchsorted(cdf, quantiles, side="left")
  4106. # We might have reached the maximum with i = len(arr), e.g. for
  4107. # quantiles = 1, and need to cut it to len(arr) - 1.
  4108. indices = minimum(indices, values_count - 1)
  4109. result = take(arr, indices, axis=0)
  4110. return result
  4111. r_shape = arr.shape[1:]
  4112. if quantiles.ndim > 0:
  4113. r_shape = quantiles.shape + r_shape
  4114. if out is None:
  4115. result = np.empty_like(arr, shape=r_shape)
  4116. else:
  4117. if out.shape != r_shape:
  4118. msg = (f"Wrong shape of argument 'out', shape={r_shape} is "
  4119. f"required; got shape={out.shape}.")
  4120. raise ValueError(msg)
  4121. result = out
  4122. # See apply_along_axis, which we do for axis=0. Note that Ni = (,)
  4123. # always, so we remove it here.
  4124. Nk = arr.shape[1:]
  4125. for kk in np.ndindex(Nk):
  4126. result[(...,) + kk] = find_cdf_1d(
  4127. arr[np.s_[:, ] + kk], cdf[np.s_[:, ] + kk]
  4128. )
  4129. # Make result the same as in unweighted inverted_cdf.
  4130. if result.shape == () and result.dtype == np.dtype("O"):
  4131. result = result.item()
  4132. if np.any(slices_having_nans):
  4133. if result.ndim == 0 and out is None:
  4134. # can't write to a scalar, but indexing will be correct
  4135. result = arr[-1]
  4136. else:
  4137. np.copyto(result, arr[-1, ...], where=slices_having_nans)
  4138. return result
  4139. def _trapezoid_dispatcher(y, x=None, dx=None, axis=None):
  4140. return (y, x)
  4141. @array_function_dispatch(_trapezoid_dispatcher)
  4142. def trapezoid(y, x=None, dx=1.0, axis=-1):
  4143. r"""
  4144. Integrate along the given axis using the composite trapezoidal rule.
  4145. If `x` is provided, the integration happens in sequence along its
  4146. elements - they are not sorted.
  4147. Integrate `y` (`x`) along each 1d slice on the given axis, compute
  4148. :math:`\int y(x) dx`.
  4149. When `x` is specified, this integrates along the parametric curve,
  4150. computing :math:`\int_t y(t) dt =
  4151. \int_t y(t) \left.\frac{dx}{dt}\right|_{x=x(t)} dt`.
  4152. .. versionadded:: 2.0.0
  4153. Parameters
  4154. ----------
  4155. y : array_like
  4156. Input array to integrate.
  4157. x : array_like, optional
  4158. The sample points corresponding to the `y` values. If `x` is None,
  4159. the sample points are assumed to be evenly spaced `dx` apart. The
  4160. default is None.
  4161. dx : scalar, optional
  4162. The spacing between sample points when `x` is None. The default is 1.
  4163. axis : int, optional
  4164. The axis along which to integrate.
  4165. Returns
  4166. -------
  4167. trapezoid : float or ndarray
  4168. Definite integral of `y` = n-dimensional array as approximated along
  4169. a single axis by the trapezoidal rule. If `y` is a 1-dimensional array,
  4170. then the result is a float. If `n` is greater than 1, then the result
  4171. is an `n`-1 dimensional array.
  4172. See Also
  4173. --------
  4174. sum, cumsum
  4175. Notes
  4176. -----
  4177. Image [2]_ illustrates trapezoidal rule -- y-axis locations of points
  4178. will be taken from `y` array, by default x-axis distances between
  4179. points will be 1.0, alternatively they can be provided with `x` array
  4180. or with `dx` scalar. Return value will be equal to combined area under
  4181. the red lines.
  4182. References
  4183. ----------
  4184. .. [1] Wikipedia page: https://en.wikipedia.org/wiki/Trapezoidal_rule
  4185. .. [2] Illustration image:
  4186. https://en.wikipedia.org/wiki/File:Composite_trapezoidal_rule_illustration.png
  4187. Examples
  4188. --------
  4189. >>> import numpy as np
  4190. Use the trapezoidal rule on evenly spaced points:
  4191. >>> np.trapezoid([1, 2, 3])
  4192. 4.0
  4193. The spacing between sample points can be selected by either the
  4194. ``x`` or ``dx`` arguments:
  4195. >>> np.trapezoid([1, 2, 3], x=[4, 6, 8])
  4196. 8.0
  4197. >>> np.trapezoid([1, 2, 3], dx=2)
  4198. 8.0
  4199. Using a decreasing ``x`` corresponds to integrating in reverse:
  4200. >>> np.trapezoid([1, 2, 3], x=[8, 6, 4])
  4201. -8.0
  4202. More generally ``x`` is used to integrate along a parametric curve. We can
  4203. estimate the integral :math:`\int_0^1 x^2 = 1/3` using:
  4204. >>> x = np.linspace(0, 1, num=50)
  4205. >>> y = x**2
  4206. >>> np.trapezoid(y, x)
  4207. 0.33340274885464394
  4208. Or estimate the area of a circle, noting we repeat the sample which closes
  4209. the curve:
  4210. >>> theta = np.linspace(0, 2 * np.pi, num=1000, endpoint=True)
  4211. >>> np.trapezoid(np.cos(theta), x=np.sin(theta))
  4212. 3.141571941375841
  4213. ``np.trapezoid`` can be applied along a specified axis to do multiple
  4214. computations in one call:
  4215. >>> a = np.arange(6).reshape(2, 3)
  4216. >>> a
  4217. array([[0, 1, 2],
  4218. [3, 4, 5]])
  4219. >>> np.trapezoid(a, axis=0)
  4220. array([1.5, 2.5, 3.5])
  4221. >>> np.trapezoid(a, axis=1)
  4222. array([2., 8.])
  4223. """
  4224. y = asanyarray(y)
  4225. if x is None:
  4226. d = dx
  4227. else:
  4228. x = asanyarray(x)
  4229. if x.ndim == 1:
  4230. d = diff(x)
  4231. # reshape to correct shape
  4232. shape = [1]*y.ndim
  4233. shape[axis] = d.shape[0]
  4234. d = d.reshape(shape)
  4235. else:
  4236. d = diff(x, axis=axis)
  4237. nd = y.ndim
  4238. slice1 = [slice(None)]*nd
  4239. slice2 = [slice(None)]*nd
  4240. slice1[axis] = slice(1, None)
  4241. slice2[axis] = slice(None, -1)
  4242. try:
  4243. ret = (d * (y[tuple(slice1)] + y[tuple(slice2)]) / 2.0).sum(axis)
  4244. except ValueError:
  4245. # Operations didn't work, cast to ndarray
  4246. d = np.asarray(d)
  4247. y = np.asarray(y)
  4248. ret = add.reduce(d * (y[tuple(slice1)]+y[tuple(slice2)])/2.0, axis)
  4249. return ret
  4250. @set_module('numpy')
  4251. def trapz(y, x=None, dx=1.0, axis=-1):
  4252. """
  4253. `trapz` is deprecated in NumPy 2.0.
  4254. Please use `trapezoid` instead, or one of the numerical integration
  4255. functions in `scipy.integrate`.
  4256. """
  4257. # Deprecated in NumPy 2.0, 2023-08-18
  4258. warnings.warn(
  4259. "`trapz` is deprecated. Use `trapezoid` instead, or one of the "
  4260. "numerical integration functions in `scipy.integrate`.",
  4261. DeprecationWarning,
  4262. stacklevel=2
  4263. )
  4264. return trapezoid(y, x=x, dx=dx, axis=axis)
  4265. def _meshgrid_dispatcher(*xi, copy=None, sparse=None, indexing=None):
  4266. return xi
  4267. # Based on scitools meshgrid
  4268. @array_function_dispatch(_meshgrid_dispatcher)
  4269. def meshgrid(*xi, copy=True, sparse=False, indexing='xy'):
  4270. """
  4271. Return a tuple of coordinate matrices from coordinate vectors.
  4272. Make N-D coordinate arrays for vectorized evaluations of
  4273. N-D scalar/vector fields over N-D grids, given
  4274. one-dimensional coordinate arrays x1, x2,..., xn.
  4275. Parameters
  4276. ----------
  4277. x1, x2,..., xn : array_like
  4278. 1-D arrays representing the coordinates of a grid.
  4279. indexing : {'xy', 'ij'}, optional
  4280. Cartesian ('xy', default) or matrix ('ij') indexing of output.
  4281. See Notes for more details.
  4282. sparse : bool, optional
  4283. If True the shape of the returned coordinate array for dimension *i*
  4284. is reduced from ``(N1, ..., Ni, ... Nn)`` to
  4285. ``(1, ..., 1, Ni, 1, ..., 1)``. These sparse coordinate grids are
  4286. intended to be use with :ref:`basics.broadcasting`. When all
  4287. coordinates are used in an expression, broadcasting still leads to a
  4288. fully-dimensonal result array.
  4289. Default is False.
  4290. copy : bool, optional
  4291. If False, a view into the original arrays are returned in order to
  4292. conserve memory. Default is True. Please note that
  4293. ``sparse=False, copy=False`` will likely return non-contiguous
  4294. arrays. Furthermore, more than one element of a broadcast array
  4295. may refer to a single memory location. If you need to write to the
  4296. arrays, make copies first.
  4297. Returns
  4298. -------
  4299. X1, X2,..., XN : tuple of ndarrays
  4300. For vectors `x1`, `x2`,..., `xn` with lengths ``Ni=len(xi)``,
  4301. returns ``(N1, N2, N3,..., Nn)`` shaped arrays if indexing='ij'
  4302. or ``(N2, N1, N3,..., Nn)`` shaped arrays if indexing='xy'
  4303. with the elements of `xi` repeated to fill the matrix along
  4304. the first dimension for `x1`, the second for `x2` and so on.
  4305. Notes
  4306. -----
  4307. This function supports both indexing conventions through the indexing
  4308. keyword argument. Giving the string 'ij' returns a meshgrid with
  4309. matrix indexing, while 'xy' returns a meshgrid with Cartesian indexing.
  4310. In the 2-D case with inputs of length M and N, the outputs are of shape
  4311. (N, M) for 'xy' indexing and (M, N) for 'ij' indexing. In the 3-D case
  4312. with inputs of length M, N and P, outputs are of shape (N, M, P) for
  4313. 'xy' indexing and (M, N, P) for 'ij' indexing. The difference is
  4314. illustrated by the following code snippet::
  4315. xv, yv = np.meshgrid(x, y, indexing='ij')
  4316. for i in range(nx):
  4317. for j in range(ny):
  4318. # treat xv[i,j], yv[i,j]
  4319. xv, yv = np.meshgrid(x, y, indexing='xy')
  4320. for i in range(nx):
  4321. for j in range(ny):
  4322. # treat xv[j,i], yv[j,i]
  4323. In the 1-D and 0-D case, the indexing and sparse keywords have no effect.
  4324. See Also
  4325. --------
  4326. mgrid : Construct a multi-dimensional "meshgrid" using indexing notation.
  4327. ogrid : Construct an open multi-dimensional "meshgrid" using indexing
  4328. notation.
  4329. :ref:`how-to-index`
  4330. Examples
  4331. --------
  4332. >>> import numpy as np
  4333. >>> nx, ny = (3, 2)
  4334. >>> x = np.linspace(0, 1, nx)
  4335. >>> y = np.linspace(0, 1, ny)
  4336. >>> xv, yv = np.meshgrid(x, y)
  4337. >>> xv
  4338. array([[0. , 0.5, 1. ],
  4339. [0. , 0.5, 1. ]])
  4340. >>> yv
  4341. array([[0., 0., 0.],
  4342. [1., 1., 1.]])
  4343. The result of `meshgrid` is a coordinate grid:
  4344. >>> import matplotlib.pyplot as plt
  4345. >>> plt.plot(xv, yv, marker='o', color='k', linestyle='none')
  4346. >>> plt.show()
  4347. You can create sparse output arrays to save memory and computation time.
  4348. >>> xv, yv = np.meshgrid(x, y, sparse=True)
  4349. >>> xv
  4350. array([[0. , 0.5, 1. ]])
  4351. >>> yv
  4352. array([[0.],
  4353. [1.]])
  4354. `meshgrid` is very useful to evaluate functions on a grid. If the
  4355. function depends on all coordinates, both dense and sparse outputs can be
  4356. used.
  4357. >>> x = np.linspace(-5, 5, 101)
  4358. >>> y = np.linspace(-5, 5, 101)
  4359. >>> # full coordinate arrays
  4360. >>> xx, yy = np.meshgrid(x, y)
  4361. >>> zz = np.sqrt(xx**2 + yy**2)
  4362. >>> xx.shape, yy.shape, zz.shape
  4363. ((101, 101), (101, 101), (101, 101))
  4364. >>> # sparse coordinate arrays
  4365. >>> xs, ys = np.meshgrid(x, y, sparse=True)
  4366. >>> zs = np.sqrt(xs**2 + ys**2)
  4367. >>> xs.shape, ys.shape, zs.shape
  4368. ((1, 101), (101, 1), (101, 101))
  4369. >>> np.array_equal(zz, zs)
  4370. True
  4371. >>> h = plt.contourf(x, y, zs)
  4372. >>> plt.axis('scaled')
  4373. >>> plt.colorbar()
  4374. >>> plt.show()
  4375. """
  4376. ndim = len(xi)
  4377. if indexing not in ['xy', 'ij']:
  4378. raise ValueError(
  4379. "Valid values for `indexing` are 'xy' and 'ij'.")
  4380. s0 = (1,) * ndim
  4381. output = [np.asanyarray(x).reshape(s0[:i] + (-1,) + s0[i + 1:])
  4382. for i, x in enumerate(xi)]
  4383. if indexing == 'xy' and ndim > 1:
  4384. # switch first and second axis
  4385. output[0].shape = (1, -1) + s0[2:]
  4386. output[1].shape = (-1, 1) + s0[2:]
  4387. if not sparse:
  4388. # Return the full N-D matrix (not only the 1-D vector)
  4389. output = np.broadcast_arrays(*output, subok=True)
  4390. if copy:
  4391. output = tuple(x.copy() for x in output)
  4392. return output
  4393. def _delete_dispatcher(arr, obj, axis=None):
  4394. return (arr, obj)
  4395. @array_function_dispatch(_delete_dispatcher)
  4396. def delete(arr, obj, axis=None):
  4397. """
  4398. Return a new array with sub-arrays along an axis deleted. For a one
  4399. dimensional array, this returns those entries not returned by
  4400. `arr[obj]`.
  4401. Parameters
  4402. ----------
  4403. arr : array_like
  4404. Input array.
  4405. obj : slice, int, array-like of ints or bools
  4406. Indicate indices of sub-arrays to remove along the specified axis.
  4407. .. versionchanged:: 1.19.0
  4408. Boolean indices are now treated as a mask of elements to remove,
  4409. rather than being cast to the integers 0 and 1.
  4410. axis : int, optional
  4411. The axis along which to delete the subarray defined by `obj`.
  4412. If `axis` is None, `obj` is applied to the flattened array.
  4413. Returns
  4414. -------
  4415. out : ndarray
  4416. A copy of `arr` with the elements specified by `obj` removed. Note
  4417. that `delete` does not occur in-place. If `axis` is None, `out` is
  4418. a flattened array.
  4419. See Also
  4420. --------
  4421. insert : Insert elements into an array.
  4422. append : Append elements at the end of an array.
  4423. Notes
  4424. -----
  4425. Often it is preferable to use a boolean mask. For example:
  4426. >>> arr = np.arange(12) + 1
  4427. >>> mask = np.ones(len(arr), dtype=bool)
  4428. >>> mask[[0,2,4]] = False
  4429. >>> result = arr[mask,...]
  4430. Is equivalent to ``np.delete(arr, [0,2,4], axis=0)``, but allows further
  4431. use of `mask`.
  4432. Examples
  4433. --------
  4434. >>> import numpy as np
  4435. >>> arr = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
  4436. >>> arr
  4437. array([[ 1, 2, 3, 4],
  4438. [ 5, 6, 7, 8],
  4439. [ 9, 10, 11, 12]])
  4440. >>> np.delete(arr, 1, 0)
  4441. array([[ 1, 2, 3, 4],
  4442. [ 9, 10, 11, 12]])
  4443. >>> np.delete(arr, np.s_[::2], 1)
  4444. array([[ 2, 4],
  4445. [ 6, 8],
  4446. [10, 12]])
  4447. >>> np.delete(arr, [1,3,5], None)
  4448. array([ 1, 3, 5, 7, 8, 9, 10, 11, 12])
  4449. """
  4450. conv = _array_converter(arr)
  4451. arr, = conv.as_arrays(subok=False)
  4452. ndim = arr.ndim
  4453. arrorder = 'F' if arr.flags.fnc else 'C'
  4454. if axis is None:
  4455. if ndim != 1:
  4456. arr = arr.ravel()
  4457. # needed for np.matrix, which is still not 1d after being ravelled
  4458. ndim = arr.ndim
  4459. axis = ndim - 1
  4460. else:
  4461. axis = normalize_axis_index(axis, ndim)
  4462. slobj = [slice(None)]*ndim
  4463. N = arr.shape[axis]
  4464. newshape = list(arr.shape)
  4465. if isinstance(obj, slice):
  4466. start, stop, step = obj.indices(N)
  4467. xr = range(start, stop, step)
  4468. numtodel = len(xr)
  4469. if numtodel <= 0:
  4470. return conv.wrap(arr.copy(order=arrorder), to_scalar=False)
  4471. # Invert if step is negative:
  4472. if step < 0:
  4473. step = -step
  4474. start = xr[-1]
  4475. stop = xr[0] + 1
  4476. newshape[axis] -= numtodel
  4477. new = empty(newshape, arr.dtype, arrorder)
  4478. # copy initial chunk
  4479. if start == 0:
  4480. pass
  4481. else:
  4482. slobj[axis] = slice(None, start)
  4483. new[tuple(slobj)] = arr[tuple(slobj)]
  4484. # copy end chunk
  4485. if stop == N:
  4486. pass
  4487. else:
  4488. slobj[axis] = slice(stop-numtodel, None)
  4489. slobj2 = [slice(None)]*ndim
  4490. slobj2[axis] = slice(stop, None)
  4491. new[tuple(slobj)] = arr[tuple(slobj2)]
  4492. # copy middle pieces
  4493. if step == 1:
  4494. pass
  4495. else: # use array indexing.
  4496. keep = ones(stop-start, dtype=bool)
  4497. keep[:stop-start:step] = False
  4498. slobj[axis] = slice(start, stop-numtodel)
  4499. slobj2 = [slice(None)]*ndim
  4500. slobj2[axis] = slice(start, stop)
  4501. arr = arr[tuple(slobj2)]
  4502. slobj2[axis] = keep
  4503. new[tuple(slobj)] = arr[tuple(slobj2)]
  4504. return conv.wrap(new, to_scalar=False)
  4505. if isinstance(obj, (int, integer)) and not isinstance(obj, bool):
  4506. single_value = True
  4507. else:
  4508. single_value = False
  4509. _obj = obj
  4510. obj = np.asarray(obj)
  4511. # `size == 0` to allow empty lists similar to indexing, but (as there)
  4512. # is really too generic:
  4513. if obj.size == 0 and not isinstance(_obj, np.ndarray):
  4514. obj = obj.astype(intp)
  4515. elif obj.size == 1 and obj.dtype.kind in "ui":
  4516. # For a size 1 integer array we can use the single-value path
  4517. # (most dtypes, except boolean, should just fail later).
  4518. obj = obj.item()
  4519. single_value = True
  4520. if single_value:
  4521. # optimization for a single value
  4522. if (obj < -N or obj >= N):
  4523. raise IndexError(
  4524. "index %i is out of bounds for axis %i with "
  4525. "size %i" % (obj, axis, N))
  4526. if (obj < 0):
  4527. obj += N
  4528. newshape[axis] -= 1
  4529. new = empty(newshape, arr.dtype, arrorder)
  4530. slobj[axis] = slice(None, obj)
  4531. new[tuple(slobj)] = arr[tuple(slobj)]
  4532. slobj[axis] = slice(obj, None)
  4533. slobj2 = [slice(None)]*ndim
  4534. slobj2[axis] = slice(obj+1, None)
  4535. new[tuple(slobj)] = arr[tuple(slobj2)]
  4536. else:
  4537. if obj.dtype == bool:
  4538. if obj.shape != (N,):
  4539. raise ValueError('boolean array argument obj to delete '
  4540. 'must be one dimensional and match the axis '
  4541. 'length of {}'.format(N))
  4542. # optimization, the other branch is slower
  4543. keep = ~obj
  4544. else:
  4545. keep = ones(N, dtype=bool)
  4546. keep[obj,] = False
  4547. slobj[axis] = keep
  4548. new = arr[tuple(slobj)]
  4549. return conv.wrap(new, to_scalar=False)
  4550. def _insert_dispatcher(arr, obj, values, axis=None):
  4551. return (arr, obj, values)
  4552. @array_function_dispatch(_insert_dispatcher)
  4553. def insert(arr, obj, values, axis=None):
  4554. """
  4555. Insert values along the given axis before the given indices.
  4556. Parameters
  4557. ----------
  4558. arr : array_like
  4559. Input array.
  4560. obj : slice, int, array-like of ints or bools
  4561. Object that defines the index or indices before which `values` is
  4562. inserted.
  4563. .. versionchanged:: 2.1.2
  4564. Boolean indices are now treated as a mask of elements to insert,
  4565. rather than being cast to the integers 0 and 1.
  4566. Support for multiple insertions when `obj` is a single scalar or a
  4567. sequence with one element (similar to calling insert multiple
  4568. times).
  4569. values : array_like
  4570. Values to insert into `arr`. If the type of `values` is different
  4571. from that of `arr`, `values` is converted to the type of `arr`.
  4572. `values` should be shaped so that ``arr[...,obj,...] = values``
  4573. is legal.
  4574. axis : int, optional
  4575. Axis along which to insert `values`. If `axis` is None then `arr`
  4576. is flattened first.
  4577. Returns
  4578. -------
  4579. out : ndarray
  4580. A copy of `arr` with `values` inserted. Note that `insert`
  4581. does not occur in-place: a new array is returned. If
  4582. `axis` is None, `out` is a flattened array.
  4583. See Also
  4584. --------
  4585. append : Append elements at the end of an array.
  4586. concatenate : Join a sequence of arrays along an existing axis.
  4587. delete : Delete elements from an array.
  4588. Notes
  4589. -----
  4590. Note that for higher dimensional inserts ``obj=0`` behaves very different
  4591. from ``obj=[0]`` just like ``arr[:,0,:] = values`` is different from
  4592. ``arr[:,[0],:] = values``. This is because of the difference between basic
  4593. and advanced :ref:`indexing <basics.indexing>`.
  4594. Examples
  4595. --------
  4596. >>> import numpy as np
  4597. >>> a = np.arange(6).reshape(3, 2)
  4598. >>> a
  4599. array([[0, 1],
  4600. [2, 3],
  4601. [4, 5]])
  4602. >>> np.insert(a, 1, 6)
  4603. array([0, 6, 1, 2, 3, 4, 5])
  4604. >>> np.insert(a, 1, 6, axis=1)
  4605. array([[0, 6, 1],
  4606. [2, 6, 3],
  4607. [4, 6, 5]])
  4608. Difference between sequence and scalars,
  4609. showing how ``obj=[1]`` behaves different from ``obj=1``:
  4610. >>> np.insert(a, [1], [[7],[8],[9]], axis=1)
  4611. array([[0, 7, 1],
  4612. [2, 8, 3],
  4613. [4, 9, 5]])
  4614. >>> np.insert(a, 1, [[7],[8],[9]], axis=1)
  4615. array([[0, 7, 8, 9, 1],
  4616. [2, 7, 8, 9, 3],
  4617. [4, 7, 8, 9, 5]])
  4618. >>> np.array_equal(np.insert(a, 1, [7, 8, 9], axis=1),
  4619. ... np.insert(a, [1], [[7],[8],[9]], axis=1))
  4620. True
  4621. >>> b = a.flatten()
  4622. >>> b
  4623. array([0, 1, 2, 3, 4, 5])
  4624. >>> np.insert(b, [2, 2], [6, 7])
  4625. array([0, 1, 6, 7, 2, 3, 4, 5])
  4626. >>> np.insert(b, slice(2, 4), [7, 8])
  4627. array([0, 1, 7, 2, 8, 3, 4, 5])
  4628. >>> np.insert(b, [2, 2], [7.13, False]) # type casting
  4629. array([0, 1, 7, 0, 2, 3, 4, 5])
  4630. >>> x = np.arange(8).reshape(2, 4)
  4631. >>> idx = (1, 3)
  4632. >>> np.insert(x, idx, 999, axis=1)
  4633. array([[ 0, 999, 1, 2, 999, 3],
  4634. [ 4, 999, 5, 6, 999, 7]])
  4635. """
  4636. conv = _array_converter(arr)
  4637. arr, = conv.as_arrays(subok=False)
  4638. ndim = arr.ndim
  4639. arrorder = 'F' if arr.flags.fnc else 'C'
  4640. if axis is None:
  4641. if ndim != 1:
  4642. arr = arr.ravel()
  4643. # needed for np.matrix, which is still not 1d after being ravelled
  4644. ndim = arr.ndim
  4645. axis = ndim - 1
  4646. else:
  4647. axis = normalize_axis_index(axis, ndim)
  4648. slobj = [slice(None)]*ndim
  4649. N = arr.shape[axis]
  4650. newshape = list(arr.shape)
  4651. if isinstance(obj, slice):
  4652. # turn it into a range object
  4653. indices = arange(*obj.indices(N), dtype=intp)
  4654. else:
  4655. # need to copy obj, because indices will be changed in-place
  4656. indices = np.array(obj)
  4657. if indices.dtype == bool:
  4658. if obj.ndim != 1:
  4659. raise ValueError('boolean array argument obj to insert '
  4660. 'must be one dimensional')
  4661. indices = np.flatnonzero(obj)
  4662. elif indices.ndim > 1:
  4663. raise ValueError(
  4664. "index array argument obj to insert must be one dimensional "
  4665. "or scalar")
  4666. if indices.size == 1:
  4667. index = indices.item()
  4668. if index < -N or index > N:
  4669. raise IndexError(f"index {obj} is out of bounds for axis {axis} "
  4670. f"with size {N}")
  4671. if (index < 0):
  4672. index += N
  4673. # There are some object array corner cases here, but we cannot avoid
  4674. # that:
  4675. values = array(values, copy=None, ndmin=arr.ndim, dtype=arr.dtype)
  4676. if indices.ndim == 0:
  4677. # broadcasting is very different here, since a[:,0,:] = ... behaves
  4678. # very different from a[:,[0],:] = ...! This changes values so that
  4679. # it works likes the second case. (here a[:,0:1,:])
  4680. values = np.moveaxis(values, 0, axis)
  4681. numnew = values.shape[axis]
  4682. newshape[axis] += numnew
  4683. new = empty(newshape, arr.dtype, arrorder)
  4684. slobj[axis] = slice(None, index)
  4685. new[tuple(slobj)] = arr[tuple(slobj)]
  4686. slobj[axis] = slice(index, index+numnew)
  4687. new[tuple(slobj)] = values
  4688. slobj[axis] = slice(index+numnew, None)
  4689. slobj2 = [slice(None)] * ndim
  4690. slobj2[axis] = slice(index, None)
  4691. new[tuple(slobj)] = arr[tuple(slobj2)]
  4692. return conv.wrap(new, to_scalar=False)
  4693. elif indices.size == 0 and not isinstance(obj, np.ndarray):
  4694. # Can safely cast the empty list to intp
  4695. indices = indices.astype(intp)
  4696. indices[indices < 0] += N
  4697. numnew = len(indices)
  4698. order = indices.argsort(kind='mergesort') # stable sort
  4699. indices[order] += np.arange(numnew)
  4700. newshape[axis] += numnew
  4701. old_mask = ones(newshape[axis], dtype=bool)
  4702. old_mask[indices] = False
  4703. new = empty(newshape, arr.dtype, arrorder)
  4704. slobj2 = [slice(None)]*ndim
  4705. slobj[axis] = indices
  4706. slobj2[axis] = old_mask
  4707. new[tuple(slobj)] = values
  4708. new[tuple(slobj2)] = arr
  4709. return conv.wrap(new, to_scalar=False)
  4710. def _append_dispatcher(arr, values, axis=None):
  4711. return (arr, values)
  4712. @array_function_dispatch(_append_dispatcher)
  4713. def append(arr, values, axis=None):
  4714. """
  4715. Append values to the end of an array.
  4716. Parameters
  4717. ----------
  4718. arr : array_like
  4719. Values are appended to a copy of this array.
  4720. values : array_like
  4721. These values are appended to a copy of `arr`. It must be of the
  4722. correct shape (the same shape as `arr`, excluding `axis`). If
  4723. `axis` is not specified, `values` can be any shape and will be
  4724. flattened before use.
  4725. axis : int, optional
  4726. The axis along which `values` are appended. If `axis` is not
  4727. given, both `arr` and `values` are flattened before use.
  4728. Returns
  4729. -------
  4730. append : ndarray
  4731. A copy of `arr` with `values` appended to `axis`. Note that
  4732. `append` does not occur in-place: a new array is allocated and
  4733. filled. If `axis` is None, `out` is a flattened array.
  4734. See Also
  4735. --------
  4736. insert : Insert elements into an array.
  4737. delete : Delete elements from an array.
  4738. Examples
  4739. --------
  4740. >>> import numpy as np
  4741. >>> np.append([1, 2, 3], [[4, 5, 6], [7, 8, 9]])
  4742. array([1, 2, 3, ..., 7, 8, 9])
  4743. When `axis` is specified, `values` must have the correct shape.
  4744. >>> np.append([[1, 2, 3], [4, 5, 6]], [[7, 8, 9]], axis=0)
  4745. array([[1, 2, 3],
  4746. [4, 5, 6],
  4747. [7, 8, 9]])
  4748. >>> np.append([[1, 2, 3], [4, 5, 6]], [7, 8, 9], axis=0)
  4749. Traceback (most recent call last):
  4750. ...
  4751. ValueError: all the input arrays must have same number of dimensions, but
  4752. the array at index 0 has 2 dimension(s) and the array at index 1 has 1
  4753. dimension(s)
  4754. >>> a = np.array([1, 2], dtype=int)
  4755. >>> c = np.append(a, [])
  4756. >>> c
  4757. array([1., 2.])
  4758. >>> c.dtype
  4759. float64
  4760. Default dtype for empty ndarrays is `float64` thus making the output of dtype
  4761. `float64` when appended with dtype `int64`
  4762. """
  4763. arr = asanyarray(arr)
  4764. if axis is None:
  4765. if arr.ndim != 1:
  4766. arr = arr.ravel()
  4767. values = ravel(values)
  4768. axis = arr.ndim-1
  4769. return concatenate((arr, values), axis=axis)
  4770. def _digitize_dispatcher(x, bins, right=None):
  4771. return (x, bins)
  4772. @array_function_dispatch(_digitize_dispatcher)
  4773. def digitize(x, bins, right=False):
  4774. """
  4775. Return the indices of the bins to which each value in input array belongs.
  4776. ========= ============= ============================
  4777. `right` order of bins returned index `i` satisfies
  4778. ========= ============= ============================
  4779. ``False`` increasing ``bins[i-1] <= x < bins[i]``
  4780. ``True`` increasing ``bins[i-1] < x <= bins[i]``
  4781. ``False`` decreasing ``bins[i-1] > x >= bins[i]``
  4782. ``True`` decreasing ``bins[i-1] >= x > bins[i]``
  4783. ========= ============= ============================
  4784. If values in `x` are beyond the bounds of `bins`, 0 or ``len(bins)`` is
  4785. returned as appropriate.
  4786. Parameters
  4787. ----------
  4788. x : array_like
  4789. Input array to be binned. Prior to NumPy 1.10.0, this array had to
  4790. be 1-dimensional, but can now have any shape.
  4791. bins : array_like
  4792. Array of bins. It has to be 1-dimensional and monotonic.
  4793. right : bool, optional
  4794. Indicating whether the intervals include the right or the left bin
  4795. edge. Default behavior is (right==False) indicating that the interval
  4796. does not include the right edge. The left bin end is open in this
  4797. case, i.e., bins[i-1] <= x < bins[i] is the default behavior for
  4798. monotonically increasing bins.
  4799. Returns
  4800. -------
  4801. indices : ndarray of ints
  4802. Output array of indices, of same shape as `x`.
  4803. Raises
  4804. ------
  4805. ValueError
  4806. If `bins` is not monotonic.
  4807. TypeError
  4808. If the type of the input is complex.
  4809. See Also
  4810. --------
  4811. bincount, histogram, unique, searchsorted
  4812. Notes
  4813. -----
  4814. If values in `x` are such that they fall outside the bin range,
  4815. attempting to index `bins` with the indices that `digitize` returns
  4816. will result in an IndexError.
  4817. .. versionadded:: 1.10.0
  4818. `numpy.digitize` is implemented in terms of `numpy.searchsorted`.
  4819. This means that a binary search is used to bin the values, which scales
  4820. much better for larger number of bins than the previous linear search.
  4821. It also removes the requirement for the input array to be 1-dimensional.
  4822. For monotonically *increasing* `bins`, the following are equivalent::
  4823. np.digitize(x, bins, right=True)
  4824. np.searchsorted(bins, x, side='left')
  4825. Note that as the order of the arguments are reversed, the side must be too.
  4826. The `searchsorted` call is marginally faster, as it does not do any
  4827. monotonicity checks. Perhaps more importantly, it supports all dtypes.
  4828. Examples
  4829. --------
  4830. >>> import numpy as np
  4831. >>> x = np.array([0.2, 6.4, 3.0, 1.6])
  4832. >>> bins = np.array([0.0, 1.0, 2.5, 4.0, 10.0])
  4833. >>> inds = np.digitize(x, bins)
  4834. >>> inds
  4835. array([1, 4, 3, 2])
  4836. >>> for n in range(x.size):
  4837. ... print(bins[inds[n]-1], "<=", x[n], "<", bins[inds[n]])
  4838. ...
  4839. 0.0 <= 0.2 < 1.0
  4840. 4.0 <= 6.4 < 10.0
  4841. 2.5 <= 3.0 < 4.0
  4842. 1.0 <= 1.6 < 2.5
  4843. >>> x = np.array([1.2, 10.0, 12.4, 15.5, 20.])
  4844. >>> bins = np.array([0, 5, 10, 15, 20])
  4845. >>> np.digitize(x,bins,right=True)
  4846. array([1, 2, 3, 4, 4])
  4847. >>> np.digitize(x,bins,right=False)
  4848. array([1, 3, 3, 4, 5])
  4849. """
  4850. x = _nx.asarray(x)
  4851. bins = _nx.asarray(bins)
  4852. # here for compatibility, searchsorted below is happy to take this
  4853. if np.issubdtype(x.dtype, _nx.complexfloating):
  4854. raise TypeError("x may not be complex")
  4855. mono = _monotonicity(bins)
  4856. if mono == 0:
  4857. raise ValueError("bins must be monotonically increasing or decreasing")
  4858. # this is backwards because the arguments below are swapped
  4859. side = 'left' if right else 'right'
  4860. if mono == -1:
  4861. # reverse the bins, and invert the results
  4862. return len(bins) - _nx.searchsorted(bins[::-1], x, side=side)
  4863. else:
  4864. return _nx.searchsorted(bins, x, side=side)