|
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612 |
- {
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Numpy - 多维数据数组软件库"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "NumPy是Python中科学计算的基本软件包。它是一个Python库,提供多维数组对象、各种派生类(如掩码数组和矩阵)和各种例程。\n",
- "* 用于对数组进行快速操作,包括数学、逻辑、形状操作、排序、选择、I/O、离散傅立叶变换、基本线性代数、基本统计操作、随机模拟等等。\n",
- "* Numpy作为Python数据计算的基础广泛应用到数据处理、信号处理、机器学习等领域。"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- ""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 1. 简介"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "`numpy`包(模块)用在几乎所有使用Python的数值计算中,为Python提供高性能向量,矩阵和高维数据结构的模块。它是用C和Fortran语言实现的,因此当计算向量化数据(用向量和矩阵表示)时,性能非常的好。\n",
- "\n",
- "为了使用`numpy`模块,你先要像下面的例子一样导入这个模块:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {},
- "outputs": [],
- "source": [
- "# 这一行的作用会在Matplotlib中介绍\n",
- "%matplotlib inline\n",
- "import matplotlib.pyplot as plt"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {},
- "outputs": [],
- "source": [
- "# 不建议用这种方式导入库\n",
- "from numpy import *"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {},
- "outputs": [],
- "source": [
- "# 建议使用这种方式\n",
- "import numpy as np"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "**建议大家使用第二种导入方法** `import numpy as np`\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 2. 创建`numpy`数组"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "有很多种方法去初始化新的numpy数组, 例如从\n",
- "\n",
- "* Python列表或元组\n",
- "* 使用专门用来创建numpy arrays的函数,例如 `arange`, `linspace`等\n",
- "* 从文件中读取数据"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 2.1 从列表中"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "例如,为了从Python列表创建新的向量和矩阵我们可以用`numpy.array`函数。\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 4,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[1, 2, 3, 4]\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "array([1, 2, 3, 4])"
- ]
- },
- "execution_count": 4,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "import numpy as np\n",
- "\n",
- "a = [1, 2, 3, 4]\n",
- "print(a)\n",
- "\n",
- "# a vector: the argument to the array function is a Python list\n",
- "v = np.array(a)\n",
- "\n",
- "v"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[1 2]\n",
- " [3 4]\n",
- " [5 6]]\n",
- "\n",
- "(3, 2)\n"
- ]
- }
- ],
- "source": [
- "# 矩阵:数组函数的参数是一个嵌套的Python列表\n",
- "M = np.array([[1, 2], [3, 4], [5, 6]])\n",
- "\n",
- "print(M)\n",
- "print()\n",
- "print(M.shape)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[[ 1 2]\n",
- " [ 3 4]\n",
- " [ 5 6]]\n",
- "\n",
- " [[ 3 4]\n",
- " [ 5 6]\n",
- " [ 7 8]]\n",
- "\n",
- " [[ 5 6]\n",
- " [ 7 8]\n",
- " [ 9 10]]\n",
- "\n",
- " [[ 7 8]\n",
- " [ 9 10]\n",
- " [11 12]]]\n",
- "\n",
- "(4, 3, 2)\n"
- ]
- }
- ],
- "source": [
- "M = np.array([[[1,2], [3,4], [5,6]], \\\n",
- " [[3,4], [5,6], [7,8]], \\\n",
- " [[5,6], [7,8], [9,10]], \\\n",
- " [[7,8], [9,10], [11,12]]])\n",
- "print(M)\n",
- "print()\n",
- "print(M.shape)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "`v`和`M`两个都是属于`numpy`模块提供的`ndarray`类型。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(numpy.ndarray, numpy.ndarray)"
- ]
- },
- "execution_count": 7,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "type(v), type(M)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "`v`和`M`之间的区别仅在于他们的形状。我们可以用属性函数`ndarray.shape`得到数组形状的信息。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(4,)"
- ]
- },
- "execution_count": 8,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "v.shape"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(4, 3, 2)"
- ]
- },
- "execution_count": 9,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M.shape"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "通过属性函数`ndarray.size`我们可以得到数组中元素的个数"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "24"
- ]
- },
- "execution_count": 10,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M.size"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "同样,我们可以用函数`numpy.shape`和`numpy.size`"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(4, 3, 2)"
- ]
- },
- "execution_count": 11,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.shape(M)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "24"
- ]
- },
- "execution_count": 12,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.size(M)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "到目前为止`numpy.ndarray`看起来非常像Python列表(或嵌套列表)。为什么不简单地使用Python列表来进行计算,而不是创建一个新的数组类型?\n",
- "\n",
- "下面有几个原因:\n",
- "\n",
- "* Python列表非常普遍。它们可以包含任何类型的对象。它们是动态类型的。它们不支持矩阵和点乘等数学函数。由于动态类型的关系,为Python列表实现这类函数的效率不是很高。\n",
- "* Numpy数组是**静态类型的**和**同构的**。元素的类型是在创建数组时确定的。\n",
- "* Numpy数组是内存高效的。\n",
- "* 由于是静态类型,数学函数的快速实现,比如“numpy”数组的乘法和加法可以用编译语言实现(使用C和Fortran).\n",
- "\n",
- "利用`ndarray`的属性函数`dtype`(数据类型),我们可以看出数组的数据是那种类型。\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "dtype('int64')"
- ]
- },
- "execution_count": 13,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M.dtype"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "如果我们试图给一个numpy数组中的元素赋一个错误类型的值,我们会得到一个错误:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [
- {
- "ename": "ValueError",
- "evalue": "invalid literal for int() with base 10: 'hello'",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m<ipython-input-14-3eecc5e8509b>\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;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[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;31mValueError\u001b[0m: invalid literal for int() with base 10: 'hello'"
- ]
- }
- ],
- "source": [
- "M[0,0,0] = \"hello\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "如果我们想的话,我们可以利用`dtype`关键字参数显式地定义我们创建的数组数据类型:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1.+0.j, 2.+0.j],\n",
- " [3.+0.j, 4.+0.j]])"
- ]
- },
- "execution_count": 15,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M = np.array([[1, 2], [3, 4]], dtype=complex)\n",
- "\n",
- "M"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "常规可以伴随`dtype`使用的数据类型是:`int`, `float`, `complex`, `bool`, `object`等\n",
- "\n",
- "我们也可以显式地定义数据类型的大小,例如:`int64`, `int16`, `float128`, `complex128`。"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 2.2 使用数组生成函数"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "对于较大的数组,使用显式的Python列表人为地初始化数据是不切实际的。除此之外我们可以用`numpy`的很多函数得到不同类型的数组。有一些常用的分别是:"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### arange"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[0 1 2 3 4 5 6 7 8 9]\n",
- "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n"
- ]
- }
- ],
- "source": [
- "# 创建一个范围\n",
- "\n",
- "x = np.arange(0, 10, 1) # 参数:start, stop, step: \n",
- "y = range(0, 10, 1)\n",
- "print(x)\n",
- "print(list(y))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([-1.00000000e+00, -9.00000000e-01, -8.00000000e-01, -7.00000000e-01,\n",
- " -6.00000000e-01, -5.00000000e-01, -4.00000000e-01, -3.00000000e-01,\n",
- " -2.00000000e-01, -1.00000000e-01, -2.22044605e-16, 1.00000000e-01,\n",
- " 2.00000000e-01, 3.00000000e-01, 4.00000000e-01, 5.00000000e-01,\n",
- " 6.00000000e-01, 7.00000000e-01, 8.00000000e-01, 9.00000000e-01])"
- ]
- },
- "execution_count": 17,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = np.arange(-1, 1, 0.1)\n",
- "\n",
- "x"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### linspace and logspace"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 0. , 2.5, 5. , 7.5, 10. ])"
- ]
- },
- "execution_count": 18,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 使用linspace两边的端点也被包含进去\n",
- "np.linspace(0, 10, 5)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([1.00000000e+00, 3.03773178e+00, 9.22781435e+00, 2.80316249e+01,\n",
- " 8.51525577e+01, 2.58670631e+02, 7.85771994e+02, 2.38696456e+03,\n",
- " 7.25095809e+03, 2.20264658e+04])"
- ]
- },
- "execution_count": 19,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.logspace(0, 10, 10, base=np.e)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### mgrid"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 20,
- "metadata": {},
- "outputs": [],
- "source": [
- "y, x = np.mgrid[0:5, 0:5] # 和MATLAB中的meshgrid类似"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 21,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0, 1, 2, 3, 4],\n",
- " [0, 1, 2, 3, 4],\n",
- " [0, 1, 2, 3, 4],\n",
- " [0, 1, 2, 3, 4],\n",
- " [0, 1, 2, 3, 4]])"
- ]
- },
- "execution_count": 21,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 22,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0, 0, 0, 0, 0],\n",
- " [1, 1, 1, 1, 1],\n",
- " [2, 2, 2, 2, 2],\n",
- " [3, 3, 3, 3, 3],\n",
- " [4, 4, 4, 4, 4]])"
- ]
- },
- "execution_count": 22,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "y"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### random data"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 23,
- "metadata": {},
- "outputs": [],
- "source": [
- "from numpy import random"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 24,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[[0.57397454, 0.12434228],\n",
- " [0.74835474, 0.01034541],\n",
- " [0.91383579, 0.02807574],\n",
- " [0.14217509, 0.64698341]],\n",
- "\n",
- " [[0.65606545, 0.84787378],\n",
- " [0.31064031, 0.70205451],\n",
- " [0.30486756, 0.34702889],\n",
- " [0.47537986, 0.91154076]],\n",
- "\n",
- " [[0.32192343, 0.77700745],\n",
- " [0.80485914, 0.85919158],\n",
- " [0.29751565, 0.27228179],\n",
- " [0.57796668, 0.18255467]],\n",
- "\n",
- " [[0.50020698, 0.58134695],\n",
- " [0.14200095, 0.97556272],\n",
- " [0.32948647, 0.35170435],\n",
- " [0.27768833, 0.75059373]],\n",
- "\n",
- " [[0.23972627, 0.08461662],\n",
- " [0.1929383 , 0.80565903],\n",
- " [0.2627892 , 0.73361884],\n",
- " [0.18415944, 0.44976198]]])"
- ]
- },
- "execution_count": 24,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 均匀随机数在[0,1)区间\n",
- "random.rand(5,4,2)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 25,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[-1.74300737, 1.94689131, 0.18922227, -0.20440928],\n",
- " [ 1.31664152, -0.01176745, -0.43956951, 0.53571291],\n",
- " [ 0.02140654, -0.09635041, -1.84205831, 0.64951045],\n",
- " [ 0.35682903, 0.96657395, -0.50099255, -0.80044681]])"
- ]
- },
- "execution_count": 25,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 标准正态分布随机数\n",
- "random.randn(4,4)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### diag"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 26,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 0, 0],\n",
- " [0, 2, 0],\n",
- " [0, 0, 3]])"
- ]
- },
- "execution_count": 26,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 一个对角矩阵\n",
- "np.diag([1,2,3])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 27,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0, 0, 0, 0],\n",
- " [1, 0, 0, 0],\n",
- " [0, 2, 0, 0],\n",
- " [0, 0, 3, 0]])"
- ]
- },
- "execution_count": 27,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 从主对角线偏移的对角线\n",
- "np.diag([1,2,3], k=-1) "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### zeros and ones"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 28,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0., 0., 0.],\n",
- " [0., 0., 0.],\n",
- " [0., 0., 0.]])"
- ]
- },
- "execution_count": 28,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.zeros((3,3))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 29,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1., 1., 1.],\n",
- " [1., 1., 1.],\n",
- " [1., 1., 1.]])"
- ]
- },
- "execution_count": 29,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.ones((3,3))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 3. 文件 I/O"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 3.1 逗号分隔值 (CSV)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "对于数据文件来说一种非常常见的文件格式是逗号分割值(CSV),或者有关的格式例如TSV(制表符分隔的值)。为了从这些文件中读取数据到Numpy数组中,我们可以用`numpy.genfromtxt`函数。例如:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 30,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "1800 1 1 -6.1 -6.1 -6.1 1\r\n",
- "1800 1 2 -15.4 -15.4 -15.4 1\r\n",
- "1800 1 3 -15.0 -15.0 -15.0 1\r\n",
- "1800 1 4 -19.3 -19.3 -19.3 1\r\n",
- "1800 1 5 -16.8 -16.8 -16.8 1\r\n",
- "1800 1 6 -11.4 -11.4 -11.4 1\r\n",
- "1800 1 7 -7.6 -7.6 -7.6 1\r\n",
- "1800 1 8 -7.1 -7.1 -7.1 1\r\n",
- "1800 1 9 -10.1 -10.1 -10.1 1\r\n",
- "1800 1 10 -9.5 -9.5 -9.5 1\r\n"
- ]
- }
- ],
- "source": [
- "!head stockholm_td_adj.dat"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 31,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "\n",
- "data = np.genfromtxt('stockholm_td_adj.dat')"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 32,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(77431, 7)"
- ]
- },
- "execution_count": 32,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "data.shape"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 33,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- "<Figure size 1008x288 with 1 Axes>"
- ]
- },
- "metadata": {
- "needs_background": "light"
- },
- "output_type": "display_data"
- }
- ],
- "source": [
- "%matplotlib inline\n",
- "import matplotlib.pyplot as plt\n",
- "\n",
- "fig, ax = plt.subplots(figsize=(14,4))\n",
- "ax.plot(data[:,0]+data[:,1]/12.0+data[:,2]/365, data[:,5])\n",
- "ax.axis('tight')\n",
- "ax.set_title('tempeatures in Stockholm')\n",
- "ax.set_xlabel('year')\n",
- "ax.set_ylabel('temperature (C)');"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "使用`numpy.savetxt`我们可以将一个Numpy数组以CSV格式存入:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 34,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0.34743109, 0.34666094, 0.67796236],\n",
- " [0.37775535, 0.7452935 , 0.44639271],\n",
- " [0.7097024 , 0.54721637, 0.96400871]])"
- ]
- },
- "execution_count": 34,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M = np.random.rand(3,3)\n",
- "\n",
- "M"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 35,
- "metadata": {},
- "outputs": [],
- "source": [
- "np.savetxt(\"random-matrix.csv\", M)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 36,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "3.474310879390657414e-01 3.466609365910759966e-01 6.779623624489031775e-01\r\n",
- "3.777553531256817587e-01 7.452935047749419395e-01 4.463927097637667707e-01\r\n",
- "7.097023968559375007e-01 5.472163711854115542e-01 9.640087120207403437e-01\r\n"
- ]
- }
- ],
- "source": [
- "!cat random-matrix.csv"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 37,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "0.34743 0.34666 0.67796\r\n",
- "0.37776 0.74529 0.44639\r\n",
- "0.70970 0.54722 0.96401\r\n"
- ]
- }
- ],
- "source": [
- "np.savetxt(\"random-matrix.csv\", M, fmt='%.5f') # fmt 确定格式\n",
- "\n",
- "!cat random-matrix.csv"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 3.2 numpy 的本地文件格式"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "当存储和读取numpy数组时非常有用。利用函数`numpy.save`和`numpy.load`:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 38,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "random-matrix.npy: NumPy array, version 1.0, header length 118\r\n"
- ]
- }
- ],
- "source": [
- "np.save(\"random-matrix.npy\", M)\n",
- "\n",
- "!file random-matrix.npy"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 39,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0.34743109, 0.34666094, 0.67796236],\n",
- " [0.37775535, 0.7452935 , 0.44639271],\n",
- " [0.7097024 , 0.54721637, 0.96400871]])"
- ]
- },
- "execution_count": 39,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.load(\"random-matrix.npy\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 4. 更多Numpy数组的性质"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 40,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "int64\n",
- "8\n"
- ]
- }
- ],
- "source": [
- "M = np.array([[1, 2], [3, 4], [5, 6]])\n",
- "\n",
- "print(M.dtype)\n",
- "print(M.itemsize) # 每个元素的字节数\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 41,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "48"
- ]
- },
- "execution_count": 41,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M.nbytes # 字节数"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 42,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2"
- ]
- },
- "execution_count": 42,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M.ndim # 维度"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 5. 操作数组"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 5.1 索引"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "我们可以用方括号和下标索引元素:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 43,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1"
- ]
- },
- "execution_count": 43,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "v = np.array([1, 2, 3, 4, 5])\n",
- "\n",
- "# v 是一个向量,仅仅只有一维,取一个索引\n",
- "v[0]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 44,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "4\n",
- "4\n",
- "[3 4]\n"
- ]
- }
- ],
- "source": [
- "# M 是一个矩阵或者是一个二维的数组,取两个索引 \n",
- "print(M[1,1])\n",
- "print(M[1][1])\n",
- "print(M[1])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "如果我们省略了一个多维数组的索引,它将会返回整行(或者,总的来说,一个 N-1 维的数组)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 45,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4],\n",
- " [5, 6]])"
- ]
- },
- "execution_count": 45,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 46,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([3, 4])"
- ]
- },
- "execution_count": 46,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M[1]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "相同的事情可以利用`:`而不是索引来实现:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 47,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([3, 4])"
- ]
- },
- "execution_count": 47,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M[1,:] # 行 1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 48,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([2, 4, 6])"
- ]
- },
- "execution_count": 48,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M[:,1] # 列 1"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "我们可以用索引赋新的值给数组中的元素:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 49,
- "metadata": {},
- "outputs": [],
- "source": [
- "M[0,0] = 1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 50,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4],\n",
- " [5, 6]])"
- ]
- },
- "execution_count": 50,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 51,
- "metadata": {},
- "outputs": [],
- "source": [
- "# 对行和列也同样有用\n",
- "M[1,:] = 0\n",
- "M[:,1] = -1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 52,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 1, -1],\n",
- " [ 0, -1],\n",
- " [ 5, -1]])"
- ]
- },
- "execution_count": 52,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 5.2 切片索引"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "切片索引是语法 `M[lower:upper:step]` 的技术名称,用于提取数组的一部分:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 53,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([1, 2, 3, 4, 5])"
- ]
- },
- "execution_count": 53,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A = np.array([1,2,3,4,5])\n",
- "A"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 54,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([2, 3])"
- ]
- },
- "execution_count": 54,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A[1:3]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "切片索引到的数据是 *可变的* : 如果它们被分配了一个新值,那么从其中提取切片的原始数组将被修改:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 55,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1, -2, -3, 4, 5])"
- ]
- },
- "execution_count": 55,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A[1:3] = [-2,-3] # auto convert type\n",
- "A[1:3] = np.array([-2, -3]) \n",
- "\n",
- "A"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "我们可以省略 `M[lower:upper:step]` 中任意的三个值"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 56,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1, -2, -3, 4, 5])"
- ]
- },
- "execution_count": 56,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A[::] # lower, upper, step 都取默认值"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 57,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1, -2, -3, 4, 5])"
- ]
- },
- "execution_count": 57,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A[:]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 58,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1, -3, 5])"
- ]
- },
- "execution_count": 58,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A[::2] # step is 2, lower and upper 代表数组的开始和结束"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 59,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1, -2, -3])"
- ]
- },
- "execution_count": 59,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A[:3] # 前3个元素"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 60,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([4, 5])"
- ]
- },
- "execution_count": 60,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A[3:] # 从索引3开始的元素"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "负索引计数从数组的结束(正索引从开始):"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 61,
- "metadata": {},
- "outputs": [],
- "source": [
- "A = np.array([1,2,3,4,5])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 62,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "5"
- ]
- },
- "execution_count": 62,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A[-1] # 数组中最后一个元素"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 63,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([3, 4, 5])"
- ]
- },
- "execution_count": 63,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A[-3:] # 最后三个元素"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "索引切片的工作方式与多维数组完全相同:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 64,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 0, 1, 2, 3, 4],\n",
- " [10, 11, 12, 13, 14],\n",
- " [20, 21, 22, 23, 24],\n",
- " [30, 31, 32, 33, 34],\n",
- " [40, 41, 42, 43, 44]])"
- ]
- },
- "execution_count": 64,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A = np.array([[n+m*10 for n in range(5)] for m in range(5)])\n",
- "\n",
- "A"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 65,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[11, 12, 13],\n",
- " [21, 22, 23],\n",
- " [31, 32, 33]])"
- ]
- },
- "execution_count": 65,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 原始数组中的一个块\n",
- "A[1:4, 1:4]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 66,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 0, 2, 4],\n",
- " [20, 22, 24],\n",
- " [40, 42, 44]])"
- ]
- },
- "execution_count": 66,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 步长\n",
- "A[::2, ::2]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 5.3 花式索引"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Fancy索引是一个名称时,一个数组或列表被使用在一个索引:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 67,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[10 11 12 13 14]\n",
- " [30 31 32 33 34]\n",
- " [20 21 22 23 24]]\n",
- "[[ 0 1 2 3 4]\n",
- " [10 11 12 13 14]\n",
- " [20 21 22 23 24]\n",
- " [30 31 32 33 34]\n",
- " [40 41 42 43 44]]\n"
- ]
- }
- ],
- "source": [
- "A = np.array([[n+m*10 for n in range(5)] for m in range(5)])\n",
- "\n",
- "row_indices = [1, 3, 2]\n",
- "print(A[row_indices])\n",
- "print(A)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 68,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([11, 31, 24])"
- ]
- },
- "execution_count": 68,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "col_indices = [1, 1, -1] # 索引-1 代表最后一个元素\n",
- "A[row_indices, col_indices]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "我们也可以使用索引掩码:如果索引掩码是一个数据类型`bool`的Numpy数组,那么一个元素被选择(True)或不(False)取决于索引掩码在每个元素位置的值:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 69,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 1, 2, 3, 4])"
- ]
- },
- "execution_count": 69,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "B = np.array([n for n in range(5)])\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 70,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 2])"
- ]
- },
- "execution_count": 70,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "row_mask = np.array([True, False, True, False, False])\n",
- "B[row_mask]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 71,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 2])"
- ]
- },
- "execution_count": 71,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 相同的事情\n",
- "row_mask = np.array([1,0,1,0,0], dtype=bool)\n",
- "B[row_mask]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "这个特性对于有条件地从数组中选择元素非常有用,例如使用比较运算符:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 72,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. , 5.5, 6. ,\n",
- " 6.5, 7. , 7.5, 8. , 8.5, 9. , 9.5])"
- ]
- },
- "execution_count": 72,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = np.arange(0, 10, 0.5)\n",
- "x"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 73,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([False, False, False, False, False, False, False, False, False,\n",
- " False, False, True, True, True, True, False, False, False,\n",
- " False, False])"
- ]
- },
- "execution_count": 73,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "mask = (5 < x) * (x < 7.5)\n",
- "\n",
- "mask"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 74,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([5.5, 6. , 6.5, 7. ])"
- ]
- },
- "execution_count": 74,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x[mask]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 75,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([3.5, 4. , 4.5, 5. , 5.5])"
- ]
- },
- "execution_count": 75,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x[(3<x) * (x<6)]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 6. 用于从数组中提取数据和创建数组的函数"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 6.1 where"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "索引掩码可以使用`where`函数转换为位置索引"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 76,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(array([11, 12, 13, 14]),)"
- ]
- },
- "execution_count": 76,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = np.arange(0, 10, 0.5)\n",
- "mask = (5 < x) * (x < 7.5)\n",
- "\n",
- "indices = np.where(mask)\n",
- "\n",
- "indices"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 77,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([5.5, 6. , 6.5, 7. ])"
- ]
- },
- "execution_count": 77,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x[indices] # 这个索引等同于花式索引x[mask]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 6.2 diag"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "使用diag函数,我们还可以提取一个数组的对角线和亚对角线:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 78,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 0, 11, 22, 33, 44])"
- ]
- },
- "execution_count": 78,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.diag(A)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 79,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([10, 21, 32, 43])"
- ]
- },
- "execution_count": 79,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.diag(A, -1)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 7. 线性代数"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "向量化代码是使用Python/Numpy编写高效数值计算的关键。这意味着尽可能多的程序应该用矩阵和向量运算来表示,比如矩阵-矩阵乘法。"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 7.1 Scalar-array 操作"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "我们可以使用常用的算术运算符来对标量数组进行乘、加、减和除运算。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 80,
- "metadata": {},
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "\n",
- "v1 = np.arange(0, 5)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 81,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 2, 4, 6, 8])"
- ]
- },
- "execution_count": 81,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "v1 * 2"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 82,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([2, 3, 4, 5, 6])"
- ]
- },
- "execution_count": 82,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "v1 + 2"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 83,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[ 0 2 4 6 8]\n",
- " [20 22 24 26 28]\n",
- " [40 42 44 46 48]\n",
- " [60 62 64 66 68]\n",
- " [80 82 84 86 88]]\n",
- "[[ 2 3 4 5 6]\n",
- " [12 13 14 15 16]\n",
- " [22 23 24 25 26]\n",
- " [32 33 34 35 36]\n",
- " [42 43 44 45 46]]\n"
- ]
- }
- ],
- "source": [
- "A = np.array([[n+m*10 for n in range(5)] for m in range(5)])\n",
- "\n",
- "print(A * 2)\n",
- "\n",
- "print(A + 2)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 7.2 数组间的元素操作"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "当我们对数组进行加法、减法、乘法和除法时,默认的行为是**element-wise**操作:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 84,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0.12684531, 0.88008175, 0.00646408],\n",
- " [0.56140088, 0.06651575, 0.79145154]])"
- ]
- },
- "execution_count": 84,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A = np.random.rand(2, 3)\n",
- "\n",
- "A * A # element-wise 乘法"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 85,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([1., 4.])"
- ]
- },
- "execution_count": 85,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "v1 = np.array([1.0, 2.0])\n",
- "v1 * v1"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "如果我们用兼容的形状进行数组的乘法,我们会得到每一行的对位相乘结果:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 86,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "((2, 3), (2,))"
- ]
- },
- "execution_count": 86,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A.shape, v1.shape"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 87,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0.35615349, 0.93812672, 0.08039952],\n",
- " [0.74926689, 0.25790647, 0.88963562]])"
- ]
- },
- "execution_count": 87,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 88,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0.35615349, 1.49853379],\n",
- " [0.93812672, 0.51581293],\n",
- " [0.08039952, 1.77927125]])"
- ]
- },
- "execution_count": 88,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A.T * v1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 89,
- "metadata": {},
- "outputs": [
- {
- "ename": "ValueError",
- "evalue": "operands could not be broadcast together with shapes (2,3) (2,) ",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m<ipython-input-89-629678c55a83>\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[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;31mValueError\u001b[0m: operands could not be broadcast together with shapes (2,3) (2,) "
- ]
- }
- ],
- "source": [
- "A*v1"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 7.4 矩阵代数"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "矩阵的乘法有两种方法,第一种方法是点乘函数,它对两个参数应用矩阵-矩阵、矩阵-向量或内向量乘法"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 90,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[2.59833251, 1.8189686 , 1.32946437, 2.15441681, 1.55219543],\n",
- " [1.4561364 , 1.26875236, 0.97855704, 1.35013248, 1.05524471],\n",
- " [2.38061437, 1.70445667, 1.16297305, 2.27888345, 1.66499116],\n",
- " [1.08602725, 0.76015292, 0.46415646, 1.38753125, 1.00011024],\n",
- " [1.82122991, 1.34175794, 0.92375387, 1.74770416, 1.27559765]])"
- ]
- },
- "execution_count": 90,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A = np.random.rand(5, 5)\n",
- "v1 = np.random.rand(5, 1)\n",
- "\n",
- "np.dot(A, A)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 91,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[2.0139906 ],\n",
- " [1.41657535],\n",
- " [2.09784627],\n",
- " [1.2752073 ],\n",
- " [1.6253844 ]])"
- ]
- },
- "execution_count": 91,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.dot(A, v1)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 92,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[2.08466462]])"
- ]
- },
- "execution_count": 92,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.dot(v1.T, v1)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "另外,我们可以将数组对象投到`matrix`类型上。这将改变标准算术运算符`+, -, *` 的行为,以使用矩阵代数。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 93,
- "metadata": {},
- "outputs": [],
- "source": [
- "M = np.matrix(A)\n",
- "v = np.matrix(v1).T # make it a column vector"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 94,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "matrix([[0.45282687, 0.64874757, 0.70028245, 0.91412865, 0.36429705]])"
- ]
- },
- "execution_count": 94,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "v"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 95,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "matrix([[2.59833251, 1.8189686 , 1.32946437, 2.15441681, 1.55219543],\n",
- " [1.4561364 , 1.26875236, 0.97855704, 1.35013248, 1.05524471],\n",
- " [2.38061437, 1.70445667, 1.16297305, 2.27888345, 1.66499116],\n",
- " [1.08602725, 0.76015292, 0.46415646, 1.38753125, 1.00011024],\n",
- " [1.82122991, 1.34175794, 0.92375387, 1.74770416, 1.27559765]])"
- ]
- },
- "execution_count": 95,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M * M"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 96,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "matrix([[2.0139906 ],\n",
- " [1.41657535],\n",
- " [2.09784627],\n",
- " [1.2752073 ],\n",
- " [1.6253844 ]])"
- ]
- },
- "execution_count": 96,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M * v.T"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 97,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "matrix([[2.08466462]])"
- ]
- },
- "execution_count": 97,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 內积\n",
- "v * v.T"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "如果我们尝试用不相配的矩阵形状加,减或者乘我们会得到错误:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 98,
- "metadata": {},
- "outputs": [],
- "source": [
- "v = np.matrix([1,2,3,4,5,6]).T"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 99,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "((5, 5), (6, 1))"
- ]
- },
- "execution_count": 99,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.shape(M), np.shape(v)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 100,
- "metadata": {},
- "outputs": [
- {
- "ename": "ValueError",
- "evalue": "shapes (5,5) and (6,1) not aligned: 5 (dim 1) != 6 (dim 0)",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m<ipython-input-100-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[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;32m~/anaconda3/lib/python3.8/site-packages/numpy/matrixlib/defmatrix.py\u001b[0m in \u001b[0;36m__mul__\u001b[0;34m(self, other)\u001b[0m\n\u001b[1;32m 218\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[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 219\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[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 220\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[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 221\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[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 222\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[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;32m<__array_function__ internals>\u001b[0m in \u001b[0;36mdot\u001b[0;34m(*args, **kwargs)\u001b[0m\n",
- "\u001b[0;31mValueError\u001b[0m: shapes (5,5) and (6,1) not aligned: 5 (dim 1) != 6 (dim 0)"
- ]
- }
- ],
- "source": [
- "M * v"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 7.5 矩阵计算与数据处理"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 求逆"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 101,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[-2. , 1. ],\n",
- " [ 1.5, -0.5]])"
- ]
- },
- "execution_count": 101,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "C = np.array([[1, 2], [3, 4]])\n",
- "np.linalg.inv(C) # equivalent to C.I "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 行列式"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 102,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "-2.0000000000000004"
- ]
- },
- "execution_count": 102,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.linalg.det(C)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 数据统计\n",
- "通常将数据集存储在Numpy数组中是非常有用的。Numpy提供了许多函数用于计算数组中数据集的统计。\n",
- "\n",
- "例如,让我们从上面使用的斯德哥尔摩温度数据集计算一些属性。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 103,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(77431, 7)"
- ]
- },
- "execution_count": 103,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "import numpy as np\n",
- "data = np.genfromtxt('stockholm_td_adj.dat')\n",
- "\n",
- "# 提醒一下,温度数据集存储在数据变量中:\n",
- "np.shape(data)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### mean"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 104,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(77431, 7)\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "6.197109684751585"
- ]
- },
- "execution_count": 104,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 温度数据在第三列中\n",
- "print(data.shape)\n",
- "np.mean(data[:,3])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 105,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0.4931528475182218"
- ]
- },
- "execution_count": 105,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A = np.random.rand(4, 3)\n",
- "np.mean(A)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "在过去的200年里,斯德哥尔摩每天的平均气温大约是6.2 C。"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 标准差和方差"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 106,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(8.282271621340573, 68.59602320966341)"
- ]
- },
- "execution_count": 106,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.std(data[:,3]), np.var(data[:,3])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 最小值和最大值"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 107,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "-25.8"
- ]
- },
- "execution_count": 107,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 最低日平均温度\n",
- "data[:,3].min()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 108,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "28.3"
- ]
- },
- "execution_count": 108,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 最高日平均温度\n",
- "data[:,3].max()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### sum, prod, and trace"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 109,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
- ]
- },
- "execution_count": 109,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "d = np.arange(0, 10)\n",
- "d"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 110,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "45"
- ]
- },
- "execution_count": 110,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 将所有的元素相加\n",
- "np.sum(d)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 111,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "3628800"
- ]
- },
- "execution_count": 111,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 全元素积分\n",
- "np.prod(d+1)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 112,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 0, 1, 3, 6, 10, 15, 21, 28, 36, 45])"
- ]
- },
- "execution_count": 112,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 累计求和\n",
- "np.cumsum(d)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 113,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1, 2, 6, 24, 120, 720, 5040,\n",
- " 40320, 362880, 3628800])"
- ]
- },
- "execution_count": 113,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 累计乘积\n",
- "np.cumprod(d+1)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 114,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1.4446600641166332"
- ]
- },
- "execution_count": 114,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 计算对角线元素的和,和diag(A).sum()一样\n",
- "np.trace(A)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 7.6 数组子集的计算"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "我们可以使用索引、花式索引和从数组中提取数据的其他方法(如上所述)来计算数组中的数据子集。\n",
- "\n",
- "例如,让我们回到温度数据集:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 115,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "1800 1 1 -6.1 -6.1 -6.1 1\r\n",
- "1800 1 2 -15.4 -15.4 -15.4 1\r\n",
- "1800 1 3 -15.0 -15.0 -15.0 1\r\n"
- ]
- }
- ],
- "source": [
- "!head -n 3 stockholm_td_adj.dat"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "数据集的格式是:年,月,日,日平均气温,低,高,位置。\n",
- "\n",
- "如果我们对某个特定月份的平均温度感兴趣,比如二月,然后我们可以创建一个索引掩码,使用它来选择当月的数据:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 116,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.])"
- ]
- },
- "execution_count": 116,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.unique(data[:,1]) # 列的值从1到12"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 117,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[False False False ... False False False]\n"
- ]
- }
- ],
- "source": [
- "mask_feb = data[:,1] == 2\n",
- "print(mask_feb)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 118,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "-3.212109570736596\n",
- "5.090390768766271\n"
- ]
- }
- ],
- "source": [
- "# 温度数据实在第三行\n",
- "print(np.mean(data[mask_feb,3]))\n",
- "print(np.std(data[mask_feb,3]))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "有了这些工具,我们就有了非常强大的数据处理能力。例如,提取每年每个月的平均气温只需要几行代码:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 119,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- "<Figure size 432x288 with 1 Axes>"
- ]
- },
- "metadata": {
- "needs_background": "light"
- },
- "output_type": "display_data"
- }
- ],
- "source": [
- "%matplotlib inline\n",
- "import matplotlib.pyplot as plt\n",
- "\n",
- "months = np.unique(data[:,1])\n",
- "monthly_mean = [np.mean(data[data[:,1] == month, 3]) for month in months]\n",
- "\n",
- "fig, ax = plt.subplots()\n",
- "ax.bar(months, monthly_mean)\n",
- "ax.set_xlabel(\"Month\")\n",
- "ax.set_ylabel(\"Monthly avg. temp.\");"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 7.7 高维数据的计算"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "当例如`min`, `max`等函数应用在高维数组上时,有时将计算应用于整个数组是有用的,而且很多时候有时只基于行或列。用`axis`参数我们可以决定这个函数应该怎样表现:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 120,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0.85882078, 0.0838741 , 0.4529751 ],\n",
- " [0.32355282, 0.23641565, 0.37693805],\n",
- " [0.06769945, 0.30438005, 0.9780961 ],\n",
- " [0.46162058, 0.42681981, 0.71106984]])"
- ]
- },
- "execution_count": 120,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "import numpy as np\n",
- "\n",
- "m = np.random.rand(4,3)\n",
- "m"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 121,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0.978096099540799"
- ]
- },
- "execution_count": 121,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# global max\n",
- "m.max()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 122,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0.85882078, 0.42681981, 0.9780961 ])"
- ]
- },
- "execution_count": 122,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# max in each column\n",
- "m.max(axis=0)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 123,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0.85882078, 0.37693805, 0.9780961 , 0.71106984])"
- ]
- },
- "execution_count": 123,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# max in each row\n",
- "m.max(axis=1)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "许多其他的在`array` 和`matrix`类中的函数和方法接受同样(可选的)的关键字参数`axis`"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 8. 阵列的重塑、调整大小和堆叠"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Numpy数组的形状可以被确定而无需复制底层数据,这使得即使对于大型数组也能有较快的操作。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 124,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[0.58458652 0.95489874 0.76873658]\n",
- " [0.79144906 0.35559767 0.96031963]\n",
- " [0.55942317 0.78723157 0.3650356 ]\n",
- " [0.04685468 0.43444695 0.33839966]]\n"
- ]
- }
- ],
- "source": [
- "import numpy as np\n",
- "\n",
- "A = np.random.rand(4, 3)\n",
- "print(A)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 125,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "4 3\n"
- ]
- }
- ],
- "source": [
- "n, m = A.shape\n",
- "print(n, m)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 126,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0.58458652, 0.95489874, 0.76873658, 0.79144906, 0.35559767,\n",
- " 0.96031963, 0.55942317, 0.78723157, 0.3650356 , 0.04685468,\n",
- " 0.43444695, 0.33839966]])"
- ]
- },
- "execution_count": 126,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "B = A.reshape((1,n*m))\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 127,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[0.58458652]\n",
- " [0.95489874]\n",
- " [0.76873658]\n",
- " [0.79144906]\n",
- " [0.35559767]\n",
- " [0.96031963]\n",
- " [0.55942317]\n",
- " [0.78723157]\n",
- " [0.3650356 ]\n",
- " [0.04685468]\n",
- " [0.43444695]\n",
- " [0.33839966]]\n",
- "(12, 1)\n"
- ]
- }
- ],
- "source": [
- "B2 = A.reshape((n*m, 1))\n",
- "print(B2)\n",
- "print(B2.shape)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 128,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[5. , 5. , 5. , 5. , 5. ,\n",
- " 0.96031963, 0.55942317, 0.78723157, 0.3650356 , 0.04685468,\n",
- " 0.43444695, 0.33839966]])"
- ]
- },
- "execution_count": 128,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "B[0,0:5] = 5 # modify the array\n",
- "\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 129,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[5. , 5. , 5. ],\n",
- " [5. , 5. , 0.96031963],\n",
- " [0.55942317, 0.78723157, 0.3650356 ],\n",
- " [0.04685468, 0.43444695, 0.33839966]])"
- ]
- },
- "execution_count": 129,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A # and the original variable is also changed. B is only a different view of the same data"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "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."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 130,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([5. , 5. , 5. , 5. , 5. ,\n",
- " 0.96031963, 0.55942317, 0.78723157, 0.3650356 , 0.04685468,\n",
- " 0.43444695, 0.33839966])"
- ]
- },
- "execution_count": 130,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "B = A.flatten()\n",
- "\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 131,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(12,)\n"
- ]
- }
- ],
- "source": [
- "print(B.shape)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 132,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[0.88616566 0.11474399 0.49426839 0.86496944 0.44553257 0.01731081\n",
- " 0.26391484 0.81714822 0.9077824 0.45350327 0.34418481 0.30680307\n",
- " 0.22397584 0.96490185 0.25766897 0.1628303 0.35022665 0.87266285\n",
- " 0.14436895 0.2987234 0.04567582 0.62524215 0.03006832 0.15222984\n",
- " 0.86554462 0.30036796 0.66637188 0.51245662 0.46296801 0.53384373\n",
- " 0.90012971 0.00319531 0.48428543 0.24703543 0.53384405 0.48024175\n",
- " 0.17175873 0.1834814 0.43739033 0.64565657 0.49266811 0.72123815\n",
- " 0.57728476 0.76663343 0.68360823 0.34881945 0.64329004 0.79011718\n",
- " 0.7055079 0.32594224 0.48795517 0.43684614 0.32047664 0.63067622\n",
- " 0.24496431 0.25019593 0.57181523 0.38889906 0.53574819 0.02653888]\n"
- ]
- }
- ],
- "source": [
- "T = np.random.rand(3, 4, 5)\n",
- "T2 = T.flatten()\n",
- "print(T2)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 133,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([10. , 10. , 10. , 10. , 10. ,\n",
- " 0.96031963, 0.55942317, 0.78723157, 0.3650356 , 0.04685468,\n",
- " 0.43444695, 0.33839966])"
- ]
- },
- "execution_count": 133,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "B[0:5] = 10\n",
- "\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 134,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[5. , 5. , 5. ],\n",
- " [5. , 5. , 0.96031963],\n",
- " [0.55942317, 0.78723157, 0.3650356 ],\n",
- " [0.04685468, 0.43444695, 0.33839966]])"
- ]
- },
- "execution_count": 134,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A # 现在A并没有改变,因为B的数值是A的复制,并不指向同样的值。"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 9. 添加、删除维度:newaxis、squeeze"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "当矩阵乘法的时候,需要两个矩阵的对应的纬度保持一致才可以正确执行,有了`newaxis`,我们可以在数组中插入新的维度,例如将一个向量转换为列或行矩阵:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 135,
- "metadata": {},
- "outputs": [],
- "source": [
- "v = np.array([1,2,3])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 136,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(3,)\n",
- "[1 2 3]\n"
- ]
- }
- ],
- "source": [
- "print(np.shape(v))\n",
- "print(v)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 137,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(3, 1)\n",
- "[[1]\n",
- " [2]\n",
- " [3]]\n"
- ]
- }
- ],
- "source": [
- "v2 = v.reshape(3, 1)\n",
- "print(v2.shape)\n",
- "print(v2)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 138,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(3,)\n",
- "(3, 1)\n"
- ]
- }
- ],
- "source": [
- "# 做一个向量v的列矩阵\n",
- "v2 = v[:, np.newaxis]\n",
- "print(v.shape)\n",
- "print(v2.shape)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 139,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(3, 1)"
- ]
- },
- "execution_count": 139,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 列矩阵\n",
- "v[:,np.newaxis].shape"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 140,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(1, 3)"
- ]
- },
- "execution_count": 140,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 行矩阵\n",
- "v[np.newaxis,:].shape"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "也可以通过 `np.expand_dims` 来实现类似的操作"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 141,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(3, 1)\n",
- "[[1]\n",
- " [2]\n",
- " [3]]\n"
- ]
- }
- ],
- "source": [
- "v = np.array([1,2,3])\n",
- "v3 = np.expand_dims(v, 1)\n",
- "print(v3.shape)\n",
- "print(v3)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "在某些情况,需要将纬度为1的那个纬度删除掉,可以使用`np.squeeze`实现"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 142,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(1, 2, 3)\n",
- "[[[1 2 3]\n",
- " [2 3 4]]]\n"
- ]
- }
- ],
- "source": [
- "arr = np.array([[[1, 2, 3], [2, 3, 4]]])\n",
- "print(arr.shape)\n",
- "print(arr)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 143,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(2, 3)\n",
- "[[1 2 3]\n",
- " [2 3 4]]\n"
- ]
- }
- ],
- "source": [
- "# 实际上第一个纬度为`1`,我们不需要\n",
- "arr2 = np.squeeze(arr, 0)\n",
- "print(arr2.shape)\n",
- "print(arr2)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "需要注意:只有数组长度在该纬度上为1,那么该纬度才可以被删除;否则会报错。"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 10. 叠加和重复数组"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "利用函数`repeat`, `tile`, `vstack`, `hstack`, 和`concatenate` 可以用较小的向量和矩阵来创建更大的向量和矩阵。"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 10.1 tile and repeat"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 144,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[1 2]\n",
- " [3 4]]\n"
- ]
- }
- ],
- "source": [
- "a = np.array([[1, 2], [3, 4]])\n",
- "print(a)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 145,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4])"
- ]
- },
- "execution_count": 145,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 重复每一个元素三次\n",
- "np.repeat(a, 3)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 146,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2, 1, 2, 1, 2],\n",
- " [3, 4, 3, 4, 3, 4]])"
- ]
- },
- "execution_count": 146,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# tile the matrix 3 times \n",
- "np.tile(a, 3)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 147,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2, 1, 2, 1, 2],\n",
- " [3, 4, 3, 4, 3, 4]])"
- ]
- },
- "execution_count": 147,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 更好的方案\n",
- "np.tile(a, (1, 3))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 148,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4],\n",
- " [1, 2],\n",
- " [3, 4],\n",
- " [1, 2],\n",
- " [3, 4]])"
- ]
- },
- "execution_count": 148,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.tile(a, (3, 1))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 10.2 concatenate"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 149,
- "metadata": {},
- "outputs": [],
- "source": [
- "b = np.array([[5, 6]])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 150,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4],\n",
- " [5, 6]])"
- ]
- },
- "execution_count": 150,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.concatenate((a, b), axis=0)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 151,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2, 5],\n",
- " [3, 4, 6]])"
- ]
- },
- "execution_count": 151,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.concatenate((a, b.T), axis=1)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 10.3 hstack and vstack"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 152,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4],\n",
- " [5, 6]])"
- ]
- },
- "execution_count": 152,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.vstack((a,b))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 153,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2, 5],\n",
- " [3, 4, 6]])"
- ]
- },
- "execution_count": 153,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.hstack((a,b.T))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 11. 复制和“深度复制”"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "为了获得高性能,Python中的赋值通常不复制底层对象。例如,在函数之间传递对象时,通过引用传递从而避免不必要的大量内存复制。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 154,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4]])"
- ]
- },
- "execution_count": 154,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A = np.array([[1, 2], [3, 4]])\n",
- "\n",
- "A"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 155,
- "metadata": {},
- "outputs": [],
- "source": [
- "# 现在B和A指的是同一个数组数据\n",
- "B = A "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 156,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[10, 2],\n",
- " [ 3, 4]])"
- ]
- },
- "execution_count": 156,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 改变B影响A\n",
- "B[0,0] = 10\n",
- "\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 157,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[10, 2],\n",
- " [ 3, 4]])"
- ]
- },
- "execution_count": 157,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "如果我们想避免这种引用赋值的行为,那么当我们从 `A` 复制一个新的完全独立的对象 `B` 时,我们需要使用函数 `copy` 来做一个所谓的“深度复制”:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 158,
- "metadata": {},
- "outputs": [],
- "source": [
- "B = np.copy(A)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 159,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[-5, 2],\n",
- " [ 3, 4]])"
- ]
- },
- "execution_count": 159,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 现在如果我们改变B,A不受影响\n",
- "B[0,0] = -5\n",
- "\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 160,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[10, 2],\n",
- " [ 3, 4]])"
- ]
- },
- "execution_count": 160,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 12. 遍历数组元素"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "通常,我们希望尽可能避免遍历数组元素(不惜一切代价)。原因是在像Python(或MATLAB)这样的解释语言中,迭代与向量化操作相比真的很慢。\n",
- "\n",
- "然而,有时迭代是不可避免的。对于这种情况,Python的For循环是最方便的遍历数组的方法:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 161,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "1\n",
- "2\n",
- "3\n",
- "4\n"
- ]
- }
- ],
- "source": [
- "v = np.array([1,2,3,4])\n",
- "\n",
- "for element in v:\n",
- " print(element)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 162,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "row [1 2]\n",
- "1\n",
- "2\n",
- "row [3 4]\n",
- "3\n",
- "4\n"
- ]
- }
- ],
- "source": [
- "M = np.array([[1,2], [3,4]])\n",
- "\n",
- "for row in M:\n",
- " print(\"row\", row)\n",
- " \n",
- " for element in row:\n",
- " print(element)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "当我们需要去\n",
- "当我们需要遍历一个数组的每个元素并修改它的元素时,使用`enumerate`函数可以方便地在`for`循环中获得元素及其索引:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 163,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "row_idx 0 row [1 2]\n",
- "col_idx 0 element 1\n",
- "col_idx 1 element 2\n",
- "row_idx 1 row [3 4]\n",
- "col_idx 0 element 3\n",
- "col_idx 1 element 4\n"
- ]
- }
- ],
- "source": [
- "for row_idx, row in enumerate(M):\n",
- " print(\"row_idx\", row_idx, \"row\", row)\n",
- " \n",
- " for col_idx, element in enumerate(row):\n",
- " print(\"col_idx\", col_idx, \"element\", element)\n",
- " \n",
- " # 更新矩阵:对每个元素求平方\n",
- " M[row_idx, col_idx] = element ** 2"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 164,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 1, 4],\n",
- " [ 9, 16]])"
- ]
- },
- "execution_count": 164,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 现在矩阵里的每一个元素都已经求得平方\n",
- "M"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 13. 向量化功能"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "正如前面多次提到的,为了获得良好的性能,我们应该尽量避免对向量和矩阵中的元素进行循环,而应该使用向量化算法。将标量算法转换为向量化算法的第一步是确保我们编写的函数使用向量输入。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 165,
- "metadata": {},
- "outputs": [],
- "source": [
- "def Theta(x):\n",
- " \"\"\"\n",
- " 阶跃函数的普遍版本\n",
- " \"\"\"\n",
- " if x >= 0:\n",
- " return 1\n",
- " else:\n",
- " return 0"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 166,
- "metadata": {
- "scrolled": true
- },
- "outputs": [
- {
- "ename": "ValueError",
- "evalue": "The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m<ipython-input-166-b49266106206>\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[0mnp\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[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;32m<ipython-input-165-cb840dbb09da>\u001b[0m in \u001b[0;36mTheta\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0m阶跃函数的普遍版本\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \"\"\"\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0;32mif\u001b[0m \u001b[0mx\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\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mValueError\u001b[0m: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()"
- ]
- }
- ],
- "source": [
- "Theta(np.array([-3,-2,-1,0,1,2,3]))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "这个操作并不可行,因为所实现的 `Theta` 函数不能接收向量输入。\n",
- "\n",
- "为了得到向量化的版本,我们可以使用Numpy函数 `vectorize` 。在许多情况下,它可以自动向量化一个函数:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 167,
- "metadata": {},
- "outputs": [],
- "source": [
- "Theta_vec = np.vectorize(Theta)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 168,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 0, 0, 1, 1, 1, 1])"
- ]
- },
- "execution_count": 168,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "Theta_vec(np.array([-3,-2,-1,0,1,2,3]))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "我们也可以实现从一开始就接受矢量输入的函数(需要更多的计算,但可能会有更好的性能):"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 169,
- "metadata": {},
- "outputs": [],
- "source": [
- "def Theta(x):\n",
- " \"\"\"\n",
- " Heaviside阶跃函数的矢量感知实现。\n",
- " \"\"\"\n",
- " return 1 * (x >= 0)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 170,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 0, 0, 1, 1, 1, 1])"
- ]
- },
- "execution_count": 170,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "Theta(np.array([-3,-2,-1,0,1,2,3]))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 171,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[False False False True True True True]\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "array([0, 0, 0, 1, 1, 1, 1])"
- ]
- },
- "execution_count": 171,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = np.array([-3,-2,-1,0,1,2,3])\n",
- "b = a>=0\n",
- "print(b)\n",
- "b*1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 172,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(0, 1)"
- ]
- },
- "execution_count": 172,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 同样适用于标量\n",
- "Theta(-1.2), Theta(2.6)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 14. 在条件中使用数组"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "当在条件中使用数组时,例如`if`语句和其他布尔表达,一个需要用`any`或者`all`,这让数组任何或者所有元素都等于`True`。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 173,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4]])"
- ]
- },
- "execution_count": 173,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M = np.array([[1, 2], [3, 4]])\n",
- "M"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 174,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 174,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "(M > 2).any()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 175,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "at least one element in M is larger than 2\n"
- ]
- }
- ],
- "source": [
- "if (M > 2).any():\n",
- " print(\"at least one element in M is larger than 2\")\n",
- "else:\n",
- " print(\"no element in M is larger than 2\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 176,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "all elements in M are not larger than 5\n"
- ]
- }
- ],
- "source": [
- "if (M > 5).all():\n",
- " print(\"all elements in M are larger than 5\")\n",
- "else:\n",
- " print(\"all elements in M are not larger than 5\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 15. 类型转换"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "因为Numpy数组是*静态类型*,数组的类型一旦创建就不会改变。但是我们可以用`astype`函数(参见类似的“asarray”函数)显式地转换一个数组的类型到其他的类型,这总是创建一个新类型的新数组。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 177,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "dtype('int64')"
- ]
- },
- "execution_count": 177,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M.dtype\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 178,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1., 2.],\n",
- " [3., 4.]])"
- ]
- },
- "execution_count": 178,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M2 = M.astype(float)\n",
- "\n",
- "M2"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 179,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "dtype('float64')"
- ]
- },
- "execution_count": 179,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M2.dtype"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 180,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ True, True],\n",
- " [ True, True]])"
- ]
- },
- "execution_count": 180,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M3 = M.astype(bool)\n",
- "\n",
- "M3"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 16. 进一步学习"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "* [NumPy 简易教程](https://www.runoob.com/numpy/numpy-tutorial.html)\n",
- "* [NumPy 官方用户指南](https://www.numpy.org.cn/user/)\n",
- "* [NumPy 官方参考手册](https://www.numpy.org.cn/reference/)\n",
- "* [一个针对MATLAB使用者的Numpy教程](https://numpy.org/doc/stable/user/numpy-for-matlab-users.html)"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.8.3"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
- }
|