You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

numpy_tutorial.ipynb 166 kB

6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858
  1. {
  2. "cells": [
  3. {
  4. "cell_type": "markdown",
  5. "metadata": {},
  6. "source": [
  7. "# Numpy - multidimensional data arrays"
  8. ]
  9. },
  10. {
  11. "cell_type": "markdown",
  12. "metadata": {},
  13. "source": [
  14. "J.R. Johansson (jrjohansson at gmail.com)\n",
  15. "\n",
  16. "The latest version of this [IPython notebook](http://ipython.org/notebook.html) lecture is available at [http://github.com/jrjohansson/scientific-python-lectures](http://github.com/jrjohansson/scientific-python-lectures).\n",
  17. "\n",
  18. "The other notebooks in this lecture series are indexed at [http://jrjohansson.github.io](http://jrjohansson.github.io)."
  19. ]
  20. },
  21. {
  22. "cell_type": "code",
  23. "execution_count": 1,
  24. "metadata": {},
  25. "outputs": [],
  26. "source": [
  27. "# what is this line all about?!? Answer in lecture 4\n",
  28. "%matplotlib inline\n",
  29. "import matplotlib.pyplot as plt"
  30. ]
  31. },
  32. {
  33. "cell_type": "markdown",
  34. "metadata": {},
  35. "source": [
  36. "## Introduction"
  37. ]
  38. },
  39. {
  40. "cell_type": "markdown",
  41. "metadata": {},
  42. "source": [
  43. "The `numpy` package (module) is used in almost all numerical computation using Python. It is a package that provide high-performance vector, matrix and higher-dimensional data structures for Python. It is implemented in C and Fortran so when calculations are vectorized (formulated with vectors and matrices), performance is very good. \n",
  44. "\n",
  45. "To use `numpy` you need to import the module, using for example:"
  46. ]
  47. },
  48. {
  49. "cell_type": "code",
  50. "execution_count": 5,
  51. "metadata": {},
  52. "outputs": [],
  53. "source": [
  54. "from numpy import *"
  55. ]
  56. },
  57. {
  58. "cell_type": "markdown",
  59. "metadata": {},
  60. "source": [
  61. "In the `numpy` package the terminology used for vectors, matrices and higher-dimensional data sets is *array*. \n",
  62. "\n"
  63. ]
  64. },
  65. {
  66. "cell_type": "markdown",
  67. "metadata": {},
  68. "source": [
  69. "## Creating `numpy` arrays"
  70. ]
  71. },
  72. {
  73. "cell_type": "markdown",
  74. "metadata": {},
  75. "source": [
  76. "There are a number of ways to initialize new numpy arrays, for example from\n",
  77. "\n",
  78. "* a Python list or tuples\n",
  79. "* using functions that are dedicated to generating numpy arrays, such as `arange`, `linspace`, etc.\n",
  80. "* reading data from files"
  81. ]
  82. },
  83. {
  84. "cell_type": "markdown",
  85. "metadata": {},
  86. "source": [
  87. "### From lists"
  88. ]
  89. },
  90. {
  91. "cell_type": "markdown",
  92. "metadata": {},
  93. "source": [
  94. "For example, to create new vector and matrix arrays from Python lists we can use the `numpy.array` function."
  95. ]
  96. },
  97. {
  98. "cell_type": "code",
  99. "execution_count": 3,
  100. "metadata": {},
  101. "outputs": [
  102. {
  103. "data": {
  104. "text/plain": [
  105. "array([1, 2, 3, 4])"
  106. ]
  107. },
  108. "execution_count": 3,
  109. "metadata": {},
  110. "output_type": "execute_result"
  111. }
  112. ],
  113. "source": [
  114. "import numpy as np\n",
  115. "\n",
  116. "# a vector: the argument to the array function is a Python list\n",
  117. "v = np.array([1,2,3,4])\n",
  118. "\n",
  119. "v"
  120. ]
  121. },
  122. {
  123. "cell_type": "code",
  124. "execution_count": 10,
  125. "metadata": {},
  126. "outputs": [
  127. {
  128. "name": "stdout",
  129. "output_type": "stream",
  130. "text": [
  131. "[[1 2]\n",
  132. " [3 4]\n",
  133. " [5 6]]\n",
  134. "(3, 2)\n"
  135. ]
  136. }
  137. ],
  138. "source": [
  139. "# a matrix: the argument to the array function is a nested Python list\n",
  140. "M = array([[1, 2], [3, 4], [5, 6]])\n",
  141. "\n",
  142. "print(M)\n",
  143. "print(M.shape)"
  144. ]
  145. },
  146. {
  147. "cell_type": "markdown",
  148. "metadata": {},
  149. "source": [
  150. "The `v` and `M` objects are both of the type `ndarray` that the `numpy` module provides."
  151. ]
  152. },
  153. {
  154. "cell_type": "code",
  155. "execution_count": 11,
  156. "metadata": {},
  157. "outputs": [
  158. {
  159. "data": {
  160. "text/plain": [
  161. "(numpy.ndarray, numpy.ndarray)"
  162. ]
  163. },
  164. "execution_count": 11,
  165. "metadata": {},
  166. "output_type": "execute_result"
  167. }
  168. ],
  169. "source": [
  170. "type(v), type(M)"
  171. ]
  172. },
  173. {
  174. "cell_type": "markdown",
  175. "metadata": {},
  176. "source": [
  177. "The difference between the `v` and `M` arrays is only their shapes. We can get information about the shape of an array by using the `ndarray.shape` property."
  178. ]
  179. },
  180. {
  181. "cell_type": "code",
  182. "execution_count": 12,
  183. "metadata": {},
  184. "outputs": [
  185. {
  186. "data": {
  187. "text/plain": [
  188. "(4,)"
  189. ]
  190. },
  191. "execution_count": 12,
  192. "metadata": {},
  193. "output_type": "execute_result"
  194. }
  195. ],
  196. "source": [
  197. "v.shape"
  198. ]
  199. },
  200. {
  201. "cell_type": "code",
  202. "execution_count": 13,
  203. "metadata": {},
  204. "outputs": [
  205. {
  206. "data": {
  207. "text/plain": [
  208. "(3, 2)"
  209. ]
  210. },
  211. "execution_count": 13,
  212. "metadata": {},
  213. "output_type": "execute_result"
  214. }
  215. ],
  216. "source": [
  217. "M.shape"
  218. ]
  219. },
  220. {
  221. "cell_type": "markdown",
  222. "metadata": {},
  223. "source": [
  224. "The number of elements in the array is available through the `ndarray.size` property:"
  225. ]
  226. },
  227. {
  228. "cell_type": "code",
  229. "execution_count": 14,
  230. "metadata": {},
  231. "outputs": [
  232. {
  233. "data": {
  234. "text/plain": [
  235. "6"
  236. ]
  237. },
  238. "execution_count": 14,
  239. "metadata": {},
  240. "output_type": "execute_result"
  241. }
  242. ],
  243. "source": [
  244. "M.size"
  245. ]
  246. },
  247. {
  248. "cell_type": "markdown",
  249. "metadata": {},
  250. "source": [
  251. "Equivalently, we could use the function `numpy.shape` and `numpy.size`"
  252. ]
  253. },
  254. {
  255. "cell_type": "code",
  256. "execution_count": 15,
  257. "metadata": {},
  258. "outputs": [
  259. {
  260. "data": {
  261. "text/plain": [
  262. "(3, 2)"
  263. ]
  264. },
  265. "execution_count": 15,
  266. "metadata": {},
  267. "output_type": "execute_result"
  268. }
  269. ],
  270. "source": [
  271. "shape(M)"
  272. ]
  273. },
  274. {
  275. "cell_type": "code",
  276. "execution_count": 16,
  277. "metadata": {},
  278. "outputs": [
  279. {
  280. "data": {
  281. "text/plain": [
  282. "6"
  283. ]
  284. },
  285. "execution_count": 16,
  286. "metadata": {},
  287. "output_type": "execute_result"
  288. }
  289. ],
  290. "source": [
  291. "size(M)"
  292. ]
  293. },
  294. {
  295. "cell_type": "markdown",
  296. "metadata": {},
  297. "source": [
  298. "So far the `numpy.ndarray` looks awefully much like a Python list (or nested list). Why not simply use Python lists for computations instead of creating a new array type? \n",
  299. "\n",
  300. "There are several reasons:\n",
  301. "\n",
  302. "* Python lists are very general. They can contain any kind of object. They are dynamically typed. They do not support mathematical functions such as matrix and dot multiplications, etc. Implementing such functions for Python lists would not be very efficient because of the dynamic typing.\n",
  303. "* Numpy arrays are **statically typed** and **homogeneous**. The type of the elements is determined when the array is created.\n",
  304. "* Numpy arrays are memory efficient.\n",
  305. "* Because of the static typing, fast implementation of mathematical functions such as multiplication and addition of `numpy` arrays can be implemented in a compiled language (C and Fortran is used).\n",
  306. "\n",
  307. "Using the `dtype` (data type) property of an `ndarray`, we can see what type the data of an array has:"
  308. ]
  309. },
  310. {
  311. "cell_type": "code",
  312. "execution_count": 17,
  313. "metadata": {},
  314. "outputs": [
  315. {
  316. "data": {
  317. "text/plain": [
  318. "dtype('int64')"
  319. ]
  320. },
  321. "execution_count": 17,
  322. "metadata": {},
  323. "output_type": "execute_result"
  324. }
  325. ],
  326. "source": [
  327. "M.dtype"
  328. ]
  329. },
  330. {
  331. "cell_type": "markdown",
  332. "metadata": {},
  333. "source": [
  334. "We get an error if we try to assign a value of the wrong type to an element in a numpy array:"
  335. ]
  336. },
  337. {
  338. "cell_type": "code",
  339. "execution_count": 21,
  340. "metadata": {},
  341. "outputs": [
  342. {
  343. "ename": "ValueError",
  344. "evalue": "invalid literal for int() with base 10: 'hello'",
  345. "output_type": "error",
  346. "traceback": [
  347. "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
  348. "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
  349. "\u001b[0;32m<ipython-input-21-e1f336250f69>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mM\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"hello\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
  350. "\u001b[0;31mValueError\u001b[0m: invalid literal for int() with base 10: 'hello'"
  351. ]
  352. }
  353. ],
  354. "source": [
  355. "M[0,0] = \"hello\""
  356. ]
  357. },
  358. {
  359. "cell_type": "markdown",
  360. "metadata": {},
  361. "source": [
  362. "If we want, we can explicitly define the type of the array data when we create it, using the `dtype` keyword argument: "
  363. ]
  364. },
  365. {
  366. "cell_type": "code",
  367. "execution_count": 22,
  368. "metadata": {},
  369. "outputs": [
  370. {
  371. "data": {
  372. "text/plain": [
  373. "array([[1.+0.j, 2.+0.j],\n",
  374. " [3.+0.j, 4.+0.j]])"
  375. ]
  376. },
  377. "execution_count": 22,
  378. "metadata": {},
  379. "output_type": "execute_result"
  380. }
  381. ],
  382. "source": [
  383. "M = array([[1, 2], [3, 4]], dtype=complex)\n",
  384. "\n",
  385. "M"
  386. ]
  387. },
  388. {
  389. "cell_type": "markdown",
  390. "metadata": {},
  391. "source": [
  392. "Common data types that can be used with `dtype` are: `int`, `float`, `complex`, `bool`, `object`, etc.\n",
  393. "\n",
  394. "We can also explicitly define the bit size of the data types, for example: `int64`, `int16`, `float128`, `complex128`."
  395. ]
  396. },
  397. {
  398. "cell_type": "markdown",
  399. "metadata": {},
  400. "source": [
  401. "### Using array-generating functions"
  402. ]
  403. },
  404. {
  405. "cell_type": "markdown",
  406. "metadata": {},
  407. "source": [
  408. "For larger arrays it is inpractical to initialize the data manually, using explicit python lists. Instead we can use one of the many functions in `numpy` that generate arrays of different forms. Some of the more common are:"
  409. ]
  410. },
  411. {
  412. "cell_type": "markdown",
  413. "metadata": {},
  414. "source": [
  415. "#### arange"
  416. ]
  417. },
  418. {
  419. "cell_type": "code",
  420. "execution_count": 26,
  421. "metadata": {},
  422. "outputs": [
  423. {
  424. "name": "stdout",
  425. "output_type": "stream",
  426. "text": [
  427. "[0 1 2 3 4 5 6 7 8 9]\n",
  428. "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n"
  429. ]
  430. }
  431. ],
  432. "source": [
  433. "# create a range\n",
  434. "\n",
  435. "x = arange(0, 10, 1) # arguments: start, stop, step\n",
  436. "y = range(0, 10, 1)\n",
  437. "print(x)\n",
  438. "print(list(y))"
  439. ]
  440. },
  441. {
  442. "cell_type": "code",
  443. "execution_count": 15,
  444. "metadata": {},
  445. "outputs": [
  446. {
  447. "data": {
  448. "text/plain": [
  449. "array([ -1.00000000e+00, -9.00000000e-01, -8.00000000e-01,\n",
  450. " -7.00000000e-01, -6.00000000e-01, -5.00000000e-01,\n",
  451. " -4.00000000e-01, -3.00000000e-01, -2.00000000e-01,\n",
  452. " -1.00000000e-01, -2.22044605e-16, 1.00000000e-01,\n",
  453. " 2.00000000e-01, 3.00000000e-01, 4.00000000e-01,\n",
  454. " 5.00000000e-01, 6.00000000e-01, 7.00000000e-01,\n",
  455. " 8.00000000e-01, 9.00000000e-01])"
  456. ]
  457. },
  458. "execution_count": 15,
  459. "metadata": {},
  460. "output_type": "execute_result"
  461. }
  462. ],
  463. "source": [
  464. "x = arange(-1, 1, 0.1)\n",
  465. "\n",
  466. "x"
  467. ]
  468. },
  469. {
  470. "cell_type": "markdown",
  471. "metadata": {},
  472. "source": [
  473. "#### linspace and logspace"
  474. ]
  475. },
  476. {
  477. "cell_type": "code",
  478. "execution_count": 16,
  479. "metadata": {},
  480. "outputs": [
  481. {
  482. "data": {
  483. "text/plain": [
  484. "array([ 0. , 0.41666667, 0.83333333, 1.25 ,\n",
  485. " 1.66666667, 2.08333333, 2.5 , 2.91666667,\n",
  486. " 3.33333333, 3.75 , 4.16666667, 4.58333333,\n",
  487. " 5. , 5.41666667, 5.83333333, 6.25 ,\n",
  488. " 6.66666667, 7.08333333, 7.5 , 7.91666667,\n",
  489. " 8.33333333, 8.75 , 9.16666667, 9.58333333, 10. ])"
  490. ]
  491. },
  492. "execution_count": 16,
  493. "metadata": {},
  494. "output_type": "execute_result"
  495. }
  496. ],
  497. "source": [
  498. "# using linspace, both end points ARE included\n",
  499. "linspace(0, 10, 25)"
  500. ]
  501. },
  502. {
  503. "cell_type": "code",
  504. "execution_count": 17,
  505. "metadata": {},
  506. "outputs": [
  507. {
  508. "data": {
  509. "text/plain": [
  510. "array([ 1.00000000e+00, 3.03773178e+00, 9.22781435e+00,\n",
  511. " 2.80316249e+01, 8.51525577e+01, 2.58670631e+02,\n",
  512. " 7.85771994e+02, 2.38696456e+03, 7.25095809e+03,\n",
  513. " 2.20264658e+04])"
  514. ]
  515. },
  516. "execution_count": 17,
  517. "metadata": {},
  518. "output_type": "execute_result"
  519. }
  520. ],
  521. "source": [
  522. "logspace(0, 10, 10, base=e)"
  523. ]
  524. },
  525. {
  526. "cell_type": "markdown",
  527. "metadata": {},
  528. "source": [
  529. "#### mgrid"
  530. ]
  531. },
  532. {
  533. "cell_type": "code",
  534. "execution_count": 27,
  535. "metadata": {},
  536. "outputs": [],
  537. "source": [
  538. "x, y = mgrid[0:5, 0:5] # similar to meshgrid in MATLAB"
  539. ]
  540. },
  541. {
  542. "cell_type": "code",
  543. "execution_count": 19,
  544. "metadata": {},
  545. "outputs": [
  546. {
  547. "data": {
  548. "text/plain": [
  549. "array([[0, 0, 0, 0, 0],\n",
  550. " [1, 1, 1, 1, 1],\n",
  551. " [2, 2, 2, 2, 2],\n",
  552. " [3, 3, 3, 3, 3],\n",
  553. " [4, 4, 4, 4, 4]])"
  554. ]
  555. },
  556. "execution_count": 19,
  557. "metadata": {},
  558. "output_type": "execute_result"
  559. }
  560. ],
  561. "source": [
  562. "x"
  563. ]
  564. },
  565. {
  566. "cell_type": "code",
  567. "execution_count": 20,
  568. "metadata": {},
  569. "outputs": [
  570. {
  571. "data": {
  572. "text/plain": [
  573. "array([[0, 1, 2, 3, 4],\n",
  574. " [0, 1, 2, 3, 4],\n",
  575. " [0, 1, 2, 3, 4],\n",
  576. " [0, 1, 2, 3, 4],\n",
  577. " [0, 1, 2, 3, 4]])"
  578. ]
  579. },
  580. "execution_count": 20,
  581. "metadata": {},
  582. "output_type": "execute_result"
  583. }
  584. ],
  585. "source": [
  586. "y"
  587. ]
  588. },
  589. {
  590. "cell_type": "markdown",
  591. "metadata": {},
  592. "source": [
  593. "#### random data"
  594. ]
  595. },
  596. {
  597. "cell_type": "code",
  598. "execution_count": 21,
  599. "metadata": {},
  600. "outputs": [],
  601. "source": [
  602. "from numpy import random"
  603. ]
  604. },
  605. {
  606. "cell_type": "code",
  607. "execution_count": 28,
  608. "metadata": {},
  609. "outputs": [],
  610. "source": [
  611. "# uniform random numbers in [0,1)\n",
  612. "random.rand(5,5)"
  613. ]
  614. },
  615. {
  616. "cell_type": "code",
  617. "execution_count": 29,
  618. "metadata": {},
  619. "outputs": [
  620. {
  621. "data": {
  622. "text/plain": [
  623. "array([[-0.8468269 , -0.32187515, 1.520302 , -0.10714052, 1.88130228],\n",
  624. " [-2.08707056, 0.1204091 , 0.0866864 , -0.46315531, 1.47835324],\n",
  625. " [-0.22495755, 0.28529696, 0.1506852 , 0.89387502, 0.65961749],\n",
  626. " [ 1.0274951 , -0.33844001, -0.01689332, 0.50706762, 0.13447227],\n",
  627. " [-0.17262793, -0.29960596, -0.28114172, 0.37986187, -0.16023985]])"
  628. ]
  629. },
  630. "execution_count": 29,
  631. "metadata": {},
  632. "output_type": "execute_result"
  633. }
  634. ],
  635. "source": [
  636. "# standard normal distributed random numbers\n",
  637. "random.randn(5,5)"
  638. ]
  639. },
  640. {
  641. "cell_type": "markdown",
  642. "metadata": {},
  643. "source": [
  644. "#### diag"
  645. ]
  646. },
  647. {
  648. "cell_type": "code",
  649. "execution_count": 30,
  650. "metadata": {},
  651. "outputs": [
  652. {
  653. "data": {
  654. "text/plain": [
  655. "array([[1, 0, 0],\n",
  656. " [0, 2, 0],\n",
  657. " [0, 0, 3]])"
  658. ]
  659. },
  660. "execution_count": 30,
  661. "metadata": {},
  662. "output_type": "execute_result"
  663. }
  664. ],
  665. "source": [
  666. "# a diagonal matrix\n",
  667. "diag([1,2,3])"
  668. ]
  669. },
  670. {
  671. "cell_type": "code",
  672. "execution_count": 31,
  673. "metadata": {},
  674. "outputs": [
  675. {
  676. "data": {
  677. "text/plain": [
  678. "array([[0, 1, 0, 0],\n",
  679. " [0, 0, 2, 0],\n",
  680. " [0, 0, 0, 3],\n",
  681. " [0, 0, 0, 0]])"
  682. ]
  683. },
  684. "execution_count": 31,
  685. "metadata": {},
  686. "output_type": "execute_result"
  687. }
  688. ],
  689. "source": [
  690. "# diagonal with offset from the main diagonal\n",
  691. "diag([1,2,3], k=1) "
  692. ]
  693. },
  694. {
  695. "cell_type": "markdown",
  696. "metadata": {},
  697. "source": [
  698. "#### zeros and ones"
  699. ]
  700. },
  701. {
  702. "cell_type": "code",
  703. "execution_count": 32,
  704. "metadata": {},
  705. "outputs": [
  706. {
  707. "data": {
  708. "text/plain": [
  709. "array([[0., 0., 0.],\n",
  710. " [0., 0., 0.],\n",
  711. " [0., 0., 0.]])"
  712. ]
  713. },
  714. "execution_count": 32,
  715. "metadata": {},
  716. "output_type": "execute_result"
  717. }
  718. ],
  719. "source": [
  720. "zeros((3,3))"
  721. ]
  722. },
  723. {
  724. "cell_type": "code",
  725. "execution_count": 33,
  726. "metadata": {},
  727. "outputs": [
  728. {
  729. "data": {
  730. "text/plain": [
  731. "array([[1., 1., 1.],\n",
  732. " [1., 1., 1.],\n",
  733. " [1., 1., 1.]])"
  734. ]
  735. },
  736. "execution_count": 33,
  737. "metadata": {},
  738. "output_type": "execute_result"
  739. }
  740. ],
  741. "source": [
  742. "ones((3,3))"
  743. ]
  744. },
  745. {
  746. "cell_type": "markdown",
  747. "metadata": {},
  748. "source": [
  749. "## File I/O"
  750. ]
  751. },
  752. {
  753. "cell_type": "markdown",
  754. "metadata": {},
  755. "source": [
  756. "### Comma-separated values (CSV)"
  757. ]
  758. },
  759. {
  760. "cell_type": "markdown",
  761. "metadata": {},
  762. "source": [
  763. "A very common file format for data files is comma-separated values (CSV), or related formats such as TSV (tab-separated values). To read data from such files into Numpy arrays we can use the `numpy.genfromtxt` function. For example, "
  764. ]
  765. },
  766. {
  767. "cell_type": "code",
  768. "execution_count": 2,
  769. "metadata": {},
  770. "outputs": [
  771. {
  772. "name": "stdout",
  773. "output_type": "stream",
  774. "text": [
  775. "1800 1 1 -6.1 -6.1 -6.1 1\r\n",
  776. "1800 1 2 -15.4 -15.4 -15.4 1\r\n",
  777. "1800 1 3 -15.0 -15.0 -15.0 1\r\n",
  778. "1800 1 4 -19.3 -19.3 -19.3 1\r\n",
  779. "1800 1 5 -16.8 -16.8 -16.8 1\r\n",
  780. "1800 1 6 -11.4 -11.4 -11.4 1\r\n",
  781. "1800 1 7 -7.6 -7.6 -7.6 1\r\n",
  782. "1800 1 8 -7.1 -7.1 -7.1 1\r\n",
  783. "1800 1 9 -10.1 -10.1 -10.1 1\r\n",
  784. "1800 1 10 -9.5 -9.5 -9.5 1\r\n"
  785. ]
  786. }
  787. ],
  788. "source": [
  789. "!head stockholm_td_adj.dat"
  790. ]
  791. },
  792. {
  793. "cell_type": "code",
  794. "execution_count": 1,
  795. "metadata": {},
  796. "outputs": [],
  797. "source": [
  798. "import numpy as np\n",
  799. "data = np.genfromtxt('stockholm_td_adj.dat')"
  800. ]
  801. },
  802. {
  803. "cell_type": "code",
  804. "execution_count": 2,
  805. "metadata": {},
  806. "outputs": [
  807. {
  808. "data": {
  809. "text/plain": [
  810. "(77431, 7)"
  811. ]
  812. },
  813. "execution_count": 2,
  814. "metadata": {},
  815. "output_type": "execute_result"
  816. }
  817. ],
  818. "source": [
  819. "data.shape"
  820. ]
  821. },
  822. {
  823. "cell_type": "code",
  824. "execution_count": 3,
  825. "metadata": {},
  826. "outputs": [
  827. {
  828. "data": {
  829. "image/png": "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\n",
  830. "text/plain": [
  831. "<Figure size 1008x288 with 1 Axes>"
  832. ]
  833. },
  834. "metadata": {
  835. "needs_background": "light"
  836. },
  837. "output_type": "display_data"
  838. }
  839. ],
  840. "source": [
  841. "%matplotlib inline\n",
  842. "import matplotlib.pyplot as plt\n",
  843. "\n",
  844. "fig, ax = plt.subplots(figsize=(14,4))\n",
  845. "ax.plot(data[:,0]+data[:,1]/12.0+data[:,2]/365, data[:,5])\n",
  846. "ax.axis('tight')\n",
  847. "ax.set_title('tempeatures in Stockholm')\n",
  848. "ax.set_xlabel('year')\n",
  849. "ax.set_ylabel('temperature (C)');"
  850. ]
  851. },
  852. {
  853. "cell_type": "markdown",
  854. "metadata": {},
  855. "source": [
  856. "Using `numpy.savetxt` we can store a Numpy array to a file in CSV format:"
  857. ]
  858. },
  859. {
  860. "cell_type": "code",
  861. "execution_count": 4,
  862. "metadata": {},
  863. "outputs": [
  864. {
  865. "data": {
  866. "text/plain": [
  867. "array([[0.05154414, 0.85499268, 0.11256926],\n",
  868. " [0.37333703, 0.71399532, 0.91667067],\n",
  869. " [0.55448257, 0.53279085, 0.49926659]])"
  870. ]
  871. },
  872. "execution_count": 4,
  873. "metadata": {},
  874. "output_type": "execute_result"
  875. }
  876. ],
  877. "source": [
  878. "M = np.random.rand(3,3)\n",
  879. "\n",
  880. "M"
  881. ]
  882. },
  883. {
  884. "cell_type": "code",
  885. "execution_count": 5,
  886. "metadata": {},
  887. "outputs": [],
  888. "source": [
  889. "np.savetxt(\"random-matrix.csv\", M)"
  890. ]
  891. },
  892. {
  893. "cell_type": "code",
  894. "execution_count": 6,
  895. "metadata": {},
  896. "outputs": [
  897. {
  898. "name": "stdout",
  899. "output_type": "stream",
  900. "text": [
  901. "5.154413507058341892e-02 8.549926762495245747e-01 1.125692636334880703e-01\r\n",
  902. "3.733370292698003912e-01 7.139953150984013064e-01 9.166706651790860194e-01\r\n",
  903. "5.544825679398455165e-01 5.327908466251080055e-01 4.992665856784902489e-01\r\n"
  904. ]
  905. }
  906. ],
  907. "source": [
  908. "!cat random-matrix.csv"
  909. ]
  910. },
  911. {
  912. "cell_type": "code",
  913. "execution_count": 7,
  914. "metadata": {},
  915. "outputs": [
  916. {
  917. "name": "stdout",
  918. "output_type": "stream",
  919. "text": [
  920. "0.05154 0.85499 0.11257\r\n",
  921. "0.37334 0.71400 0.91667\r\n",
  922. "0.55448 0.53279 0.49927\r\n"
  923. ]
  924. }
  925. ],
  926. "source": [
  927. "np.savetxt(\"random-matrix.csv\", M, fmt='%.5f') # fmt specifies the format\n",
  928. "\n",
  929. "!cat random-matrix.csv"
  930. ]
  931. },
  932. {
  933. "cell_type": "markdown",
  934. "metadata": {},
  935. "source": [
  936. "### Numpy's native file format"
  937. ]
  938. },
  939. {
  940. "cell_type": "markdown",
  941. "metadata": {},
  942. "source": [
  943. "Useful when storing and reading back numpy array data. Use the functions `numpy.save` and `numpy.load`:"
  944. ]
  945. },
  946. {
  947. "cell_type": "code",
  948. "execution_count": 8,
  949. "metadata": {},
  950. "outputs": [
  951. {
  952. "name": "stdout",
  953. "output_type": "stream",
  954. "text": [
  955. "random-matrix.npy: data\r\n"
  956. ]
  957. }
  958. ],
  959. "source": [
  960. "np.save(\"random-matrix.npy\", M)\n",
  961. "\n",
  962. "!file random-matrix.npy"
  963. ]
  964. },
  965. {
  966. "cell_type": "code",
  967. "execution_count": 9,
  968. "metadata": {},
  969. "outputs": [
  970. {
  971. "data": {
  972. "text/plain": [
  973. "array([[0.05154414, 0.85499268, 0.11256926],\n",
  974. " [0.37333703, 0.71399532, 0.91667067],\n",
  975. " [0.55448257, 0.53279085, 0.49926659]])"
  976. ]
  977. },
  978. "execution_count": 9,
  979. "metadata": {},
  980. "output_type": "execute_result"
  981. }
  982. ],
  983. "source": [
  984. "np.load(\"random-matrix.npy\")"
  985. ]
  986. },
  987. {
  988. "cell_type": "markdown",
  989. "metadata": {},
  990. "source": [
  991. "## More properties of the numpy arrays"
  992. ]
  993. },
  994. {
  995. "cell_type": "code",
  996. "execution_count": 10,
  997. "metadata": {},
  998. "outputs": [
  999. {
  1000. "name": "stdout",
  1001. "output_type": "stream",
  1002. "text": [
  1003. "float64\n",
  1004. "8\n"
  1005. ]
  1006. }
  1007. ],
  1008. "source": [
  1009. "print(M.dtype)\n",
  1010. "print(M.itemsize) # bytes per element\n"
  1011. ]
  1012. },
  1013. {
  1014. "cell_type": "code",
  1015. "execution_count": 11,
  1016. "metadata": {},
  1017. "outputs": [
  1018. {
  1019. "data": {
  1020. "text/plain": [
  1021. "72"
  1022. ]
  1023. },
  1024. "execution_count": 11,
  1025. "metadata": {},
  1026. "output_type": "execute_result"
  1027. }
  1028. ],
  1029. "source": [
  1030. "M.nbytes # number of bytes"
  1031. ]
  1032. },
  1033. {
  1034. "cell_type": "code",
  1035. "execution_count": 12,
  1036. "metadata": {},
  1037. "outputs": [
  1038. {
  1039. "data": {
  1040. "text/plain": [
  1041. "2"
  1042. ]
  1043. },
  1044. "execution_count": 12,
  1045. "metadata": {},
  1046. "output_type": "execute_result"
  1047. }
  1048. ],
  1049. "source": [
  1050. "M.ndim # number of dimensions"
  1051. ]
  1052. },
  1053. {
  1054. "cell_type": "markdown",
  1055. "metadata": {},
  1056. "source": [
  1057. "## Manipulating arrays"
  1058. ]
  1059. },
  1060. {
  1061. "cell_type": "markdown",
  1062. "metadata": {},
  1063. "source": [
  1064. "### Indexing"
  1065. ]
  1066. },
  1067. {
  1068. "cell_type": "markdown",
  1069. "metadata": {},
  1070. "source": [
  1071. "We can index elements in an array using square brackets and indices:"
  1072. ]
  1073. },
  1074. {
  1075. "cell_type": "code",
  1076. "execution_count": 14,
  1077. "metadata": {},
  1078. "outputs": [
  1079. {
  1080. "data": {
  1081. "text/plain": [
  1082. "1"
  1083. ]
  1084. },
  1085. "execution_count": 14,
  1086. "metadata": {},
  1087. "output_type": "execute_result"
  1088. }
  1089. ],
  1090. "source": [
  1091. "v = np.array([1, 2, 3, 4, 5])\n",
  1092. "# v is a vector, and has only one dimension, taking one index\n",
  1093. "v[0]"
  1094. ]
  1095. },
  1096. {
  1097. "cell_type": "code",
  1098. "execution_count": 16,
  1099. "metadata": {},
  1100. "outputs": [
  1101. {
  1102. "name": "stdout",
  1103. "output_type": "stream",
  1104. "text": [
  1105. "0.7139953150984013\n",
  1106. "0.7139953150984013\n",
  1107. "[0.37333703 0.71399532 0.91667067]\n"
  1108. ]
  1109. }
  1110. ],
  1111. "source": [
  1112. "\n",
  1113. "# M is a matrix, or a 2 dimensional array, taking two indices \n",
  1114. "print(M[1,1])\n",
  1115. "print(M[1][1])\n",
  1116. "print(M[1])"
  1117. ]
  1118. },
  1119. {
  1120. "cell_type": "markdown",
  1121. "metadata": {},
  1122. "source": [
  1123. "If we omit an index of a multidimensional array it returns the whole row (or, in general, a N-1 dimensional array) "
  1124. ]
  1125. },
  1126. {
  1127. "cell_type": "code",
  1128. "execution_count": 17,
  1129. "metadata": {},
  1130. "outputs": [
  1131. {
  1132. "data": {
  1133. "text/plain": [
  1134. "array([[0.05154414, 0.85499268, 0.11256926],\n",
  1135. " [0.37333703, 0.71399532, 0.91667067],\n",
  1136. " [0.55448257, 0.53279085, 0.49926659]])"
  1137. ]
  1138. },
  1139. "execution_count": 17,
  1140. "metadata": {},
  1141. "output_type": "execute_result"
  1142. }
  1143. ],
  1144. "source": [
  1145. "M"
  1146. ]
  1147. },
  1148. {
  1149. "cell_type": "code",
  1150. "execution_count": 18,
  1151. "metadata": {},
  1152. "outputs": [
  1153. {
  1154. "data": {
  1155. "text/plain": [
  1156. "array([0.37333703, 0.71399532, 0.91667067])"
  1157. ]
  1158. },
  1159. "execution_count": 18,
  1160. "metadata": {},
  1161. "output_type": "execute_result"
  1162. }
  1163. ],
  1164. "source": [
  1165. "M[1]"
  1166. ]
  1167. },
  1168. {
  1169. "cell_type": "markdown",
  1170. "metadata": {},
  1171. "source": [
  1172. "The same thing can be achieved with using `:` instead of an index: "
  1173. ]
  1174. },
  1175. {
  1176. "cell_type": "code",
  1177. "execution_count": 19,
  1178. "metadata": {},
  1179. "outputs": [
  1180. {
  1181. "data": {
  1182. "text/plain": [
  1183. "array([0.37333703, 0.71399532, 0.91667067])"
  1184. ]
  1185. },
  1186. "execution_count": 19,
  1187. "metadata": {},
  1188. "output_type": "execute_result"
  1189. }
  1190. ],
  1191. "source": [
  1192. "M[1,:] # row 1"
  1193. ]
  1194. },
  1195. {
  1196. "cell_type": "code",
  1197. "execution_count": 20,
  1198. "metadata": {},
  1199. "outputs": [
  1200. {
  1201. "data": {
  1202. "text/plain": [
  1203. "array([0.85499268, 0.71399532, 0.53279085])"
  1204. ]
  1205. },
  1206. "execution_count": 20,
  1207. "metadata": {},
  1208. "output_type": "execute_result"
  1209. }
  1210. ],
  1211. "source": [
  1212. "M[:,1] # column 1"
  1213. ]
  1214. },
  1215. {
  1216. "cell_type": "markdown",
  1217. "metadata": {},
  1218. "source": [
  1219. "We can assign new values to elements in an array using indexing:"
  1220. ]
  1221. },
  1222. {
  1223. "cell_type": "code",
  1224. "execution_count": 21,
  1225. "metadata": {},
  1226. "outputs": [],
  1227. "source": [
  1228. "M[0,0] = 1"
  1229. ]
  1230. },
  1231. {
  1232. "cell_type": "code",
  1233. "execution_count": 22,
  1234. "metadata": {},
  1235. "outputs": [
  1236. {
  1237. "data": {
  1238. "text/plain": [
  1239. "array([[1. , 0.85499268, 0.11256926],\n",
  1240. " [0.37333703, 0.71399532, 0.91667067],\n",
  1241. " [0.55448257, 0.53279085, 0.49926659]])"
  1242. ]
  1243. },
  1244. "execution_count": 22,
  1245. "metadata": {},
  1246. "output_type": "execute_result"
  1247. }
  1248. ],
  1249. "source": [
  1250. "M"
  1251. ]
  1252. },
  1253. {
  1254. "cell_type": "code",
  1255. "execution_count": 23,
  1256. "metadata": {},
  1257. "outputs": [],
  1258. "source": [
  1259. "# also works for rows and columns\n",
  1260. "M[1,:] = 0\n",
  1261. "M[:,2] = -1"
  1262. ]
  1263. },
  1264. {
  1265. "cell_type": "code",
  1266. "execution_count": 24,
  1267. "metadata": {},
  1268. "outputs": [
  1269. {
  1270. "data": {
  1271. "text/plain": [
  1272. "array([[ 1. , 0.85499268, -1. ],\n",
  1273. " [ 0. , 0. , -1. ],\n",
  1274. " [ 0.55448257, 0.53279085, -1. ]])"
  1275. ]
  1276. },
  1277. "execution_count": 24,
  1278. "metadata": {},
  1279. "output_type": "execute_result"
  1280. }
  1281. ],
  1282. "source": [
  1283. "M"
  1284. ]
  1285. },
  1286. {
  1287. "cell_type": "markdown",
  1288. "metadata": {},
  1289. "source": [
  1290. "### Index slicing"
  1291. ]
  1292. },
  1293. {
  1294. "cell_type": "markdown",
  1295. "metadata": {},
  1296. "source": [
  1297. "Index slicing is the technical name for the syntax `M[lower:upper:step]` to extract part of an array:"
  1298. ]
  1299. },
  1300. {
  1301. "cell_type": "code",
  1302. "execution_count": 26,
  1303. "metadata": {},
  1304. "outputs": [
  1305. {
  1306. "data": {
  1307. "text/plain": [
  1308. "array([1, 2, 3, 4, 5])"
  1309. ]
  1310. },
  1311. "execution_count": 26,
  1312. "metadata": {},
  1313. "output_type": "execute_result"
  1314. }
  1315. ],
  1316. "source": [
  1317. "A = np.array([1,2,3,4,5])\n",
  1318. "A"
  1319. ]
  1320. },
  1321. {
  1322. "cell_type": "code",
  1323. "execution_count": 27,
  1324. "metadata": {},
  1325. "outputs": [
  1326. {
  1327. "data": {
  1328. "text/plain": [
  1329. "array([2, 3])"
  1330. ]
  1331. },
  1332. "execution_count": 27,
  1333. "metadata": {},
  1334. "output_type": "execute_result"
  1335. }
  1336. ],
  1337. "source": [
  1338. "A[1:3]"
  1339. ]
  1340. },
  1341. {
  1342. "cell_type": "markdown",
  1343. "metadata": {},
  1344. "source": [
  1345. "Array slices are *mutable*: if they are assigned a new value the original array from which the slice was extracted is modified:"
  1346. ]
  1347. },
  1348. {
  1349. "cell_type": "code",
  1350. "execution_count": 30,
  1351. "metadata": {},
  1352. "outputs": [
  1353. {
  1354. "data": {
  1355. "text/plain": [
  1356. "array([ 1, -2, -3, 4, 5])"
  1357. ]
  1358. },
  1359. "execution_count": 30,
  1360. "metadata": {},
  1361. "output_type": "execute_result"
  1362. }
  1363. ],
  1364. "source": [
  1365. "A[1:3] = [-2,-3] # auto convert type\n",
  1366. "A[1:3] = np.array([-2, -3]) \n",
  1367. "\n",
  1368. "A"
  1369. ]
  1370. },
  1371. {
  1372. "cell_type": "markdown",
  1373. "metadata": {},
  1374. "source": [
  1375. "We can omit any of the three parameters in `M[lower:upper:step]`:"
  1376. ]
  1377. },
  1378. {
  1379. "cell_type": "code",
  1380. "execution_count": 31,
  1381. "metadata": {},
  1382. "outputs": [
  1383. {
  1384. "data": {
  1385. "text/plain": [
  1386. "array([ 1, -2, -3, 4, 5])"
  1387. ]
  1388. },
  1389. "execution_count": 31,
  1390. "metadata": {},
  1391. "output_type": "execute_result"
  1392. }
  1393. ],
  1394. "source": [
  1395. "A[::] # lower, upper, step all take the default values"
  1396. ]
  1397. },
  1398. {
  1399. "cell_type": "code",
  1400. "execution_count": 33,
  1401. "metadata": {},
  1402. "outputs": [
  1403. {
  1404. "data": {
  1405. "text/plain": [
  1406. "array([ 1, -2, -3, 4, 5])"
  1407. ]
  1408. },
  1409. "execution_count": 33,
  1410. "metadata": {},
  1411. "output_type": "execute_result"
  1412. }
  1413. ],
  1414. "source": [
  1415. "A[:]"
  1416. ]
  1417. },
  1418. {
  1419. "cell_type": "code",
  1420. "execution_count": 55,
  1421. "metadata": {},
  1422. "outputs": [
  1423. {
  1424. "data": {
  1425. "text/plain": [
  1426. "array([ 1, -3, 5])"
  1427. ]
  1428. },
  1429. "execution_count": 55,
  1430. "metadata": {},
  1431. "output_type": "execute_result"
  1432. }
  1433. ],
  1434. "source": [
  1435. "A[::2] # step is 2, lower and upper defaults to the beginning and end of the array"
  1436. ]
  1437. },
  1438. {
  1439. "cell_type": "code",
  1440. "execution_count": 56,
  1441. "metadata": {},
  1442. "outputs": [
  1443. {
  1444. "data": {
  1445. "text/plain": [
  1446. "array([ 1, -2, -3])"
  1447. ]
  1448. },
  1449. "execution_count": 56,
  1450. "metadata": {},
  1451. "output_type": "execute_result"
  1452. }
  1453. ],
  1454. "source": [
  1455. "A[:3] # first three elements"
  1456. ]
  1457. },
  1458. {
  1459. "cell_type": "code",
  1460. "execution_count": 57,
  1461. "metadata": {},
  1462. "outputs": [
  1463. {
  1464. "data": {
  1465. "text/plain": [
  1466. "array([4, 5])"
  1467. ]
  1468. },
  1469. "execution_count": 57,
  1470. "metadata": {},
  1471. "output_type": "execute_result"
  1472. }
  1473. ],
  1474. "source": [
  1475. "A[3:] # elements from index 3"
  1476. ]
  1477. },
  1478. {
  1479. "cell_type": "markdown",
  1480. "metadata": {},
  1481. "source": [
  1482. "Negative indices counts from the end of the array (positive index from the begining):"
  1483. ]
  1484. },
  1485. {
  1486. "cell_type": "code",
  1487. "execution_count": 34,
  1488. "metadata": {},
  1489. "outputs": [],
  1490. "source": [
  1491. "A = np.array([1,2,3,4,5])"
  1492. ]
  1493. },
  1494. {
  1495. "cell_type": "code",
  1496. "execution_count": 35,
  1497. "metadata": {},
  1498. "outputs": [
  1499. {
  1500. "data": {
  1501. "text/plain": [
  1502. "5"
  1503. ]
  1504. },
  1505. "execution_count": 35,
  1506. "metadata": {},
  1507. "output_type": "execute_result"
  1508. }
  1509. ],
  1510. "source": [
  1511. "A[-1] # the last element in the array"
  1512. ]
  1513. },
  1514. {
  1515. "cell_type": "code",
  1516. "execution_count": 36,
  1517. "metadata": {},
  1518. "outputs": [
  1519. {
  1520. "data": {
  1521. "text/plain": [
  1522. "array([3, 4, 5])"
  1523. ]
  1524. },
  1525. "execution_count": 36,
  1526. "metadata": {},
  1527. "output_type": "execute_result"
  1528. }
  1529. ],
  1530. "source": [
  1531. "A[-3:] # the last three elements"
  1532. ]
  1533. },
  1534. {
  1535. "cell_type": "markdown",
  1536. "metadata": {},
  1537. "source": [
  1538. "Index slicing works exactly the same way for multidimensional arrays:"
  1539. ]
  1540. },
  1541. {
  1542. "cell_type": "code",
  1543. "execution_count": 38,
  1544. "metadata": {},
  1545. "outputs": [
  1546. {
  1547. "data": {
  1548. "text/plain": [
  1549. "array([[ 0, 1, 2, 3, 4],\n",
  1550. " [10, 11, 12, 13, 14],\n",
  1551. " [20, 21, 22, 23, 24],\n",
  1552. " [30, 31, 32, 33, 34],\n",
  1553. " [40, 41, 42, 43, 44]])"
  1554. ]
  1555. },
  1556. "execution_count": 38,
  1557. "metadata": {},
  1558. "output_type": "execute_result"
  1559. }
  1560. ],
  1561. "source": [
  1562. "A = np.array([[n+m*10 for n in range(5)] for m in range(5)])\n",
  1563. "\n",
  1564. "A"
  1565. ]
  1566. },
  1567. {
  1568. "cell_type": "code",
  1569. "execution_count": 62,
  1570. "metadata": {},
  1571. "outputs": [
  1572. {
  1573. "data": {
  1574. "text/plain": [
  1575. "array([[11, 12, 13],\n",
  1576. " [21, 22, 23],\n",
  1577. " [31, 32, 33]])"
  1578. ]
  1579. },
  1580. "execution_count": 62,
  1581. "metadata": {},
  1582. "output_type": "execute_result"
  1583. }
  1584. ],
  1585. "source": [
  1586. "# a block from the original array\n",
  1587. "A[1:4, 1:4]"
  1588. ]
  1589. },
  1590. {
  1591. "cell_type": "code",
  1592. "execution_count": 63,
  1593. "metadata": {},
  1594. "outputs": [
  1595. {
  1596. "data": {
  1597. "text/plain": [
  1598. "array([[ 0, 2, 4],\n",
  1599. " [20, 22, 24],\n",
  1600. " [40, 42, 44]])"
  1601. ]
  1602. },
  1603. "execution_count": 63,
  1604. "metadata": {},
  1605. "output_type": "execute_result"
  1606. }
  1607. ],
  1608. "source": [
  1609. "# strides\n",
  1610. "A[::2, ::2]"
  1611. ]
  1612. },
  1613. {
  1614. "cell_type": "markdown",
  1615. "metadata": {},
  1616. "source": [
  1617. "### Fancy indexing"
  1618. ]
  1619. },
  1620. {
  1621. "cell_type": "markdown",
  1622. "metadata": {},
  1623. "source": [
  1624. "Fancy indexing is the name for when an array or list is used in-place of an index: "
  1625. ]
  1626. },
  1627. {
  1628. "cell_type": "code",
  1629. "execution_count": 41,
  1630. "metadata": {},
  1631. "outputs": [
  1632. {
  1633. "name": "stdout",
  1634. "output_type": "stream",
  1635. "text": [
  1636. "[[10 11 12 13 14]\n",
  1637. " [20 21 22 23 24]\n",
  1638. " [30 31 32 33 34]]\n",
  1639. "[[ 0 1 2 3 4]\n",
  1640. " [10 11 12 13 14]\n",
  1641. " [20 21 22 23 24]\n",
  1642. " [30 31 32 33 34]\n",
  1643. " [40 41 42 43 44]]\n"
  1644. ]
  1645. }
  1646. ],
  1647. "source": [
  1648. "row_indices = [1, 2, 3]\n",
  1649. "print(A[row_indices])\n",
  1650. "print(A)"
  1651. ]
  1652. },
  1653. {
  1654. "cell_type": "code",
  1655. "execution_count": 65,
  1656. "metadata": {},
  1657. "outputs": [
  1658. {
  1659. "data": {
  1660. "text/plain": [
  1661. "array([11, 22, 34])"
  1662. ]
  1663. },
  1664. "execution_count": 65,
  1665. "metadata": {},
  1666. "output_type": "execute_result"
  1667. }
  1668. ],
  1669. "source": [
  1670. "col_indices = [1, 2, -1] # remember, index -1 means the last element\n",
  1671. "A[row_indices, col_indices]"
  1672. ]
  1673. },
  1674. {
  1675. "cell_type": "markdown",
  1676. "metadata": {},
  1677. "source": [
  1678. "We can also use index masks: If the index mask is an Numpy array of data type `bool`, then an element is selected (True) or not (False) depending on the value of the index mask at the position of each element: "
  1679. ]
  1680. },
  1681. {
  1682. "cell_type": "code",
  1683. "execution_count": 66,
  1684. "metadata": {},
  1685. "outputs": [
  1686. {
  1687. "data": {
  1688. "text/plain": [
  1689. "array([0, 1, 2, 3, 4])"
  1690. ]
  1691. },
  1692. "execution_count": 66,
  1693. "metadata": {},
  1694. "output_type": "execute_result"
  1695. }
  1696. ],
  1697. "source": [
  1698. "B = array([n for n in range(5)])\n",
  1699. "B"
  1700. ]
  1701. },
  1702. {
  1703. "cell_type": "code",
  1704. "execution_count": 67,
  1705. "metadata": {},
  1706. "outputs": [
  1707. {
  1708. "data": {
  1709. "text/plain": [
  1710. "array([0, 2])"
  1711. ]
  1712. },
  1713. "execution_count": 67,
  1714. "metadata": {},
  1715. "output_type": "execute_result"
  1716. }
  1717. ],
  1718. "source": [
  1719. "row_mask = array([True, False, True, False, False])\n",
  1720. "B[row_mask]"
  1721. ]
  1722. },
  1723. {
  1724. "cell_type": "code",
  1725. "execution_count": 68,
  1726. "metadata": {},
  1727. "outputs": [
  1728. {
  1729. "data": {
  1730. "text/plain": [
  1731. "array([0, 2])"
  1732. ]
  1733. },
  1734. "execution_count": 68,
  1735. "metadata": {},
  1736. "output_type": "execute_result"
  1737. }
  1738. ],
  1739. "source": [
  1740. "# same thing\n",
  1741. "row_mask = array([1,0,1,0,0], dtype=bool)\n",
  1742. "B[row_mask]"
  1743. ]
  1744. },
  1745. {
  1746. "cell_type": "markdown",
  1747. "metadata": {},
  1748. "source": [
  1749. "This feature is very useful to conditionally select elements from an array, using for example comparison operators:"
  1750. ]
  1751. },
  1752. {
  1753. "cell_type": "code",
  1754. "execution_count": 42,
  1755. "metadata": {},
  1756. "outputs": [
  1757. {
  1758. "data": {
  1759. "text/plain": [
  1760. "array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. , 5.5, 6. ,\n",
  1761. " 6.5, 7. , 7.5, 8. , 8.5, 9. , 9.5])"
  1762. ]
  1763. },
  1764. "execution_count": 42,
  1765. "metadata": {},
  1766. "output_type": "execute_result"
  1767. }
  1768. ],
  1769. "source": [
  1770. "x = np.arange(0, 10, 0.5)\n",
  1771. "x"
  1772. ]
  1773. },
  1774. {
  1775. "cell_type": "code",
  1776. "execution_count": 44,
  1777. "metadata": {},
  1778. "outputs": [
  1779. {
  1780. "data": {
  1781. "text/plain": [
  1782. "array([False, False, False, False, False, False, False, False, False,\n",
  1783. " False, False, True, True, True, True, False, False, False,\n",
  1784. " False, False])"
  1785. ]
  1786. },
  1787. "execution_count": 44,
  1788. "metadata": {},
  1789. "output_type": "execute_result"
  1790. }
  1791. ],
  1792. "source": [
  1793. "mask = (5 < x) * (x < 7.5)\n",
  1794. "\n",
  1795. "mask"
  1796. ]
  1797. },
  1798. {
  1799. "cell_type": "code",
  1800. "execution_count": 45,
  1801. "metadata": {},
  1802. "outputs": [
  1803. {
  1804. "data": {
  1805. "text/plain": [
  1806. "array([5.5, 6. , 6.5, 7. ])"
  1807. ]
  1808. },
  1809. "execution_count": 45,
  1810. "metadata": {},
  1811. "output_type": "execute_result"
  1812. }
  1813. ],
  1814. "source": [
  1815. "x[mask]"
  1816. ]
  1817. },
  1818. {
  1819. "cell_type": "code",
  1820. "execution_count": 46,
  1821. "metadata": {},
  1822. "outputs": [
  1823. {
  1824. "data": {
  1825. "text/plain": [
  1826. "array([3.5, 4. , 4.5, 5. , 5.5])"
  1827. ]
  1828. },
  1829. "execution_count": 46,
  1830. "metadata": {},
  1831. "output_type": "execute_result"
  1832. }
  1833. ],
  1834. "source": [
  1835. "x[(3<x)*(x<6)]"
  1836. ]
  1837. },
  1838. {
  1839. "cell_type": "markdown",
  1840. "metadata": {},
  1841. "source": [
  1842. "## Functions for extracting data from arrays and creating arrays"
  1843. ]
  1844. },
  1845. {
  1846. "cell_type": "markdown",
  1847. "metadata": {},
  1848. "source": [
  1849. "### where"
  1850. ]
  1851. },
  1852. {
  1853. "cell_type": "markdown",
  1854. "metadata": {},
  1855. "source": [
  1856. "The index mask can be converted to position index using the `where` function"
  1857. ]
  1858. },
  1859. {
  1860. "cell_type": "code",
  1861. "execution_count": 47,
  1862. "metadata": {},
  1863. "outputs": [
  1864. {
  1865. "data": {
  1866. "text/plain": [
  1867. "(array([11, 12, 13, 14]),)"
  1868. ]
  1869. },
  1870. "execution_count": 47,
  1871. "metadata": {},
  1872. "output_type": "execute_result"
  1873. }
  1874. ],
  1875. "source": [
  1876. "indices = np.where(mask)\n",
  1877. "\n",
  1878. "indices"
  1879. ]
  1880. },
  1881. {
  1882. "cell_type": "code",
  1883. "execution_count": 48,
  1884. "metadata": {},
  1885. "outputs": [
  1886. {
  1887. "data": {
  1888. "text/plain": [
  1889. "array([5.5, 6. , 6.5, 7. ])"
  1890. ]
  1891. },
  1892. "execution_count": 48,
  1893. "metadata": {},
  1894. "output_type": "execute_result"
  1895. }
  1896. ],
  1897. "source": [
  1898. "x[indices] # this indexing is equivalent to the fancy indexing x[mask]"
  1899. ]
  1900. },
  1901. {
  1902. "cell_type": "markdown",
  1903. "metadata": {},
  1904. "source": [
  1905. "### diag"
  1906. ]
  1907. },
  1908. {
  1909. "cell_type": "markdown",
  1910. "metadata": {},
  1911. "source": [
  1912. "With the diag function we can also extract the diagonal and subdiagonals of an array:"
  1913. ]
  1914. },
  1915. {
  1916. "cell_type": "code",
  1917. "execution_count": 74,
  1918. "metadata": {},
  1919. "outputs": [
  1920. {
  1921. "data": {
  1922. "text/plain": [
  1923. "array([ 0, 11, 22, 33, 44])"
  1924. ]
  1925. },
  1926. "execution_count": 74,
  1927. "metadata": {},
  1928. "output_type": "execute_result"
  1929. }
  1930. ],
  1931. "source": [
  1932. "diag(A)"
  1933. ]
  1934. },
  1935. {
  1936. "cell_type": "code",
  1937. "execution_count": 75,
  1938. "metadata": {},
  1939. "outputs": [
  1940. {
  1941. "data": {
  1942. "text/plain": [
  1943. "array([10, 21, 32, 43])"
  1944. ]
  1945. },
  1946. "execution_count": 75,
  1947. "metadata": {},
  1948. "output_type": "execute_result"
  1949. }
  1950. ],
  1951. "source": [
  1952. "diag(A, -1)"
  1953. ]
  1954. },
  1955. {
  1956. "cell_type": "markdown",
  1957. "metadata": {},
  1958. "source": [
  1959. "### take"
  1960. ]
  1961. },
  1962. {
  1963. "cell_type": "markdown",
  1964. "metadata": {},
  1965. "source": [
  1966. "The `take` function is similar to fancy indexing described above:"
  1967. ]
  1968. },
  1969. {
  1970. "cell_type": "code",
  1971. "execution_count": 76,
  1972. "metadata": {},
  1973. "outputs": [
  1974. {
  1975. "data": {
  1976. "text/plain": [
  1977. "array([-3, -2, -1, 0, 1, 2])"
  1978. ]
  1979. },
  1980. "execution_count": 76,
  1981. "metadata": {},
  1982. "output_type": "execute_result"
  1983. }
  1984. ],
  1985. "source": [
  1986. "v2 = arange(-3,3)\n",
  1987. "v2"
  1988. ]
  1989. },
  1990. {
  1991. "cell_type": "code",
  1992. "execution_count": 77,
  1993. "metadata": {},
  1994. "outputs": [
  1995. {
  1996. "data": {
  1997. "text/plain": [
  1998. "array([-2, 0, 2])"
  1999. ]
  2000. },
  2001. "execution_count": 77,
  2002. "metadata": {},
  2003. "output_type": "execute_result"
  2004. }
  2005. ],
  2006. "source": [
  2007. "row_indices = [1, 3, 5]\n",
  2008. "v2[row_indices] # fancy indexing"
  2009. ]
  2010. },
  2011. {
  2012. "cell_type": "code",
  2013. "execution_count": 78,
  2014. "metadata": {},
  2015. "outputs": [
  2016. {
  2017. "data": {
  2018. "text/plain": [
  2019. "array([-2, 0, 2])"
  2020. ]
  2021. },
  2022. "execution_count": 78,
  2023. "metadata": {},
  2024. "output_type": "execute_result"
  2025. }
  2026. ],
  2027. "source": [
  2028. "v2.take(row_indices)"
  2029. ]
  2030. },
  2031. {
  2032. "cell_type": "markdown",
  2033. "metadata": {},
  2034. "source": [
  2035. "But `take` also works on lists and other objects:"
  2036. ]
  2037. },
  2038. {
  2039. "cell_type": "code",
  2040. "execution_count": 79,
  2041. "metadata": {},
  2042. "outputs": [
  2043. {
  2044. "data": {
  2045. "text/plain": [
  2046. "array([-2, 0, 2])"
  2047. ]
  2048. },
  2049. "execution_count": 79,
  2050. "metadata": {},
  2051. "output_type": "execute_result"
  2052. }
  2053. ],
  2054. "source": [
  2055. "take([-3, -2, -1, 0, 1, 2], row_indices)"
  2056. ]
  2057. },
  2058. {
  2059. "cell_type": "markdown",
  2060. "metadata": {},
  2061. "source": [
  2062. "### choose"
  2063. ]
  2064. },
  2065. {
  2066. "cell_type": "markdown",
  2067. "metadata": {},
  2068. "source": [
  2069. "Constructs an array by picking elements from several arrays:"
  2070. ]
  2071. },
  2072. {
  2073. "cell_type": "code",
  2074. "execution_count": 49,
  2075. "metadata": {},
  2076. "outputs": [
  2077. {
  2078. "data": {
  2079. "text/plain": [
  2080. "array([ 5, -2, 5, -2])"
  2081. ]
  2082. },
  2083. "execution_count": 49,
  2084. "metadata": {},
  2085. "output_type": "execute_result"
  2086. }
  2087. ],
  2088. "source": [
  2089. "which = [1, 0, 1, 0]\n",
  2090. "choices = [[-2,-2,-2,-2], [5,5,5,5]]\n",
  2091. "\n",
  2092. "np.choose(which, choices)"
  2093. ]
  2094. },
  2095. {
  2096. "cell_type": "markdown",
  2097. "metadata": {},
  2098. "source": [
  2099. "## Linear algebra"
  2100. ]
  2101. },
  2102. {
  2103. "cell_type": "markdown",
  2104. "metadata": {},
  2105. "source": [
  2106. "Vectorizing code is the key to writing efficient numerical calculation with Python/Numpy. That means that as much as possible of a program should be formulated in terms of matrix and vector operations, like matrix-matrix multiplication."
  2107. ]
  2108. },
  2109. {
  2110. "cell_type": "markdown",
  2111. "metadata": {},
  2112. "source": [
  2113. "### Scalar-array operations"
  2114. ]
  2115. },
  2116. {
  2117. "cell_type": "markdown",
  2118. "metadata": {},
  2119. "source": [
  2120. "We can use the usual arithmetic operators to multiply, add, subtract, and divide arrays with scalar numbers."
  2121. ]
  2122. },
  2123. {
  2124. "cell_type": "code",
  2125. "execution_count": 61,
  2126. "metadata": {},
  2127. "outputs": [],
  2128. "source": [
  2129. "v1 = np.arange(0, 5)"
  2130. ]
  2131. },
  2132. {
  2133. "cell_type": "code",
  2134. "execution_count": 51,
  2135. "metadata": {},
  2136. "outputs": [
  2137. {
  2138. "data": {
  2139. "text/plain": [
  2140. "array([0, 2, 4, 6, 8])"
  2141. ]
  2142. },
  2143. "execution_count": 51,
  2144. "metadata": {},
  2145. "output_type": "execute_result"
  2146. }
  2147. ],
  2148. "source": [
  2149. "v1 * 2"
  2150. ]
  2151. },
  2152. {
  2153. "cell_type": "code",
  2154. "execution_count": 52,
  2155. "metadata": {},
  2156. "outputs": [
  2157. {
  2158. "data": {
  2159. "text/plain": [
  2160. "array([2, 3, 4, 5, 6])"
  2161. ]
  2162. },
  2163. "execution_count": 52,
  2164. "metadata": {},
  2165. "output_type": "execute_result"
  2166. }
  2167. ],
  2168. "source": [
  2169. "v1 + 2"
  2170. ]
  2171. },
  2172. {
  2173. "cell_type": "code",
  2174. "execution_count": 53,
  2175. "metadata": {},
  2176. "outputs": [
  2177. {
  2178. "data": {
  2179. "text/plain": [
  2180. "(array([[ 0, 2, 4, 6, 8],\n",
  2181. " [20, 22, 24, 26, 28],\n",
  2182. " [40, 42, 44, 46, 48],\n",
  2183. " [60, 62, 64, 66, 68],\n",
  2184. " [80, 82, 84, 86, 88]]), array([[ 2, 3, 4, 5, 6],\n",
  2185. " [12, 13, 14, 15, 16],\n",
  2186. " [22, 23, 24, 25, 26],\n",
  2187. " [32, 33, 34, 35, 36],\n",
  2188. " [42, 43, 44, 45, 46]]))"
  2189. ]
  2190. },
  2191. "execution_count": 53,
  2192. "metadata": {},
  2193. "output_type": "execute_result"
  2194. }
  2195. ],
  2196. "source": [
  2197. "A * 2, A + 2"
  2198. ]
  2199. },
  2200. {
  2201. "cell_type": "markdown",
  2202. "metadata": {},
  2203. "source": [
  2204. "### Element-wise array-array operations"
  2205. ]
  2206. },
  2207. {
  2208. "cell_type": "markdown",
  2209. "metadata": {},
  2210. "source": [
  2211. "When we add, subtract, multiply and divide arrays with each other, the default behaviour is **element-wise** operations:"
  2212. ]
  2213. },
  2214. {
  2215. "cell_type": "code",
  2216. "execution_count": 59,
  2217. "metadata": {},
  2218. "outputs": [
  2219. {
  2220. "data": {
  2221. "text/plain": [
  2222. "array([[0.58554016, 0.35362438, 0.01644849],\n",
  2223. " [0.0509308 , 0.39489878, 0.287905 ]])"
  2224. ]
  2225. },
  2226. "execution_count": 59,
  2227. "metadata": {},
  2228. "output_type": "execute_result"
  2229. }
  2230. ],
  2231. "source": [
  2232. "A = np.random.rand(2, 3)\n",
  2233. "\n",
  2234. "A * A # element-wise multiplication"
  2235. ]
  2236. },
  2237. {
  2238. "cell_type": "code",
  2239. "execution_count": 56,
  2240. "metadata": {},
  2241. "outputs": [
  2242. {
  2243. "data": {
  2244. "text/plain": [
  2245. "array([ 0, 1, 4, 9, 16])"
  2246. ]
  2247. },
  2248. "execution_count": 56,
  2249. "metadata": {},
  2250. "output_type": "execute_result"
  2251. }
  2252. ],
  2253. "source": [
  2254. "v1 * v1"
  2255. ]
  2256. },
  2257. {
  2258. "cell_type": "markdown",
  2259. "metadata": {},
  2260. "source": [
  2261. "If we multiply arrays with compatible shapes, we get an element-wise multiplication of each row:"
  2262. ]
  2263. },
  2264. {
  2265. "cell_type": "code",
  2266. "execution_count": 60,
  2267. "metadata": {},
  2268. "outputs": [
  2269. {
  2270. "data": {
  2271. "text/plain": [
  2272. "((2, 3), (5,))"
  2273. ]
  2274. },
  2275. "execution_count": 60,
  2276. "metadata": {},
  2277. "output_type": "execute_result"
  2278. }
  2279. ],
  2280. "source": [
  2281. "A.shape, v1.shape"
  2282. ]
  2283. },
  2284. {
  2285. "cell_type": "code",
  2286. "execution_count": 62,
  2287. "metadata": {},
  2288. "outputs": [
  2289. {
  2290. "ename": "ValueError",
  2291. "evalue": "operands could not be broadcast together with shapes (2,3) (5,) ",
  2292. "output_type": "error",
  2293. "traceback": [
  2294. "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
  2295. "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
  2296. "\u001b[0;32m<ipython-input-62-1af134c5c5d0>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mA\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mv1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
  2297. "\u001b[0;31mValueError\u001b[0m: operands could not be broadcast together with shapes (2,3) (5,) "
  2298. ]
  2299. }
  2300. ],
  2301. "source": [
  2302. "A * v1"
  2303. ]
  2304. },
  2305. {
  2306. "cell_type": "markdown",
  2307. "metadata": {},
  2308. "source": [
  2309. "### Matrix algebra"
  2310. ]
  2311. },
  2312. {
  2313. "cell_type": "markdown",
  2314. "metadata": {},
  2315. "source": [
  2316. "What about matrix mutiplication? There are two ways. We can either use the `dot` function, which applies a matrix-matrix, matrix-vector, or inner vector multiplication to its two arguments: "
  2317. ]
  2318. },
  2319. {
  2320. "cell_type": "code",
  2321. "execution_count": 64,
  2322. "metadata": {},
  2323. "outputs": [
  2324. {
  2325. "data": {
  2326. "text/plain": [
  2327. "array([[1.61923857, 0.95558371, 1.11141445, 1.64271612, 1.80666486],\n",
  2328. " [1.71358703, 1.45250572, 1.01957436, 1.72544194, 2.10519363],\n",
  2329. " [1.5255213 , 0.55960695, 1.43264196, 1.61597327, 1.47385403],\n",
  2330. " [0.51089051, 0.59210298, 0.45696844, 0.59261034, 0.72884524],\n",
  2331. " [0.81307747, 0.52389725, 0.65030053, 0.84393132, 0.88557227]])"
  2332. ]
  2333. },
  2334. "execution_count": 64,
  2335. "metadata": {},
  2336. "output_type": "execute_result"
  2337. }
  2338. ],
  2339. "source": [
  2340. "A = np.random.rand(5, 5)\n",
  2341. "v = np.random.rand(5, 1)\n",
  2342. "\n",
  2343. "np.dot(A, A)"
  2344. ]
  2345. },
  2346. {
  2347. "cell_type": "code",
  2348. "execution_count": 66,
  2349. "metadata": {},
  2350. "outputs": [
  2351. {
  2352. "data": {
  2353. "text/plain": [
  2354. "array([6.30499252, 7.63515634, 4.90215304, 4.16180701, 2.98227738])"
  2355. ]
  2356. },
  2357. "execution_count": 66,
  2358. "metadata": {},
  2359. "output_type": "execute_result"
  2360. }
  2361. ],
  2362. "source": [
  2363. "np.dot(A, v1)"
  2364. ]
  2365. },
  2366. {
  2367. "cell_type": "code",
  2368. "execution_count": 67,
  2369. "metadata": {},
  2370. "outputs": [
  2371. {
  2372. "data": {
  2373. "text/plain": [
  2374. "30"
  2375. ]
  2376. },
  2377. "execution_count": 67,
  2378. "metadata": {},
  2379. "output_type": "execute_result"
  2380. }
  2381. ],
  2382. "source": [
  2383. "np.dot(v1, v1)"
  2384. ]
  2385. },
  2386. {
  2387. "cell_type": "markdown",
  2388. "metadata": {},
  2389. "source": [
  2390. "Alternatively, we can cast the array objects to the type `matrix`. This changes the behavior of the standard arithmetic operators `+, -, *` to use matrix algebra."
  2391. ]
  2392. },
  2393. {
  2394. "cell_type": "code",
  2395. "execution_count": 68,
  2396. "metadata": {},
  2397. "outputs": [],
  2398. "source": [
  2399. "M = np.matrix(A)\n",
  2400. "v = np.matrix(v1).T # make it a column vector"
  2401. ]
  2402. },
  2403. {
  2404. "cell_type": "code",
  2405. "execution_count": 79,
  2406. "metadata": {},
  2407. "outputs": [
  2408. {
  2409. "data": {
  2410. "text/plain": [
  2411. "matrix([[1],\n",
  2412. " [2],\n",
  2413. " [3],\n",
  2414. " [4],\n",
  2415. " [5],\n",
  2416. " [6]])"
  2417. ]
  2418. },
  2419. "execution_count": 79,
  2420. "metadata": {},
  2421. "output_type": "execute_result"
  2422. }
  2423. ],
  2424. "source": [
  2425. "v"
  2426. ]
  2427. },
  2428. {
  2429. "cell_type": "code",
  2430. "execution_count": 70,
  2431. "metadata": {},
  2432. "outputs": [
  2433. {
  2434. "data": {
  2435. "text/plain": [
  2436. "matrix([[1.61923857, 0.95558371, 1.11141445, 1.64271612, 1.80666486],\n",
  2437. " [1.71358703, 1.45250572, 1.01957436, 1.72544194, 2.10519363],\n",
  2438. " [1.5255213 , 0.55960695, 1.43264196, 1.61597327, 1.47385403],\n",
  2439. " [0.51089051, 0.59210298, 0.45696844, 0.59261034, 0.72884524],\n",
  2440. " [0.81307747, 0.52389725, 0.65030053, 0.84393132, 0.88557227]])"
  2441. ]
  2442. },
  2443. "execution_count": 70,
  2444. "metadata": {},
  2445. "output_type": "execute_result"
  2446. }
  2447. ],
  2448. "source": [
  2449. "M * M"
  2450. ]
  2451. },
  2452. {
  2453. "cell_type": "code",
  2454. "execution_count": 71,
  2455. "metadata": {},
  2456. "outputs": [
  2457. {
  2458. "data": {
  2459. "text/plain": [
  2460. "matrix([[6.30499252],\n",
  2461. " [7.63515634],\n",
  2462. " [4.90215304],\n",
  2463. " [4.16180701],\n",
  2464. " [2.98227738]])"
  2465. ]
  2466. },
  2467. "execution_count": 71,
  2468. "metadata": {},
  2469. "output_type": "execute_result"
  2470. }
  2471. ],
  2472. "source": [
  2473. "M * v"
  2474. ]
  2475. },
  2476. {
  2477. "cell_type": "code",
  2478. "execution_count": 72,
  2479. "metadata": {},
  2480. "outputs": [
  2481. {
  2482. "data": {
  2483. "text/plain": [
  2484. "matrix([[30]])"
  2485. ]
  2486. },
  2487. "execution_count": 72,
  2488. "metadata": {},
  2489. "output_type": "execute_result"
  2490. }
  2491. ],
  2492. "source": [
  2493. "# inner product\n",
  2494. "v.T * v"
  2495. ]
  2496. },
  2497. {
  2498. "cell_type": "code",
  2499. "execution_count": 97,
  2500. "metadata": {},
  2501. "outputs": [
  2502. {
  2503. "data": {
  2504. "text/plain": [
  2505. "matrix([[ 30],\n",
  2506. " [131],\n",
  2507. " [232],\n",
  2508. " [333],\n",
  2509. " [434]])"
  2510. ]
  2511. },
  2512. "execution_count": 97,
  2513. "metadata": {},
  2514. "output_type": "execute_result"
  2515. }
  2516. ],
  2517. "source": [
  2518. "# with matrix objects, standard matrix algebra applies\n",
  2519. "v + M*v"
  2520. ]
  2521. },
  2522. {
  2523. "cell_type": "markdown",
  2524. "metadata": {},
  2525. "source": [
  2526. "If we try to add, subtract or multiply objects with incomplatible shapes we get an error:"
  2527. ]
  2528. },
  2529. {
  2530. "cell_type": "code",
  2531. "execution_count": 76,
  2532. "metadata": {},
  2533. "outputs": [],
  2534. "source": [
  2535. "v = np.matrix([1,2,3,4,5,6]).T"
  2536. ]
  2537. },
  2538. {
  2539. "cell_type": "code",
  2540. "execution_count": 77,
  2541. "metadata": {},
  2542. "outputs": [
  2543. {
  2544. "data": {
  2545. "text/plain": [
  2546. "((5, 5), (6, 1))"
  2547. ]
  2548. },
  2549. "execution_count": 77,
  2550. "metadata": {},
  2551. "output_type": "execute_result"
  2552. }
  2553. ],
  2554. "source": [
  2555. "np.shape(M), np.shape(v)"
  2556. ]
  2557. },
  2558. {
  2559. "cell_type": "code",
  2560. "execution_count": 78,
  2561. "metadata": {},
  2562. "outputs": [
  2563. {
  2564. "ename": "ValueError",
  2565. "evalue": "shapes (5,5) and (6,1) not aligned: 5 (dim 1) != 6 (dim 0)",
  2566. "output_type": "error",
  2567. "traceback": [
  2568. "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
  2569. "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
  2570. "\u001b[0;32m<ipython-input-78-e8f88679fe45>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mM\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
  2571. "\u001b[0;32m~/.virtualenv/dl/lib/python3.5/site-packages/numpy/matrixlib/defmatrix.py\u001b[0m in \u001b[0;36m__mul__\u001b[0;34m(self, other)\u001b[0m\n\u001b[1;32m 307\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mother\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mN\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndarray\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 308\u001b[0m \u001b[0;31m# This promotes 1-D vectors to row vectors\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 309\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mN\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0masmatrix\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mother\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 310\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misscalar\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mother\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mhasattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mother\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'__rmul__'\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 311\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mN\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mother\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
  2572. "\u001b[0;31mValueError\u001b[0m: shapes (5,5) and (6,1) not aligned: 5 (dim 1) != 6 (dim 0)"
  2573. ]
  2574. }
  2575. ],
  2576. "source": [
  2577. "M * v"
  2578. ]
  2579. },
  2580. {
  2581. "cell_type": "markdown",
  2582. "metadata": {},
  2583. "source": [
  2584. "See also the related functions: `inner`, `outer`, `cross`, `kron`, `tensordot`. Try for example `help(kron)`."
  2585. ]
  2586. },
  2587. {
  2588. "cell_type": "markdown",
  2589. "metadata": {},
  2590. "source": [
  2591. "### Array/Matrix transformations"
  2592. ]
  2593. },
  2594. {
  2595. "cell_type": "markdown",
  2596. "metadata": {},
  2597. "source": [
  2598. "Above we have used the `.T` to transpose the matrix object `v`. We could also have used the `transpose` function to accomplish the same thing. \n",
  2599. "\n",
  2600. "Other mathematical functions that transform matrix objects are:"
  2601. ]
  2602. },
  2603. {
  2604. "cell_type": "code",
  2605. "execution_count": 81,
  2606. "metadata": {},
  2607. "outputs": [
  2608. {
  2609. "name": "stdout",
  2610. "output_type": "stream",
  2611. "text": [
  2612. "[[0.52324656 0.21248895 0.81560972 0.45277567]\n",
  2613. " [0.57447573 0.06345405 0.41295542 0.18753998]\n",
  2614. " [0.46850626 0.20506338 0.97890548 0.79394942]]\n",
  2615. "[[0.52324656 0.57447573 0.46850626]\n",
  2616. " [0.21248895 0.06345405 0.20506338]\n",
  2617. " [0.81560972 0.41295542 0.97890548]\n",
  2618. " [0.45277567 0.18753998 0.79394942]]\n"
  2619. ]
  2620. }
  2621. ],
  2622. "source": [
  2623. "A = np.random.rand(3,4)\n",
  2624. "print(A)\n",
  2625. "print(A.T)"
  2626. ]
  2627. },
  2628. {
  2629. "cell_type": "code",
  2630. "execution_count": 83,
  2631. "metadata": {},
  2632. "outputs": [
  2633. {
  2634. "data": {
  2635. "text/plain": [
  2636. "matrix([[0.+1.j, 0.+2.j],\n",
  2637. " [0.+3.j, 0.+4.j]])"
  2638. ]
  2639. },
  2640. "execution_count": 83,
  2641. "metadata": {},
  2642. "output_type": "execute_result"
  2643. }
  2644. ],
  2645. "source": [
  2646. "C = np.matrix([[1j, 2j], [3j, 4j]])\n",
  2647. "C"
  2648. ]
  2649. },
  2650. {
  2651. "cell_type": "code",
  2652. "execution_count": 102,
  2653. "metadata": {},
  2654. "outputs": [
  2655. {
  2656. "data": {
  2657. "text/plain": [
  2658. "matrix([[ 0.-1.j, 0.-2.j],\n",
  2659. " [ 0.-3.j, 0.-4.j]])"
  2660. ]
  2661. },
  2662. "execution_count": 102,
  2663. "metadata": {},
  2664. "output_type": "execute_result"
  2665. }
  2666. ],
  2667. "source": [
  2668. "conjugate(C)"
  2669. ]
  2670. },
  2671. {
  2672. "cell_type": "markdown",
  2673. "metadata": {},
  2674. "source": [
  2675. "Hermitian conjugate: transpose + conjugate"
  2676. ]
  2677. },
  2678. {
  2679. "cell_type": "code",
  2680. "execution_count": 103,
  2681. "metadata": {},
  2682. "outputs": [
  2683. {
  2684. "data": {
  2685. "text/plain": [
  2686. "matrix([[ 0.-1.j, 0.-3.j],\n",
  2687. " [ 0.-2.j, 0.-4.j]])"
  2688. ]
  2689. },
  2690. "execution_count": 103,
  2691. "metadata": {},
  2692. "output_type": "execute_result"
  2693. }
  2694. ],
  2695. "source": [
  2696. "C.H"
  2697. ]
  2698. },
  2699. {
  2700. "cell_type": "markdown",
  2701. "metadata": {},
  2702. "source": [
  2703. "We can extract the real and imaginary parts of complex-valued arrays using `real` and `imag`:"
  2704. ]
  2705. },
  2706. {
  2707. "cell_type": "code",
  2708. "execution_count": 104,
  2709. "metadata": {},
  2710. "outputs": [
  2711. {
  2712. "data": {
  2713. "text/plain": [
  2714. "matrix([[ 0., 0.],\n",
  2715. " [ 0., 0.]])"
  2716. ]
  2717. },
  2718. "execution_count": 104,
  2719. "metadata": {},
  2720. "output_type": "execute_result"
  2721. }
  2722. ],
  2723. "source": [
  2724. "real(C) # same as: C.real"
  2725. ]
  2726. },
  2727. {
  2728. "cell_type": "code",
  2729. "execution_count": 105,
  2730. "metadata": {},
  2731. "outputs": [
  2732. {
  2733. "data": {
  2734. "text/plain": [
  2735. "matrix([[ 1., 2.],\n",
  2736. " [ 3., 4.]])"
  2737. ]
  2738. },
  2739. "execution_count": 105,
  2740. "metadata": {},
  2741. "output_type": "execute_result"
  2742. }
  2743. ],
  2744. "source": [
  2745. "imag(C) # same as: C.imag"
  2746. ]
  2747. },
  2748. {
  2749. "cell_type": "markdown",
  2750. "metadata": {},
  2751. "source": [
  2752. "Or the complex argument and absolute value"
  2753. ]
  2754. },
  2755. {
  2756. "cell_type": "code",
  2757. "execution_count": 106,
  2758. "metadata": {},
  2759. "outputs": [
  2760. {
  2761. "data": {
  2762. "text/plain": [
  2763. "array([[ 0.78539816, 1.10714872],\n",
  2764. " [ 1.24904577, 1.32581766]])"
  2765. ]
  2766. },
  2767. "execution_count": 106,
  2768. "metadata": {},
  2769. "output_type": "execute_result"
  2770. }
  2771. ],
  2772. "source": [
  2773. "angle(C+1) # heads up MATLAB Users, angle is used instead of arg"
  2774. ]
  2775. },
  2776. {
  2777. "cell_type": "code",
  2778. "execution_count": 107,
  2779. "metadata": {},
  2780. "outputs": [
  2781. {
  2782. "data": {
  2783. "text/plain": [
  2784. "matrix([[ 1., 2.],\n",
  2785. " [ 3., 4.]])"
  2786. ]
  2787. },
  2788. "execution_count": 107,
  2789. "metadata": {},
  2790. "output_type": "execute_result"
  2791. }
  2792. ],
  2793. "source": [
  2794. "abs(C)"
  2795. ]
  2796. },
  2797. {
  2798. "cell_type": "markdown",
  2799. "metadata": {},
  2800. "source": [
  2801. "### Matrix computations"
  2802. ]
  2803. },
  2804. {
  2805. "cell_type": "markdown",
  2806. "metadata": {},
  2807. "source": [
  2808. "#### Inverse"
  2809. ]
  2810. },
  2811. {
  2812. "cell_type": "code",
  2813. "execution_count": 85,
  2814. "metadata": {},
  2815. "outputs": [
  2816. {
  2817. "data": {
  2818. "text/plain": [
  2819. "matrix([[0.+2.j , 0.-1.j ],\n",
  2820. " [0.-1.5j, 0.+0.5j]])"
  2821. ]
  2822. },
  2823. "execution_count": 85,
  2824. "metadata": {},
  2825. "output_type": "execute_result"
  2826. }
  2827. ],
  2828. "source": [
  2829. "np.linalg.inv(C) # equivalent to C.I "
  2830. ]
  2831. },
  2832. {
  2833. "cell_type": "code",
  2834. "execution_count": 109,
  2835. "metadata": {},
  2836. "outputs": [
  2837. {
  2838. "data": {
  2839. "text/plain": [
  2840. "matrix([[ 1.00000000e+00+0.j, 4.44089210e-16+0.j],\n",
  2841. " [ 0.00000000e+00+0.j, 1.00000000e+00+0.j]])"
  2842. ]
  2843. },
  2844. "execution_count": 109,
  2845. "metadata": {},
  2846. "output_type": "execute_result"
  2847. }
  2848. ],
  2849. "source": [
  2850. "C.I * C"
  2851. ]
  2852. },
  2853. {
  2854. "cell_type": "markdown",
  2855. "metadata": {},
  2856. "source": [
  2857. "#### Determinant"
  2858. ]
  2859. },
  2860. {
  2861. "cell_type": "code",
  2862. "execution_count": 86,
  2863. "metadata": {},
  2864. "outputs": [
  2865. {
  2866. "data": {
  2867. "text/plain": [
  2868. "(2.0000000000000004+0j)"
  2869. ]
  2870. },
  2871. "execution_count": 86,
  2872. "metadata": {},
  2873. "output_type": "execute_result"
  2874. }
  2875. ],
  2876. "source": [
  2877. "np.linalg.det(C)"
  2878. ]
  2879. },
  2880. {
  2881. "cell_type": "code",
  2882. "execution_count": 111,
  2883. "metadata": {},
  2884. "outputs": [
  2885. {
  2886. "data": {
  2887. "text/plain": [
  2888. "(0.50000000000000011+0j)"
  2889. ]
  2890. },
  2891. "execution_count": 111,
  2892. "metadata": {},
  2893. "output_type": "execute_result"
  2894. }
  2895. ],
  2896. "source": [
  2897. "linalg.det(C.I)"
  2898. ]
  2899. },
  2900. {
  2901. "cell_type": "markdown",
  2902. "metadata": {},
  2903. "source": [
  2904. "### Data processing"
  2905. ]
  2906. },
  2907. {
  2908. "cell_type": "markdown",
  2909. "metadata": {},
  2910. "source": [
  2911. "Often it is useful to store datasets in Numpy arrays. Numpy provides a number of functions to calculate statistics of datasets in arrays. \n",
  2912. "\n",
  2913. "For example, let's calculate some properties from the Stockholm temperature dataset used above."
  2914. ]
  2915. },
  2916. {
  2917. "cell_type": "code",
  2918. "execution_count": 87,
  2919. "metadata": {},
  2920. "outputs": [
  2921. {
  2922. "data": {
  2923. "text/plain": [
  2924. "(77431, 7)"
  2925. ]
  2926. },
  2927. "execution_count": 87,
  2928. "metadata": {},
  2929. "output_type": "execute_result"
  2930. }
  2931. ],
  2932. "source": [
  2933. "# reminder, the tempeature dataset is stored in the data variable:\n",
  2934. "np.shape(data)"
  2935. ]
  2936. },
  2937. {
  2938. "cell_type": "markdown",
  2939. "metadata": {},
  2940. "source": [
  2941. "#### mean"
  2942. ]
  2943. },
  2944. {
  2945. "cell_type": "code",
  2946. "execution_count": 88,
  2947. "metadata": {},
  2948. "outputs": [
  2949. {
  2950. "name": "stdout",
  2951. "output_type": "stream",
  2952. "text": [
  2953. "(77431, 7)\n"
  2954. ]
  2955. },
  2956. {
  2957. "data": {
  2958. "text/plain": [
  2959. "6.197109684751585"
  2960. ]
  2961. },
  2962. "execution_count": 88,
  2963. "metadata": {},
  2964. "output_type": "execute_result"
  2965. }
  2966. ],
  2967. "source": [
  2968. "# the temperature data is in column 3\n",
  2969. "print(data.shape)\n",
  2970. "np.mean(data[:,3])"
  2971. ]
  2972. },
  2973. {
  2974. "cell_type": "code",
  2975. "execution_count": 81,
  2976. "metadata": {},
  2977. "outputs": [],
  2978. "source": [
  2979. "A = np.random.rand(4, 3)\n",
  2980. "np.mean(A)"
  2981. ]
  2982. },
  2983. {
  2984. "cell_type": "markdown",
  2985. "metadata": {},
  2986. "source": [
  2987. "The daily mean temperature in Stockholm over the last 200 years has been about 6.2 C."
  2988. ]
  2989. },
  2990. {
  2991. "cell_type": "markdown",
  2992. "metadata": {},
  2993. "source": [
  2994. "#### standard deviations and variance"
  2995. ]
  2996. },
  2997. {
  2998. "cell_type": "code",
  2999. "execution_count": 89,
  3000. "metadata": {},
  3001. "outputs": [
  3002. {
  3003. "data": {
  3004. "text/plain": [
  3005. "(8.282271621340573, 68.59602320966341)"
  3006. ]
  3007. },
  3008. "execution_count": 89,
  3009. "metadata": {},
  3010. "output_type": "execute_result"
  3011. }
  3012. ],
  3013. "source": [
  3014. "np.std(data[:,3]), np.var(data[:,3])"
  3015. ]
  3016. },
  3017. {
  3018. "cell_type": "markdown",
  3019. "metadata": {},
  3020. "source": [
  3021. "#### min and max"
  3022. ]
  3023. },
  3024. {
  3025. "cell_type": "code",
  3026. "execution_count": 90,
  3027. "metadata": {},
  3028. "outputs": [
  3029. {
  3030. "data": {
  3031. "text/plain": [
  3032. "-25.8"
  3033. ]
  3034. },
  3035. "execution_count": 90,
  3036. "metadata": {},
  3037. "output_type": "execute_result"
  3038. }
  3039. ],
  3040. "source": [
  3041. "# lowest daily average temperature\n",
  3042. "data[:,3].min()"
  3043. ]
  3044. },
  3045. {
  3046. "cell_type": "code",
  3047. "execution_count": 91,
  3048. "metadata": {},
  3049. "outputs": [
  3050. {
  3051. "data": {
  3052. "text/plain": [
  3053. "28.3"
  3054. ]
  3055. },
  3056. "execution_count": 91,
  3057. "metadata": {},
  3058. "output_type": "execute_result"
  3059. }
  3060. ],
  3061. "source": [
  3062. "# highest daily average temperature\n",
  3063. "data[:,3].max()"
  3064. ]
  3065. },
  3066. {
  3067. "cell_type": "markdown",
  3068. "metadata": {},
  3069. "source": [
  3070. "#### sum, prod, and trace"
  3071. ]
  3072. },
  3073. {
  3074. "cell_type": "code",
  3075. "execution_count": 92,
  3076. "metadata": {},
  3077. "outputs": [
  3078. {
  3079. "data": {
  3080. "text/plain": [
  3081. "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
  3082. ]
  3083. },
  3084. "execution_count": 92,
  3085. "metadata": {},
  3086. "output_type": "execute_result"
  3087. }
  3088. ],
  3089. "source": [
  3090. "d = np.arange(0, 10)\n",
  3091. "d"
  3092. ]
  3093. },
  3094. {
  3095. "cell_type": "code",
  3096. "execution_count": 93,
  3097. "metadata": {},
  3098. "outputs": [
  3099. {
  3100. "data": {
  3101. "text/plain": [
  3102. "45"
  3103. ]
  3104. },
  3105. "execution_count": 93,
  3106. "metadata": {},
  3107. "output_type": "execute_result"
  3108. }
  3109. ],
  3110. "source": [
  3111. "# sum up all elements\n",
  3112. "np.sum(d)"
  3113. ]
  3114. },
  3115. {
  3116. "cell_type": "code",
  3117. "execution_count": 94,
  3118. "metadata": {},
  3119. "outputs": [
  3120. {
  3121. "data": {
  3122. "text/plain": [
  3123. "3628800"
  3124. ]
  3125. },
  3126. "execution_count": 94,
  3127. "metadata": {},
  3128. "output_type": "execute_result"
  3129. }
  3130. ],
  3131. "source": [
  3132. "# product of all elements\n",
  3133. "np.prod(d+1)"
  3134. ]
  3135. },
  3136. {
  3137. "cell_type": "code",
  3138. "execution_count": 95,
  3139. "metadata": {},
  3140. "outputs": [
  3141. {
  3142. "data": {
  3143. "text/plain": [
  3144. "array([ 0, 1, 3, 6, 10, 15, 21, 28, 36, 45])"
  3145. ]
  3146. },
  3147. "execution_count": 95,
  3148. "metadata": {},
  3149. "output_type": "execute_result"
  3150. }
  3151. ],
  3152. "source": [
  3153. "# cummulative sum\n",
  3154. "np.cumsum(d)"
  3155. ]
  3156. },
  3157. {
  3158. "cell_type": "code",
  3159. "execution_count": 97,
  3160. "metadata": {},
  3161. "outputs": [
  3162. {
  3163. "data": {
  3164. "text/plain": [
  3165. "array([ 1, 2, 6, 24, 120, 720, 5040,\n",
  3166. " 40320, 362880, 3628800])"
  3167. ]
  3168. },
  3169. "execution_count": 97,
  3170. "metadata": {},
  3171. "output_type": "execute_result"
  3172. }
  3173. ],
  3174. "source": [
  3175. "# cummulative product\n",
  3176. "np.cumprod(d+1)"
  3177. ]
  3178. },
  3179. {
  3180. "cell_type": "code",
  3181. "execution_count": 98,
  3182. "metadata": {},
  3183. "outputs": [
  3184. {
  3185. "data": {
  3186. "text/plain": [
  3187. "1.565606093694652"
  3188. ]
  3189. },
  3190. "execution_count": 98,
  3191. "metadata": {},
  3192. "output_type": "execute_result"
  3193. }
  3194. ],
  3195. "source": [
  3196. "# same as: diag(A).sum()\n",
  3197. "np.trace(A)"
  3198. ]
  3199. },
  3200. {
  3201. "cell_type": "markdown",
  3202. "metadata": {},
  3203. "source": [
  3204. "### Computations on subsets of arrays"
  3205. ]
  3206. },
  3207. {
  3208. "cell_type": "markdown",
  3209. "metadata": {},
  3210. "source": [
  3211. "We can compute with subsets of the data in an array using indexing, fancy indexing, and the other methods of extracting data from an array (described above).\n",
  3212. "\n",
  3213. "For example, let's go back to the temperature dataset:"
  3214. ]
  3215. },
  3216. {
  3217. "cell_type": "code",
  3218. "execution_count": 86,
  3219. "metadata": {},
  3220. "outputs": [
  3221. {
  3222. "name": "stdout",
  3223. "output_type": "stream",
  3224. "text": [
  3225. "1800 1 1 -6.1 -6.1 -6.1 1\r\n",
  3226. "1800 1 2 -15.4 -15.4 -15.4 1\r\n",
  3227. "1800 1 3 -15.0 -15.0 -15.0 1\r\n"
  3228. ]
  3229. }
  3230. ],
  3231. "source": [
  3232. "!head -n 3 stockholm_td_adj.dat"
  3233. ]
  3234. },
  3235. {
  3236. "cell_type": "markdown",
  3237. "metadata": {},
  3238. "source": [
  3239. "The dataformat is: year, month, day, daily average temperature, low, high, location.\n",
  3240. "\n",
  3241. "If we are interested in the average temperature only in a particular month, say February, then we can create a index mask and use it to select only the data for that month using:"
  3242. ]
  3243. },
  3244. {
  3245. "cell_type": "code",
  3246. "execution_count": 99,
  3247. "metadata": {},
  3248. "outputs": [
  3249. {
  3250. "data": {
  3251. "text/plain": [
  3252. "array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.])"
  3253. ]
  3254. },
  3255. "execution_count": 99,
  3256. "metadata": {},
  3257. "output_type": "execute_result"
  3258. }
  3259. ],
  3260. "source": [
  3261. "np.unique(data[:,1]) # the month column takes values from 1 to 12"
  3262. ]
  3263. },
  3264. {
  3265. "cell_type": "code",
  3266. "execution_count": 101,
  3267. "metadata": {},
  3268. "outputs": [
  3269. {
  3270. "name": "stdout",
  3271. "output_type": "stream",
  3272. "text": [
  3273. "[False False False ... False False False]\n"
  3274. ]
  3275. }
  3276. ],
  3277. "source": [
  3278. "mask_feb = data[:,1] == 2\n",
  3279. "print(mask_feb)"
  3280. ]
  3281. },
  3282. {
  3283. "cell_type": "code",
  3284. "execution_count": 102,
  3285. "metadata": {},
  3286. "outputs": [
  3287. {
  3288. "name": "stdout",
  3289. "output_type": "stream",
  3290. "text": [
  3291. "-3.212109570736596\n",
  3292. "5.090390768766271\n"
  3293. ]
  3294. }
  3295. ],
  3296. "source": [
  3297. "# the temperature data is in column 3\n",
  3298. "print(np.mean(data[mask_feb,3]))\n",
  3299. "print(np.std(data[mask_feb,3]))"
  3300. ]
  3301. },
  3302. {
  3303. "cell_type": "markdown",
  3304. "metadata": {},
  3305. "source": [
  3306. "With these tools we have very powerful data processing capabilities at our disposal. For example, to extract the average monthly average temperatures for each month of the year only takes a few lines of code: "
  3307. ]
  3308. },
  3309. {
  3310. "cell_type": "code",
  3311. "execution_count": 103,
  3312. "metadata": {},
  3313. "outputs": [
  3314. {
  3315. "data": {
  3316. "image/png": "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\n",
  3317. "text/plain": [
  3318. "<Figure size 432x288 with 1 Axes>"
  3319. ]
  3320. },
  3321. "metadata": {
  3322. "needs_background": "light"
  3323. },
  3324. "output_type": "display_data"
  3325. }
  3326. ],
  3327. "source": [
  3328. "months = np.arange(1,13)\n",
  3329. "monthly_mean = [np.mean(data[data[:,1] == month, 3]) for month in months]\n",
  3330. "\n",
  3331. "fig, ax = plt.subplots()\n",
  3332. "ax.bar(months, monthly_mean)\n",
  3333. "ax.set_xlabel(\"Month\")\n",
  3334. "ax.set_ylabel(\"Monthly avg. temp.\");"
  3335. ]
  3336. },
  3337. {
  3338. "cell_type": "markdown",
  3339. "metadata": {},
  3340. "source": [
  3341. "### Calculations with higher-dimensional data"
  3342. ]
  3343. },
  3344. {
  3345. "cell_type": "markdown",
  3346. "metadata": {},
  3347. "source": [
  3348. "When functions such as `min`, `max`, etc. are applied to a multidimensional arrays, it is sometimes useful to apply the calculation to the entire array, and sometimes only on a row or column basis. Using the `axis` argument we can specify how these functions should behave: "
  3349. ]
  3350. },
  3351. {
  3352. "cell_type": "code",
  3353. "execution_count": 2,
  3354. "metadata": {},
  3355. "outputs": [
  3356. {
  3357. "data": {
  3358. "text/plain": [
  3359. "array([[0.37256155, 0.55372079, 0.79188821],\n",
  3360. " [0.31015577, 0.15060291, 0.35533741],\n",
  3361. " [0.74538933, 0.09260393, 0.97473277]])"
  3362. ]
  3363. },
  3364. "execution_count": 2,
  3365. "metadata": {},
  3366. "output_type": "execute_result"
  3367. }
  3368. ],
  3369. "source": [
  3370. "import numpy as np\n",
  3371. "\n",
  3372. "m = np.random.rand(3,3)\n",
  3373. "m"
  3374. ]
  3375. },
  3376. {
  3377. "cell_type": "code",
  3378. "execution_count": 3,
  3379. "metadata": {},
  3380. "outputs": [
  3381. {
  3382. "data": {
  3383. "text/plain": [
  3384. "0.9747327654750723"
  3385. ]
  3386. },
  3387. "execution_count": 3,
  3388. "metadata": {},
  3389. "output_type": "execute_result"
  3390. }
  3391. ],
  3392. "source": [
  3393. "# global max\n",
  3394. "m.max()"
  3395. ]
  3396. },
  3397. {
  3398. "cell_type": "code",
  3399. "execution_count": 4,
  3400. "metadata": {},
  3401. "outputs": [
  3402. {
  3403. "data": {
  3404. "text/plain": [
  3405. "array([0.74538933, 0.55372079, 0.97473277])"
  3406. ]
  3407. },
  3408. "execution_count": 4,
  3409. "metadata": {},
  3410. "output_type": "execute_result"
  3411. }
  3412. ],
  3413. "source": [
  3414. "# max in each column\n",
  3415. "m.max(axis=0)"
  3416. ]
  3417. },
  3418. {
  3419. "cell_type": "code",
  3420. "execution_count": 5,
  3421. "metadata": {},
  3422. "outputs": [
  3423. {
  3424. "data": {
  3425. "text/plain": [
  3426. "array([0.79188821, 0.35533741, 0.97473277])"
  3427. ]
  3428. },
  3429. "execution_count": 5,
  3430. "metadata": {},
  3431. "output_type": "execute_result"
  3432. }
  3433. ],
  3434. "source": [
  3435. "# max in each row\n",
  3436. "m.max(axis=1)"
  3437. ]
  3438. },
  3439. {
  3440. "cell_type": "markdown",
  3441. "metadata": {},
  3442. "source": [
  3443. "Many other functions and methods in the `array` and `matrix` classes accept the same (optional) `axis` keyword argument."
  3444. ]
  3445. },
  3446. {
  3447. "cell_type": "markdown",
  3448. "metadata": {},
  3449. "source": [
  3450. "## Reshaping, resizing and stacking arrays"
  3451. ]
  3452. },
  3453. {
  3454. "cell_type": "markdown",
  3455. "metadata": {},
  3456. "source": [
  3457. "The shape of an Numpy array can be modified without copying the underlaying data, which makes it a fast operation even for large arrays."
  3458. ]
  3459. },
  3460. {
  3461. "cell_type": "code",
  3462. "execution_count": 9,
  3463. "metadata": {},
  3464. "outputs": [
  3465. {
  3466. "name": "stdout",
  3467. "output_type": "stream",
  3468. "text": [
  3469. "[[0.32932131 0.81267957 0.85936584]\n",
  3470. " [0.39382838 0.47577722 0.05040035]\n",
  3471. " [0.40055451 0.35697994 0.18257562]\n",
  3472. " [0.22687327 0.21119009 0.35634197]]\n"
  3473. ]
  3474. }
  3475. ],
  3476. "source": [
  3477. "import numpy as np\n",
  3478. "\n",
  3479. "A = np.random.rand(4, 3)\n",
  3480. "print(A)"
  3481. ]
  3482. },
  3483. {
  3484. "cell_type": "code",
  3485. "execution_count": 11,
  3486. "metadata": {},
  3487. "outputs": [
  3488. {
  3489. "name": "stdout",
  3490. "output_type": "stream",
  3491. "text": [
  3492. "4 3\n"
  3493. ]
  3494. }
  3495. ],
  3496. "source": [
  3497. "n, m = A.shape\n",
  3498. "print(n, m)"
  3499. ]
  3500. },
  3501. {
  3502. "cell_type": "code",
  3503. "execution_count": 12,
  3504. "metadata": {},
  3505. "outputs": [
  3506. {
  3507. "data": {
  3508. "text/plain": [
  3509. "array([[0.32932131, 0.81267957, 0.85936584, 0.39382838, 0.47577722,\n",
  3510. " 0.05040035, 0.40055451, 0.35697994, 0.18257562, 0.22687327,\n",
  3511. " 0.21119009, 0.35634197]])"
  3512. ]
  3513. },
  3514. "execution_count": 12,
  3515. "metadata": {},
  3516. "output_type": "execute_result"
  3517. }
  3518. ],
  3519. "source": [
  3520. "B = A.reshape((1,n*m))\n",
  3521. "B"
  3522. ]
  3523. },
  3524. {
  3525. "cell_type": "code",
  3526. "execution_count": 13,
  3527. "metadata": {},
  3528. "outputs": [
  3529. {
  3530. "name": "stdout",
  3531. "output_type": "stream",
  3532. "text": [
  3533. "[[0.32932131]\n",
  3534. " [0.81267957]\n",
  3535. " [0.85936584]\n",
  3536. " [0.39382838]\n",
  3537. " [0.47577722]\n",
  3538. " [0.05040035]\n",
  3539. " [0.40055451]\n",
  3540. " [0.35697994]\n",
  3541. " [0.18257562]\n",
  3542. " [0.22687327]\n",
  3543. " [0.21119009]\n",
  3544. " [0.35634197]]\n"
  3545. ]
  3546. }
  3547. ],
  3548. "source": [
  3549. "B2 = A.reshape((n*m, 1))\n",
  3550. "print(B2)"
  3551. ]
  3552. },
  3553. {
  3554. "cell_type": "code",
  3555. "execution_count": 14,
  3556. "metadata": {},
  3557. "outputs": [
  3558. {
  3559. "data": {
  3560. "text/plain": [
  3561. "array([[5. , 5. , 5. , 5. , 5. ,\n",
  3562. " 0.05040035, 0.40055451, 0.35697994, 0.18257562, 0.22687327,\n",
  3563. " 0.21119009, 0.35634197]])"
  3564. ]
  3565. },
  3566. "execution_count": 14,
  3567. "metadata": {},
  3568. "output_type": "execute_result"
  3569. }
  3570. ],
  3571. "source": [
  3572. "B[0,0:5] = 5 # modify the array\n",
  3573. "\n",
  3574. "B"
  3575. ]
  3576. },
  3577. {
  3578. "cell_type": "code",
  3579. "execution_count": 15,
  3580. "metadata": {},
  3581. "outputs": [
  3582. {
  3583. "data": {
  3584. "text/plain": [
  3585. "array([[5. , 5. , 5. ],\n",
  3586. " [5. , 5. , 0.05040035],\n",
  3587. " [0.40055451, 0.35697994, 0.18257562],\n",
  3588. " [0.22687327, 0.21119009, 0.35634197]])"
  3589. ]
  3590. },
  3591. "execution_count": 15,
  3592. "metadata": {},
  3593. "output_type": "execute_result"
  3594. }
  3595. ],
  3596. "source": [
  3597. "A # and the original variable is also changed. B is only a different view of the same data"
  3598. ]
  3599. },
  3600. {
  3601. "cell_type": "markdown",
  3602. "metadata": {},
  3603. "source": [
  3604. "We can also use the function `flatten` to make a higher-dimensional array into a vector. But this function create a copy of the data."
  3605. ]
  3606. },
  3607. {
  3608. "cell_type": "code",
  3609. "execution_count": 16,
  3610. "metadata": {},
  3611. "outputs": [
  3612. {
  3613. "data": {
  3614. "text/plain": [
  3615. "array([5. , 5. , 5. , 5. , 5. ,\n",
  3616. " 0.05040035, 0.40055451, 0.35697994, 0.18257562, 0.22687327,\n",
  3617. " 0.21119009, 0.35634197])"
  3618. ]
  3619. },
  3620. "execution_count": 16,
  3621. "metadata": {},
  3622. "output_type": "execute_result"
  3623. }
  3624. ],
  3625. "source": [
  3626. "B = A.flatten()\n",
  3627. "\n",
  3628. "B"
  3629. ]
  3630. },
  3631. {
  3632. "cell_type": "code",
  3633. "execution_count": 17,
  3634. "metadata": {},
  3635. "outputs": [
  3636. {
  3637. "name": "stdout",
  3638. "output_type": "stream",
  3639. "text": [
  3640. "(12,)\n"
  3641. ]
  3642. }
  3643. ],
  3644. "source": [
  3645. "print(B.shape)"
  3646. ]
  3647. },
  3648. {
  3649. "cell_type": "code",
  3650. "execution_count": 20,
  3651. "metadata": {},
  3652. "outputs": [
  3653. {
  3654. "name": "stdout",
  3655. "output_type": "stream",
  3656. "text": [
  3657. "[0.52082931 0.58821997 0.70808793 0.34761316 0.11281727 0.11376124\n",
  3658. " 0.08101192 0.94869316 0.49396522 0.9028535 0.88374347 0.15748069\n",
  3659. " 0.40813454 0.43204046 0.10210289 0.53834053 0.2108077 0.16937058\n",
  3660. " 0.2986501 0.3484833 0.94668855 0.55656648 0.79644948 0.42907108\n",
  3661. " 0.43089653 0.34901272 0.00796387 0.2622972 0.58181746 0.40590039\n",
  3662. " 0.74013682 0.2209137 0.9875646 0.1765581 0.67434898 0.46760903\n",
  3663. " 0.11710641 0.37788507 0.09466252 0.37517915 0.33241018 0.45899419\n",
  3664. " 0.27653395 0.3303985 0.44020914 0.93743914 0.5024886 0.48790875\n",
  3665. " 0.3113069 0.63876202 0.87791101 0.47762896 0.51462614 0.26859618\n",
  3666. " 0.79257729 0.12382349 0.33468532 0.00623251 0.7782686 0.41511344]\n"
  3667. ]
  3668. }
  3669. ],
  3670. "source": [
  3671. "T = np.random.rand(3, 4, 5)\n",
  3672. "T2 = T.flatten()\n",
  3673. "print(T2)"
  3674. ]
  3675. },
  3676. {
  3677. "cell_type": "code",
  3678. "execution_count": 18,
  3679. "metadata": {},
  3680. "outputs": [
  3681. {
  3682. "data": {
  3683. "text/plain": [
  3684. "array([10. , 10. , 10. , 10. , 10. ,\n",
  3685. " 0.05040035, 0.40055451, 0.35697994, 0.18257562, 0.22687327,\n",
  3686. " 0.21119009, 0.35634197])"
  3687. ]
  3688. },
  3689. "execution_count": 18,
  3690. "metadata": {},
  3691. "output_type": "execute_result"
  3692. }
  3693. ],
  3694. "source": [
  3695. "B[0:5] = 10\n",
  3696. "\n",
  3697. "B"
  3698. ]
  3699. },
  3700. {
  3701. "cell_type": "code",
  3702. "execution_count": 19,
  3703. "metadata": {},
  3704. "outputs": [
  3705. {
  3706. "data": {
  3707. "text/plain": [
  3708. "array([[5. , 5. , 5. ],\n",
  3709. " [5. , 5. , 0.05040035],\n",
  3710. " [0.40055451, 0.35697994, 0.18257562],\n",
  3711. " [0.22687327, 0.21119009, 0.35634197]])"
  3712. ]
  3713. },
  3714. "execution_count": 19,
  3715. "metadata": {},
  3716. "output_type": "execute_result"
  3717. }
  3718. ],
  3719. "source": [
  3720. "A # now A has not changed, because B's data is a copy of A's, not refering to the same data"
  3721. ]
  3722. },
  3723. {
  3724. "cell_type": "markdown",
  3725. "metadata": {},
  3726. "source": [
  3727. "## Adding a new dimension: newaxis"
  3728. ]
  3729. },
  3730. {
  3731. "cell_type": "markdown",
  3732. "metadata": {},
  3733. "source": [
  3734. "With `newaxis`, we can insert new dimensions in an array, for example converting a vector to a column or row matrix:"
  3735. ]
  3736. },
  3737. {
  3738. "cell_type": "code",
  3739. "execution_count": 21,
  3740. "metadata": {},
  3741. "outputs": [],
  3742. "source": [
  3743. "v = np.array([1,2,3])"
  3744. ]
  3745. },
  3746. {
  3747. "cell_type": "code",
  3748. "execution_count": 23,
  3749. "metadata": {},
  3750. "outputs": [
  3751. {
  3752. "data": {
  3753. "text/plain": [
  3754. "(3,)"
  3755. ]
  3756. },
  3757. "execution_count": 23,
  3758. "metadata": {},
  3759. "output_type": "execute_result"
  3760. }
  3761. ],
  3762. "source": [
  3763. "np.shape(v)"
  3764. ]
  3765. },
  3766. {
  3767. "cell_type": "code",
  3768. "execution_count": 24,
  3769. "metadata": {},
  3770. "outputs": [
  3771. {
  3772. "name": "stdout",
  3773. "output_type": "stream",
  3774. "text": [
  3775. "[1 2 3]\n"
  3776. ]
  3777. }
  3778. ],
  3779. "source": [
  3780. "print(v)"
  3781. ]
  3782. },
  3783. {
  3784. "cell_type": "code",
  3785. "execution_count": 29,
  3786. "metadata": {},
  3787. "outputs": [
  3788. {
  3789. "name": "stdout",
  3790. "output_type": "stream",
  3791. "text": [
  3792. "[[1]\n",
  3793. " [2]\n",
  3794. " [3]]\n"
  3795. ]
  3796. }
  3797. ],
  3798. "source": [
  3799. "v2 = v.reshape(3, 1)\n",
  3800. "print(v2)"
  3801. ]
  3802. },
  3803. {
  3804. "cell_type": "code",
  3805. "execution_count": 26,
  3806. "metadata": {},
  3807. "outputs": [
  3808. {
  3809. "data": {
  3810. "text/plain": [
  3811. "array([[1],\n",
  3812. " [2],\n",
  3813. " [3]])"
  3814. ]
  3815. },
  3816. "execution_count": 26,
  3817. "metadata": {},
  3818. "output_type": "execute_result"
  3819. }
  3820. ],
  3821. "source": [
  3822. "# make a column matrix of the vector v\n",
  3823. "v[:, np.newaxis]"
  3824. ]
  3825. },
  3826. {
  3827. "cell_type": "code",
  3828. "execution_count": 143,
  3829. "metadata": {},
  3830. "outputs": [
  3831. {
  3832. "data": {
  3833. "text/plain": [
  3834. "(3, 1)"
  3835. ]
  3836. },
  3837. "execution_count": 143,
  3838. "metadata": {},
  3839. "output_type": "execute_result"
  3840. }
  3841. ],
  3842. "source": [
  3843. "# column matrix\n",
  3844. "v[:,newaxis].shape"
  3845. ]
  3846. },
  3847. {
  3848. "cell_type": "code",
  3849. "execution_count": 144,
  3850. "metadata": {},
  3851. "outputs": [
  3852. {
  3853. "data": {
  3854. "text/plain": [
  3855. "(1, 3)"
  3856. ]
  3857. },
  3858. "execution_count": 144,
  3859. "metadata": {},
  3860. "output_type": "execute_result"
  3861. }
  3862. ],
  3863. "source": [
  3864. "# row matrix\n",
  3865. "v[newaxis,:].shape"
  3866. ]
  3867. },
  3868. {
  3869. "cell_type": "markdown",
  3870. "metadata": {},
  3871. "source": [
  3872. "## Stacking and repeating arrays"
  3873. ]
  3874. },
  3875. {
  3876. "cell_type": "markdown",
  3877. "metadata": {},
  3878. "source": [
  3879. "Using function `repeat`, `tile`, `vstack`, `hstack`, and `concatenate` we can create larger vectors and matrices from smaller ones:"
  3880. ]
  3881. },
  3882. {
  3883. "cell_type": "markdown",
  3884. "metadata": {},
  3885. "source": [
  3886. "### tile and repeat"
  3887. ]
  3888. },
  3889. {
  3890. "cell_type": "code",
  3891. "execution_count": 30,
  3892. "metadata": {},
  3893. "outputs": [],
  3894. "source": [
  3895. "a = np.array([[1, 2], [3, 4]])"
  3896. ]
  3897. },
  3898. {
  3899. "cell_type": "code",
  3900. "execution_count": 31,
  3901. "metadata": {},
  3902. "outputs": [
  3903. {
  3904. "name": "stdout",
  3905. "output_type": "stream",
  3906. "text": [
  3907. "[[1 2]\n",
  3908. " [3 4]]\n"
  3909. ]
  3910. },
  3911. {
  3912. "data": {
  3913. "text/plain": [
  3914. "array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4])"
  3915. ]
  3916. },
  3917. "execution_count": 31,
  3918. "metadata": {},
  3919. "output_type": "execute_result"
  3920. }
  3921. ],
  3922. "source": [
  3923. "print(a)\n",
  3924. "\n",
  3925. "np.repeat?\n",
  3926. "# repeat each element 3 times\n",
  3927. "np.repeat(a, 3)"
  3928. ]
  3929. },
  3930. {
  3931. "cell_type": "code",
  3932. "execution_count": 32,
  3933. "metadata": {},
  3934. "outputs": [
  3935. {
  3936. "data": {
  3937. "text/plain": [
  3938. "array([[1, 2, 1, 2, 1, 2],\n",
  3939. " [3, 4, 3, 4, 3, 4]])"
  3940. ]
  3941. },
  3942. "execution_count": 32,
  3943. "metadata": {},
  3944. "output_type": "execute_result"
  3945. }
  3946. ],
  3947. "source": [
  3948. "# tile the matrix 3 times \n",
  3949. "np.tile(a, 3)"
  3950. ]
  3951. },
  3952. {
  3953. "cell_type": "code",
  3954. "execution_count": 35,
  3955. "metadata": {},
  3956. "outputs": [
  3957. {
  3958. "data": {
  3959. "text/plain": [
  3960. "array([[1, 2, 1, 2, 1, 2],\n",
  3961. " [3, 4, 3, 4, 3, 4]])"
  3962. ]
  3963. },
  3964. "execution_count": 35,
  3965. "metadata": {},
  3966. "output_type": "execute_result"
  3967. }
  3968. ],
  3969. "source": [
  3970. "# better method\n",
  3971. "np.tile(a, (1, 3))"
  3972. ]
  3973. },
  3974. {
  3975. "cell_type": "code",
  3976. "execution_count": 34,
  3977. "metadata": {},
  3978. "outputs": [
  3979. {
  3980. "data": {
  3981. "text/plain": [
  3982. "array([[1, 2],\n",
  3983. " [3, 4],\n",
  3984. " [1, 2],\n",
  3985. " [3, 4],\n",
  3986. " [1, 2],\n",
  3987. " [3, 4]])"
  3988. ]
  3989. },
  3990. "execution_count": 34,
  3991. "metadata": {},
  3992. "output_type": "execute_result"
  3993. }
  3994. ],
  3995. "source": [
  3996. "np.tile(a, (3, 1))"
  3997. ]
  3998. },
  3999. {
  4000. "cell_type": "markdown",
  4001. "metadata": {},
  4002. "source": [
  4003. "### concatenate"
  4004. ]
  4005. },
  4006. {
  4007. "cell_type": "code",
  4008. "execution_count": 44,
  4009. "metadata": {},
  4010. "outputs": [],
  4011. "source": [
  4012. "b = np.array([[5, 6]])"
  4013. ]
  4014. },
  4015. {
  4016. "cell_type": "code",
  4017. "execution_count": 41,
  4018. "metadata": {},
  4019. "outputs": [
  4020. {
  4021. "ename": "ValueError",
  4022. "evalue": "all the input array dimensions except for the concatenation axis must match exactly",
  4023. "output_type": "error",
  4024. "traceback": [
  4025. "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
  4026. "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
  4027. "\u001b[0;32m<ipython-input-41-0ed2f549f1e6>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mconcatenate\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
  4028. "\u001b[0;31mValueError\u001b[0m: all the input array dimensions except for the concatenation axis must match exactly"
  4029. ]
  4030. }
  4031. ],
  4032. "source": [
  4033. "np.concatenate((a, b), axis=0)"
  4034. ]
  4035. },
  4036. {
  4037. "cell_type": "code",
  4038. "execution_count": 45,
  4039. "metadata": {},
  4040. "outputs": [
  4041. {
  4042. "data": {
  4043. "text/plain": [
  4044. "array([[1, 2, 5],\n",
  4045. " [3, 4, 6]])"
  4046. ]
  4047. },
  4048. "execution_count": 45,
  4049. "metadata": {},
  4050. "output_type": "execute_result"
  4051. }
  4052. ],
  4053. "source": [
  4054. "np.concatenate((a, b.T), axis=1)"
  4055. ]
  4056. },
  4057. {
  4058. "cell_type": "markdown",
  4059. "metadata": {},
  4060. "source": [
  4061. "### hstack and vstack"
  4062. ]
  4063. },
  4064. {
  4065. "cell_type": "code",
  4066. "execution_count": 46,
  4067. "metadata": {},
  4068. "outputs": [
  4069. {
  4070. "data": {
  4071. "text/plain": [
  4072. "array([[1, 2],\n",
  4073. " [3, 4],\n",
  4074. " [5, 6]])"
  4075. ]
  4076. },
  4077. "execution_count": 46,
  4078. "metadata": {},
  4079. "output_type": "execute_result"
  4080. }
  4081. ],
  4082. "source": [
  4083. "np.vstack((a,b))"
  4084. ]
  4085. },
  4086. {
  4087. "cell_type": "code",
  4088. "execution_count": 47,
  4089. "metadata": {},
  4090. "outputs": [
  4091. {
  4092. "data": {
  4093. "text/plain": [
  4094. "array([[1, 2, 5],\n",
  4095. " [3, 4, 6]])"
  4096. ]
  4097. },
  4098. "execution_count": 47,
  4099. "metadata": {},
  4100. "output_type": "execute_result"
  4101. }
  4102. ],
  4103. "source": [
  4104. "np.hstack((a,b.T))"
  4105. ]
  4106. },
  4107. {
  4108. "cell_type": "markdown",
  4109. "metadata": {},
  4110. "source": [
  4111. "## Copy and \"deep copy\""
  4112. ]
  4113. },
  4114. {
  4115. "cell_type": "markdown",
  4116. "metadata": {},
  4117. "source": [
  4118. "To achieve high performance, assignments in Python usually do not copy the underlaying objects. This is important for example when objects are passed between functions, to avoid an excessive amount of memory copying when it is not necessary (technical term: pass by reference). "
  4119. ]
  4120. },
  4121. {
  4122. "cell_type": "code",
  4123. "execution_count": 48,
  4124. "metadata": {},
  4125. "outputs": [
  4126. {
  4127. "data": {
  4128. "text/plain": [
  4129. "array([[1, 2],\n",
  4130. " [3, 4]])"
  4131. ]
  4132. },
  4133. "execution_count": 48,
  4134. "metadata": {},
  4135. "output_type": "execute_result"
  4136. }
  4137. ],
  4138. "source": [
  4139. "A = np.array([[1, 2], [3, 4]])\n",
  4140. "\n",
  4141. "A"
  4142. ]
  4143. },
  4144. {
  4145. "cell_type": "code",
  4146. "execution_count": 49,
  4147. "metadata": {},
  4148. "outputs": [],
  4149. "source": [
  4150. "# now B is referring to the same array data as A \n",
  4151. "B = A "
  4152. ]
  4153. },
  4154. {
  4155. "cell_type": "code",
  4156. "execution_count": 50,
  4157. "metadata": {},
  4158. "outputs": [
  4159. {
  4160. "data": {
  4161. "text/plain": [
  4162. "array([[10, 2],\n",
  4163. " [ 3, 4]])"
  4164. ]
  4165. },
  4166. "execution_count": 50,
  4167. "metadata": {},
  4168. "output_type": "execute_result"
  4169. }
  4170. ],
  4171. "source": [
  4172. "# changing B affects A\n",
  4173. "B[0,0] = 10\n",
  4174. "\n",
  4175. "B"
  4176. ]
  4177. },
  4178. {
  4179. "cell_type": "code",
  4180. "execution_count": 51,
  4181. "metadata": {},
  4182. "outputs": [
  4183. {
  4184. "data": {
  4185. "text/plain": [
  4186. "array([[10, 2],\n",
  4187. " [ 3, 4]])"
  4188. ]
  4189. },
  4190. "execution_count": 51,
  4191. "metadata": {},
  4192. "output_type": "execute_result"
  4193. }
  4194. ],
  4195. "source": [
  4196. "A"
  4197. ]
  4198. },
  4199. {
  4200. "cell_type": "markdown",
  4201. "metadata": {},
  4202. "source": [
  4203. "If we want to avoid this behavior, so that when we get a new completely independent object `B` copied from `A`, then we need to do a so-called \"deep copy\" using the function `copy`:"
  4204. ]
  4205. },
  4206. {
  4207. "cell_type": "code",
  4208. "execution_count": 52,
  4209. "metadata": {},
  4210. "outputs": [],
  4211. "source": [
  4212. "B = np.copy(A)"
  4213. ]
  4214. },
  4215. {
  4216. "cell_type": "code",
  4217. "execution_count": 53,
  4218. "metadata": {},
  4219. "outputs": [
  4220. {
  4221. "data": {
  4222. "text/plain": [
  4223. "array([[-5, 2],\n",
  4224. " [ 3, 4]])"
  4225. ]
  4226. },
  4227. "execution_count": 53,
  4228. "metadata": {},
  4229. "output_type": "execute_result"
  4230. }
  4231. ],
  4232. "source": [
  4233. "# now, if we modify B, A is not affected\n",
  4234. "B[0,0] = -5\n",
  4235. "\n",
  4236. "B"
  4237. ]
  4238. },
  4239. {
  4240. "cell_type": "code",
  4241. "execution_count": 54,
  4242. "metadata": {},
  4243. "outputs": [
  4244. {
  4245. "data": {
  4246. "text/plain": [
  4247. "array([[10, 2],\n",
  4248. " [ 3, 4]])"
  4249. ]
  4250. },
  4251. "execution_count": 54,
  4252. "metadata": {},
  4253. "output_type": "execute_result"
  4254. }
  4255. ],
  4256. "source": [
  4257. "A"
  4258. ]
  4259. },
  4260. {
  4261. "cell_type": "markdown",
  4262. "metadata": {},
  4263. "source": [
  4264. "## Iterating over array elements"
  4265. ]
  4266. },
  4267. {
  4268. "cell_type": "markdown",
  4269. "metadata": {},
  4270. "source": [
  4271. "Generally, we want to avoid iterating over the elements of arrays whenever we can (at all costs). The reason is that in a interpreted language like Python (or MATLAB), iterations are really slow compared to vectorized operations. \n",
  4272. "\n",
  4273. "However, sometimes iterations are unavoidable. For such cases, the Python `for` loop is the most convenient way to iterate over an array:"
  4274. ]
  4275. },
  4276. {
  4277. "cell_type": "code",
  4278. "execution_count": 55,
  4279. "metadata": {},
  4280. "outputs": [
  4281. {
  4282. "name": "stdout",
  4283. "output_type": "stream",
  4284. "text": [
  4285. "1\n",
  4286. "2\n",
  4287. "3\n",
  4288. "4\n"
  4289. ]
  4290. }
  4291. ],
  4292. "source": [
  4293. "v = np.array([1,2,3,4])\n",
  4294. "\n",
  4295. "for element in v:\n",
  4296. " print(element)"
  4297. ]
  4298. },
  4299. {
  4300. "cell_type": "code",
  4301. "execution_count": 56,
  4302. "metadata": {},
  4303. "outputs": [
  4304. {
  4305. "name": "stdout",
  4306. "output_type": "stream",
  4307. "text": [
  4308. "row [1 2]\n",
  4309. "1\n",
  4310. "2\n",
  4311. "row [3 4]\n",
  4312. "3\n",
  4313. "4\n"
  4314. ]
  4315. }
  4316. ],
  4317. "source": [
  4318. "M = np.array([[1,2], [3,4]])\n",
  4319. "\n",
  4320. "for row in M:\n",
  4321. " print(\"row\", row)\n",
  4322. " \n",
  4323. " for element in row:\n",
  4324. " print(element)"
  4325. ]
  4326. },
  4327. {
  4328. "cell_type": "markdown",
  4329. "metadata": {},
  4330. "source": [
  4331. "When we need to iterate over each element of an array and modify its elements, it is convenient to use the `enumerate` function to obtain both the element and its index in the `for` loop: "
  4332. ]
  4333. },
  4334. {
  4335. "cell_type": "code",
  4336. "execution_count": 162,
  4337. "metadata": {},
  4338. "outputs": [
  4339. {
  4340. "name": "stdout",
  4341. "output_type": "stream",
  4342. "text": [
  4343. "('row_idx', 0, 'row', array([1, 2]))\n",
  4344. "('col_idx', 0, 'element', 1)\n",
  4345. "('col_idx', 1, 'element', 2)\n",
  4346. "('row_idx', 1, 'row', array([3, 4]))\n",
  4347. "('col_idx', 0, 'element', 3)\n",
  4348. "('col_idx', 1, 'element', 4)\n"
  4349. ]
  4350. }
  4351. ],
  4352. "source": [
  4353. "for row_idx, row in enumerate(M):\n",
  4354. " print(\"row_idx\", row_idx, \"row\", row)\n",
  4355. " \n",
  4356. " for col_idx, element in enumerate(row):\n",
  4357. " print(\"col_idx\", col_idx, \"element\", element)\n",
  4358. " \n",
  4359. " # update the matrix M: square each element\n",
  4360. " M[row_idx, col_idx] = element ** 2"
  4361. ]
  4362. },
  4363. {
  4364. "cell_type": "code",
  4365. "execution_count": 163,
  4366. "metadata": {},
  4367. "outputs": [
  4368. {
  4369. "data": {
  4370. "text/plain": [
  4371. "array([[ 1, 4],\n",
  4372. " [ 9, 16]])"
  4373. ]
  4374. },
  4375. "execution_count": 163,
  4376. "metadata": {},
  4377. "output_type": "execute_result"
  4378. }
  4379. ],
  4380. "source": [
  4381. "# each element in M is now squared\n",
  4382. "M"
  4383. ]
  4384. },
  4385. {
  4386. "cell_type": "markdown",
  4387. "metadata": {},
  4388. "source": [
  4389. "## Vectorizing functions"
  4390. ]
  4391. },
  4392. {
  4393. "cell_type": "markdown",
  4394. "metadata": {},
  4395. "source": [
  4396. "As mentioned several times by now, to get good performance we should try to avoid looping over elements in our vectors and matrices, and instead use vectorized algorithms. The first step in converting a scalar algorithm to a vectorized algorithm is to make sure that the functions we write work with vector inputs."
  4397. ]
  4398. },
  4399. {
  4400. "cell_type": "code",
  4401. "execution_count": 57,
  4402. "metadata": {},
  4403. "outputs": [],
  4404. "source": [
  4405. "def Theta(x):\n",
  4406. " \"\"\"\n",
  4407. " Scalar implemenation of the Heaviside step function.\n",
  4408. " \"\"\"\n",
  4409. " if x >= 0:\n",
  4410. " return 1\n",
  4411. " else:\n",
  4412. " return 0"
  4413. ]
  4414. },
  4415. {
  4416. "cell_type": "code",
  4417. "execution_count": 58,
  4418. "metadata": {},
  4419. "outputs": [
  4420. {
  4421. "ename": "NameError",
  4422. "evalue": "name 'array' is not defined",
  4423. "output_type": "error",
  4424. "traceback": [
  4425. "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
  4426. "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)",
  4427. "\u001b[0;32m<ipython-input-58-2cb2062a7e18>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mTheta\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m3\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
  4428. "\u001b[0;31mNameError\u001b[0m: name 'array' is not defined"
  4429. ]
  4430. }
  4431. ],
  4432. "source": [
  4433. "Theta(array([-3,-2,-1,0,1,2,3]))"
  4434. ]
  4435. },
  4436. {
  4437. "cell_type": "markdown",
  4438. "metadata": {},
  4439. "source": [
  4440. "OK, that didn't work because we didn't write the `Theta` function so that it can handle a vector input... \n",
  4441. "\n",
  4442. "To get a vectorized version of Theta we can use the Numpy function `vectorize`. In many cases it can automatically vectorize a function:"
  4443. ]
  4444. },
  4445. {
  4446. "cell_type": "code",
  4447. "execution_count": 59,
  4448. "metadata": {},
  4449. "outputs": [],
  4450. "source": [
  4451. "Theta_vec = np.vectorize(Theta)"
  4452. ]
  4453. },
  4454. {
  4455. "cell_type": "code",
  4456. "execution_count": 61,
  4457. "metadata": {},
  4458. "outputs": [
  4459. {
  4460. "data": {
  4461. "text/plain": [
  4462. "array([0, 0, 0, 1, 1, 1, 1])"
  4463. ]
  4464. },
  4465. "execution_count": 61,
  4466. "metadata": {},
  4467. "output_type": "execute_result"
  4468. }
  4469. ],
  4470. "source": [
  4471. "Theta_vec(np.array([-3,-2,-1,0,1,2,3]))"
  4472. ]
  4473. },
  4474. {
  4475. "cell_type": "markdown",
  4476. "metadata": {},
  4477. "source": [
  4478. "We can also implement the function to accept a vector input from the beginning (requires more effort but might give better performance):"
  4479. ]
  4480. },
  4481. {
  4482. "cell_type": "code",
  4483. "execution_count": 62,
  4484. "metadata": {},
  4485. "outputs": [],
  4486. "source": [
  4487. "def Theta(x):\n",
  4488. " \"\"\"\n",
  4489. " Vector-aware implemenation of the Heaviside step function.\n",
  4490. " \"\"\"\n",
  4491. " return 1 * (x >= 0)"
  4492. ]
  4493. },
  4494. {
  4495. "cell_type": "code",
  4496. "execution_count": 64,
  4497. "metadata": {},
  4498. "outputs": [
  4499. {
  4500. "data": {
  4501. "text/plain": [
  4502. "array([0, 0, 0, 1, 1, 1, 1])"
  4503. ]
  4504. },
  4505. "execution_count": 64,
  4506. "metadata": {},
  4507. "output_type": "execute_result"
  4508. }
  4509. ],
  4510. "source": [
  4511. "Theta(np.array([-3,-2,-1,0,1,2,3]))"
  4512. ]
  4513. },
  4514. {
  4515. "cell_type": "code",
  4516. "execution_count": 67,
  4517. "metadata": {},
  4518. "outputs": [
  4519. {
  4520. "data": {
  4521. "text/plain": [
  4522. "array([0, 0, 0, 1, 1, 1, 1])"
  4523. ]
  4524. },
  4525. "execution_count": 67,
  4526. "metadata": {},
  4527. "output_type": "execute_result"
  4528. }
  4529. ],
  4530. "source": [
  4531. "a = np.array([-3,-2,-1,0,1,2,3])\n",
  4532. "b = a>=0\n",
  4533. "b*1"
  4534. ]
  4535. },
  4536. {
  4537. "cell_type": "code",
  4538. "execution_count": 170,
  4539. "metadata": {},
  4540. "outputs": [
  4541. {
  4542. "data": {
  4543. "text/plain": [
  4544. "(0, 1)"
  4545. ]
  4546. },
  4547. "execution_count": 170,
  4548. "metadata": {},
  4549. "output_type": "execute_result"
  4550. }
  4551. ],
  4552. "source": [
  4553. "# still works for scalars as well\n",
  4554. "Theta(-1.2), Theta(2.6)"
  4555. ]
  4556. },
  4557. {
  4558. "cell_type": "markdown",
  4559. "metadata": {},
  4560. "source": [
  4561. "## Using arrays in conditions"
  4562. ]
  4563. },
  4564. {
  4565. "cell_type": "markdown",
  4566. "metadata": {},
  4567. "source": [
  4568. "When using arrays in conditions,for example `if` statements and other boolean expressions, one needs to use `any` or `all`, which requires that any or all elements in the array evalutes to `True`:"
  4569. ]
  4570. },
  4571. {
  4572. "cell_type": "code",
  4573. "execution_count": 69,
  4574. "metadata": {},
  4575. "outputs": [
  4576. {
  4577. "data": {
  4578. "text/plain": [
  4579. "array([[1, 2],\n",
  4580. " [3, 4]])"
  4581. ]
  4582. },
  4583. "execution_count": 69,
  4584. "metadata": {},
  4585. "output_type": "execute_result"
  4586. }
  4587. ],
  4588. "source": [
  4589. "M = np.array([[1, 2], [3, 4]])\n",
  4590. "M"
  4591. ]
  4592. },
  4593. {
  4594. "cell_type": "code",
  4595. "execution_count": 71,
  4596. "metadata": {},
  4597. "outputs": [
  4598. {
  4599. "data": {
  4600. "text/plain": [
  4601. "True"
  4602. ]
  4603. },
  4604. "execution_count": 71,
  4605. "metadata": {},
  4606. "output_type": "execute_result"
  4607. }
  4608. ],
  4609. "source": [
  4610. "(M > 2).any()"
  4611. ]
  4612. },
  4613. {
  4614. "cell_type": "code",
  4615. "execution_count": 72,
  4616. "metadata": {},
  4617. "outputs": [
  4618. {
  4619. "name": "stdout",
  4620. "output_type": "stream",
  4621. "text": [
  4622. "at least one element in M is larger than 2\n"
  4623. ]
  4624. }
  4625. ],
  4626. "source": [
  4627. "if (M > 2).any():\n",
  4628. " print(\"at least one element in M is larger than 2\")\n",
  4629. "else:\n",
  4630. " print(\"no element in M is larger than 2\")"
  4631. ]
  4632. },
  4633. {
  4634. "cell_type": "code",
  4635. "execution_count": 73,
  4636. "metadata": {},
  4637. "outputs": [
  4638. {
  4639. "name": "stdout",
  4640. "output_type": "stream",
  4641. "text": [
  4642. "all elements in M are not larger than 5\n"
  4643. ]
  4644. }
  4645. ],
  4646. "source": [
  4647. "if (M > 5).all():\n",
  4648. " print(\"all elements in M are larger than 5\")\n",
  4649. "else:\n",
  4650. " print(\"all elements in M are not larger than 5\")"
  4651. ]
  4652. },
  4653. {
  4654. "cell_type": "markdown",
  4655. "metadata": {},
  4656. "source": [
  4657. "## Type casting"
  4658. ]
  4659. },
  4660. {
  4661. "cell_type": "markdown",
  4662. "metadata": {},
  4663. "source": [
  4664. "Since Numpy arrays are *statically typed*, the type of an array does not change once created. But we can explicitly cast an array of some type to another using the `astype` functions (see also the similar `asarray` function). This always create a new array of new type:"
  4665. ]
  4666. },
  4667. {
  4668. "cell_type": "code",
  4669. "execution_count": 74,
  4670. "metadata": {},
  4671. "outputs": [
  4672. {
  4673. "data": {
  4674. "text/plain": [
  4675. "dtype('int64')"
  4676. ]
  4677. },
  4678. "execution_count": 74,
  4679. "metadata": {},
  4680. "output_type": "execute_result"
  4681. }
  4682. ],
  4683. "source": [
  4684. "M.dtype"
  4685. ]
  4686. },
  4687. {
  4688. "cell_type": "code",
  4689. "execution_count": 75,
  4690. "metadata": {},
  4691. "outputs": [
  4692. {
  4693. "data": {
  4694. "text/plain": [
  4695. "array([[1., 2.],\n",
  4696. " [3., 4.]])"
  4697. ]
  4698. },
  4699. "execution_count": 75,
  4700. "metadata": {},
  4701. "output_type": "execute_result"
  4702. }
  4703. ],
  4704. "source": [
  4705. "M2 = M.astype(float)\n",
  4706. "\n",
  4707. "M2"
  4708. ]
  4709. },
  4710. {
  4711. "cell_type": "code",
  4712. "execution_count": 76,
  4713. "metadata": {},
  4714. "outputs": [
  4715. {
  4716. "data": {
  4717. "text/plain": [
  4718. "dtype('float64')"
  4719. ]
  4720. },
  4721. "execution_count": 76,
  4722. "metadata": {},
  4723. "output_type": "execute_result"
  4724. }
  4725. ],
  4726. "source": [
  4727. "M2.dtype"
  4728. ]
  4729. },
  4730. {
  4731. "cell_type": "code",
  4732. "execution_count": 77,
  4733. "metadata": {},
  4734. "outputs": [
  4735. {
  4736. "data": {
  4737. "text/plain": [
  4738. "array([[ True, True],\n",
  4739. " [ True, True]])"
  4740. ]
  4741. },
  4742. "execution_count": 77,
  4743. "metadata": {},
  4744. "output_type": "execute_result"
  4745. }
  4746. ],
  4747. "source": [
  4748. "M3 = M.astype(bool)\n",
  4749. "\n",
  4750. "M3"
  4751. ]
  4752. },
  4753. {
  4754. "cell_type": "markdown",
  4755. "metadata": {},
  4756. "source": [
  4757. "## Further reading"
  4758. ]
  4759. },
  4760. {
  4761. "cell_type": "markdown",
  4762. "metadata": {},
  4763. "source": [
  4764. "* http://numpy.scipy.org\n",
  4765. "* http://scipy.org/Tentative_NumPy_Tutorial\n",
  4766. "* http://scipy.org/NumPy_for_Matlab_Users - A Numpy guide for MATLAB users."
  4767. ]
  4768. },
  4769. {
  4770. "cell_type": "markdown",
  4771. "metadata": {},
  4772. "source": [
  4773. "## Versions"
  4774. ]
  4775. },
  4776. {
  4777. "cell_type": "code",
  4778. "execution_count": 178,
  4779. "metadata": {},
  4780. "outputs": [
  4781. {
  4782. "data": {
  4783. "application/json": {
  4784. "Software versions": [
  4785. {
  4786. "module": "Python",
  4787. "version": "2.7.10 64bit [GCC 4.2.1 (Apple Inc. build 5577)]"
  4788. },
  4789. {
  4790. "module": "IPython",
  4791. "version": "3.2.1"
  4792. },
  4793. {
  4794. "module": "OS",
  4795. "version": "Darwin 14.1.0 x86_64 i386 64bit"
  4796. },
  4797. {
  4798. "module": "numpy",
  4799. "version": "1.9.2"
  4800. }
  4801. ]
  4802. },
  4803. "text/html": [
  4804. "<table><tr><th>Software</th><th>Version</th></tr><tr><td>Python</td><td>2.7.10 64bit [GCC 4.2.1 (Apple Inc. build 5577)]</td></tr><tr><td>IPython</td><td>3.2.1</td></tr><tr><td>OS</td><td>Darwin 14.1.0 x86_64 i386 64bit</td></tr><tr><td>numpy</td><td>1.9.2</td></tr><tr><td colspan='2'>Sat Aug 15 11:02:09 2015 JST</td></tr></table>"
  4805. ],
  4806. "text/latex": [
  4807. "\\begin{tabular}{|l|l|}\\hline\n",
  4808. "{\\bf Software} & {\\bf Version} \\\\ \\hline\\hline\n",
  4809. "Python & 2.7.10 64bit [GCC 4.2.1 (Apple Inc. build 5577)] \\\\ \\hline\n",
  4810. "IPython & 3.2.1 \\\\ \\hline\n",
  4811. "OS & Darwin 14.1.0 x86\\_64 i386 64bit \\\\ \\hline\n",
  4812. "numpy & 1.9.2 \\\\ \\hline\n",
  4813. "\\hline \\multicolumn{2}{|l|}{Sat Aug 15 11:02:09 2015 JST} \\\\ \\hline\n",
  4814. "\\end{tabular}\n"
  4815. ],
  4816. "text/plain": [
  4817. "Software versions\n",
  4818. "Python 2.7.10 64bit [GCC 4.2.1 (Apple Inc. build 5577)]\n",
  4819. "IPython 3.2.1\n",
  4820. "OS Darwin 14.1.0 x86_64 i386 64bit\n",
  4821. "numpy 1.9.2\n",
  4822. "Sat Aug 15 11:02:09 2015 JST"
  4823. ]
  4824. },
  4825. "execution_count": 178,
  4826. "metadata": {},
  4827. "output_type": "execute_result"
  4828. }
  4829. ],
  4830. "source": [
  4831. "%reload_ext version_information\n",
  4832. "\n",
  4833. "%version_information numpy"
  4834. ]
  4835. }
  4836. ],
  4837. "metadata": {
  4838. "kernelspec": {
  4839. "display_name": "Python 3",
  4840. "language": "python",
  4841. "name": "python3"
  4842. },
  4843. "language_info": {
  4844. "codemirror_mode": {
  4845. "name": "ipython",
  4846. "version": 3
  4847. },
  4848. "file_extension": ".py",
  4849. "mimetype": "text/x-python",
  4850. "name": "python",
  4851. "nbconvert_exporter": "python",
  4852. "pygments_lexer": "ipython3",
  4853. "version": "3.5.2"
  4854. }
  4855. },
  4856. "nbformat": 4,
  4857. "nbformat_minor": 1
  4858. }

机器学习越来越多应用到飞行器、机器人等领域,其目的是利用计算机实现类似人类的智能,从而实现装备的智能化与无人化。本课程旨在引导学生掌握机器学习的基本知识、典型方法与技术,通过具体的应用案例激发学生对该学科的兴趣,鼓励学生能够从人工智能的角度来分析、解决飞行器、机器人所面临的问题和挑战。本课程主要内容包括Python编程基础,机器学习模型,无监督学习、监督学习、深度学习基础知识与实现,并学习如何利用机器学习解决实际问题,从而全面提升自我的《综合能力》。