|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644 |
- {
- "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": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "# 这一行的作用会在Matplotlib中介绍\n",
- "%matplotlib inline\n",
- "import matplotlib.pyplot as plt"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 2,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "# 不建议用这种方式导入库\n",
- "from numpy import *"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {
- "collapsed": true
- },
- "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": 7,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[1, 2], [3, 4], [5, 6]]\n",
- "[[1 2]\n",
- " [3 4]\n",
- " [5 6]]\n",
- "\n",
- "(3, 2)\n"
- ]
- }
- ],
- "source": [
- "# 矩阵:数组函数的参数是一个嵌套的Python列表\n",
- "a = [[1, 2], [3, 4], [5, 6]]\n",
- "M = np.array(a)\n",
- "\n",
- "print(a)\n",
- "print(M)\n",
- "print()\n",
- "print(M.shape)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "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": 10,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(numpy.ndarray, numpy.ndarray)"
- ]
- },
- "execution_count": 10,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "type(v), type(M)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "`v`和`M`之间的区别仅在于他们的形状。我们可以用属性函数`ndarray.shape`得到数组形状的信息。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(4,)"
- ]
- },
- "execution_count": 11,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "v.shape"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(4, 3, 2)"
- ]
- },
- "execution_count": 12,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M.shape"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "通过属性函数`ndarray.size`我们可以得到数组中元素的个数"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "24"
- ]
- },
- "execution_count": 13,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M.size"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "同样,我们可以用函数`numpy.shape`和`numpy.size`"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(4, 3, 2)"
- ]
- },
- "execution_count": 15,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.shape(M)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "24"
- ]
- },
- "execution_count": 16,
- "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": 17,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "dtype('int64')"
- ]
- },
- "execution_count": 17,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M.dtype"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "如果我们试图给一个numpy数组中的元素赋一个错误类型的值,我们会得到一个错误:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 23,
- "metadata": {},
- "outputs": [],
- "source": [
- "M[0,0,0] = \"Hello\"\n"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "如果想显式设定类型的话,可以利用`dtype`关键字参数显式地创建给定数据类型的数组:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 25,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1.+0.j, 2.+0.j],\n",
- " [3.+0.j, 4.+0.j]])"
- ]
- },
- "execution_count": 25,
- "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": 27,
- "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": 29,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([-1.50000000e+00, -1.40000000e+00, -1.30000000e+00, -1.20000000e+00,\n",
- " -1.10000000e+00, -1.00000000e+00, -9.00000000e-01, -8.00000000e-01,\n",
- " -7.00000000e-01, -6.00000000e-01, -5.00000000e-01, -4.00000000e-01,\n",
- " -3.00000000e-01, -2.00000000e-01, -1.00000000e-01, 1.33226763e-15,\n",
- " 1.00000000e-01, 2.00000000e-01, 3.00000000e-01, 4.00000000e-01,\n",
- " 5.00000000e-01, 6.00000000e-01, 7.00000000e-01, 8.00000000e-01,\n",
- " 9.00000000e-01, 1.00000000e+00, 1.10000000e+00, 1.20000000e+00,\n",
- " 1.30000000e+00, 1.40000000e+00])"
- ]
- },
- "execution_count": 29,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = np.arange(-1.5, 1.5, 0.1)\n",
- "\n",
- "x"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### linspace and logspace"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 30,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 0. , 2.5, 5. , 7.5, 10. ])"
- ]
- },
- "execution_count": 30,
- "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": 31,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "y, x = np.mgrid[0:5, 0:5] # 和MATLAB中的meshgrid类似"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 32,
- "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": 32,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 33,
- "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": 33,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "y"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### random 数据"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 34,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "from numpy import random"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 35,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[[0.70579787, 0.45339106],\n",
- " [0.70077228, 0.42219419],\n",
- " [0.23131123, 0.03411284],\n",
- " [0.2532498 , 0.07772567]],\n",
- "\n",
- " [[0.75365153, 0.69937927],\n",
- " [0.21553641, 0.56617441],\n",
- " [0.61761472, 0.11883064],\n",
- " [0.7861052 , 0.25673121]],\n",
- "\n",
- " [[0.71446123, 0.85646903],\n",
- " [0.28415481, 0.62853095],\n",
- " [0.33432352, 0.16008364],\n",
- " [0.44492951, 0.37964323]],\n",
- "\n",
- " [[0.29149357, 0.6174702 ],\n",
- " [0.74610846, 0.29358931],\n",
- " [0.54484636, 0.6733187 ],\n",
- " [0.26218121, 0.49989907]],\n",
- "\n",
- " [[0.19261666, 0.73021809],\n",
- " [0.96694702, 0.91832708],\n",
- " [0.25561228, 0.26086337],\n",
- " [0.63901316, 0.18787211]]])"
- ]
- },
- "execution_count": 35,
- "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": 36,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 0, 0],\n",
- " [0, 2, 0],\n",
- " [0, 0, 3]])"
- ]
- },
- "execution_count": 36,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 一个对角矩阵\n",
- "np.diag([1,2,3])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 38,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0, 1, 0, 0],\n",
- " [0, 0, 2, 0],\n",
- " [0, 0, 0, 3],\n",
- " [0, 0, 0, 0]])"
- ]
- },
- "execution_count": 38,
- "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": 39,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0., 0., 0.],\n",
- " [0., 0., 0.],\n",
- " [0., 0., 0.]])"
- ]
- },
- "execution_count": 39,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.zeros((3,3))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 42,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1., 1., 1.],\n",
- " [1., 1., 1.],\n",
- " [1., 1., 1.]])"
- ]
- },
- "execution_count": 42,
- "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": 43,
- "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": 44,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "\n",
- "data = np.genfromtxt('stockholm_td_adj.dat')"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 45,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(77431, 7)"
- ]
- },
- "execution_count": 45,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "data.shape"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 46,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/png": "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\nAAAASUVORK5CYII=\n",
- "text/plain": [
- "<matplotlib.figure.Figure at 0x7ff5667f1f28>"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "%matplotlib inline\n",
- "import matplotlib.pyplot as plt\n",
- "import matplotlib as mpl\n",
- "\n",
- "mpl.rcParams['font.family'] = 'SimHei'\n",
- "plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题)\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('斯德哥尔摩的温度')\n",
- "ax.set_xlabel('年份')\n",
- "ax.set_ylabel('温度(摄氏度)');\n",
- "fig.savefig('fig-res-tempture-stockholm.pdf')"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "使用`numpy.savetxt`我们可以将一个Numpy数组以CSV格式存入:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 47,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0.82845074, 0.51029894, 0.08941169],\n",
- " [0.61403488, 0.90697888, 0.54387303],\n",
- " [0.87268988, 0.78110361, 0.53332052]])"
- ]
- },
- "execution_count": 47,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M = np.random.rand(3,3)\n",
- "\n",
- "M"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 35,
- "metadata": {
- "collapsed": true
- },
- "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": 48,
- "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": 49,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0.82845074, 0.51029894, 0.08941169],\n",
- " [0.61403488, 0.90697888, 0.54387303],\n",
- " [0.87268988, 0.78110361, 0.53332052]])"
- ]
- },
- "execution_count": 49,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.load(\"random-matrix.npy\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 4. 更多Numpy数组的性质"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 50,
- "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": 51,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "48"
- ]
- },
- "execution_count": 51,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M.nbytes # 字节数"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 52,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2"
- ]
- },
- "execution_count": 52,
- "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": 53,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1"
- ]
- },
- "execution_count": 53,
- "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": 54,
- "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": 55,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([3, 4])"
- ]
- },
- "execution_count": 55,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M[1]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "相同的事情可以利用 `:` 而不是索引来实现:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 56,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([3, 4])"
- ]
- },
- "execution_count": 56,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M[1,:] # 行 1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 57,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([2, 4, 6])"
- ]
- },
- "execution_count": 57,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M[:,1] # 列 1"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "我们可以用索引赋新的值给数组中的元素:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 58,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "M[0,0] = 1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 59,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4],\n",
- " [5, 6]])"
- ]
- },
- "execution_count": 59,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 60,
- "metadata": {
- "collapsed": true
- },
- "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": 61,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([1, 2, 3, 4, 5])"
- ]
- },
- "execution_count": 61,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A = np.array([1,2,3,4,5])\n",
- "A"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 62,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([2, 3])"
- ]
- },
- "execution_count": 62,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A[1:3]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "切片索引到的数据是 *可变的* : 如果它们被分配了一个新值,那么从其中提取切片的原始数组将被修改:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 63,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1, -2, -3, 4, 5])"
- ]
- },
- "execution_count": 63,
- "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": {
- "collapsed": true
- },
- "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": 69,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([11, 31, 24])"
- ]
- },
- "execution_count": 69,
- "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": 71,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 1, 2, 3, 4])"
- ]
- },
- "execution_count": 71,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "B = np.array([n for n in range(5)])\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 73,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 2])"
- ]
- },
- "execution_count": 73,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "row_mask = np.array([True, False, True, False, False])\n",
- "B[row_mask]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 74,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 2])"
- ]
- },
- "execution_count": 74,
- "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": 75,
- "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": 75,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = np.arange(0, 10, 0.5)\n",
- "x"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 76,
- "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": 76,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "mask = (5 < x) * (x < 7.5)\n",
- "\n",
- "mask"
- ]
- },
- {
- "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[mask]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 78,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([3.5, 4. , 4.5, 5. , 5.5])"
- ]
- },
- "execution_count": 78,
- "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": 80,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(array([11, 12, 13, 14]),)"
- ]
- },
- "execution_count": 80,
- "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": 81,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([5.5, 6. , 6.5, 7. ])"
- ]
- },
- "execution_count": 81,
- "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": 84,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[ 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"
- ]
- },
- {
- "data": {
- "text/plain": [
- "array([ 0, 11, 22, 33, 44])"
- ]
- },
- "execution_count": 84,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "print(A)\n",
- "np.diag(A)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 83,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([10, 21, 32, 43])"
- ]
- },
- "execution_count": 83,
- "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": 85,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "\n",
- "v1 = np.arange(0, 5)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 86,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 2, 4, 6, 8])"
- ]
- },
- "execution_count": 86,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "v1 * 2"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 87,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([2, 3, 4, 5, 6])"
- ]
- },
- "execution_count": 87,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "v1 + 2"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 88,
- "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": 89,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0.04644473, 0.04194416, 0.47883722],\n",
- " [0.54588546, 0.01731503, 0.6762046 ]])"
- ]
- },
- "execution_count": 89,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A = np.random.rand(2, 3)\n",
- "\n",
- "A * A # element-wise 乘法"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 90,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([1., 4.])"
- ]
- },
- "execution_count": 90,
- "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": 95,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[0.2155104 0.20480274 0.69198065]\n",
- " [0.73884062 0.1315866 0.82231661]]\n",
- "[1. 2.]\n"
- ]
- }
- ],
- "source": [
- "A.shape, v1.shape\n",
- "print(A)\n",
- "print(v1)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 99,
- "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-99-1b4232de65b6>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mA\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mv1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;31mValueError\u001b[0m: operands could not be broadcast together with shapes (2,3) (2,) "
- ]
- }
- ],
- "source": [
- "A*v1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 98,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0.2155104 , 1.47768123],\n",
- " [0.20480274, 0.2631732 ],\n",
- " [0.69198065, 1.64463321]])"
- ]
- },
- "execution_count": 98,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A.T * v1"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 7.4 矩阵代数"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "矩阵的乘法有两种方法,第一种方法是点乘函数,它对两个参数应用矩阵-矩阵、矩阵-向量或内向量乘法"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 101,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1.12309 , 2.2085345 , 1.7819952 , 1.65833535, 1.28453148],\n",
- " [0.33434263, 2.28904424, 1.42540142, 1.66026458, 1.29312083],\n",
- " [0.33457282, 1.44496209, 1.7598308 , 1.29000407, 0.62386269],\n",
- " [0.25751315, 1.78002052, 1.39686586, 1.5606918 , 0.83024555],\n",
- " [0.36376464, 1.73034161, 1.06421057, 1.11477265, 1.15680181]])"
- ]
- },
- "execution_count": 101,
- "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": 102,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1.98507978],\n",
- " [1.24839224],\n",
- " [0.93544866],\n",
- " [0.71593381],\n",
- " [1.29545275]])"
- ]
- },
- "execution_count": 102,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.dot(A, v1)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 103,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[2.25685841]])"
- ]
- },
- "execution_count": 103,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.dot(v1.T, v1)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "另外,我们可以将数组对象投到`matrix`类型上。这将改变标准算术运算符`+, -, *` 的行为,以使用矩阵代数。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 105,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "M = np.matrix(A)\n",
- "v = np.matrix(v1).T # make it a column vector"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 106,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "matrix([[0.93788751, 0.13927003, 0.978233 , 0.04281574, 0.63170904]])"
- ]
- },
- "execution_count": 106,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "v"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 107,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "matrix([[1.12309 , 2.2085345 , 1.7819952 , 1.65833535, 1.28453148],\n",
- " [0.33434263, 2.28904424, 1.42540142, 1.66026458, 1.29312083],\n",
- " [0.33457282, 1.44496209, 1.7598308 , 1.29000407, 0.62386269],\n",
- " [0.25751315, 1.78002052, 1.39686586, 1.5606918 , 0.83024555],\n",
- " [0.36376464, 1.73034161, 1.06421057, 1.11477265, 1.15680181]])"
- ]
- },
- "execution_count": 107,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M * M"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 108,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "matrix([[1.98507978],\n",
- " [1.24839224],\n",
- " [0.93544866],\n",
- " [0.71593381],\n",
- " [1.29545275]])"
- ]
- },
- "execution_count": 108,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M * v.T"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 109,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "matrix([[2.25685841]])"
- ]
- },
- "execution_count": 109,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 內积\n",
- "v * v.T"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "如果我们尝试用不相配的矩阵形状加,减或者乘我们会得到错误:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 113,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "v = np.matrix([1,2,3,4,5]).T"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 114,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "((5, 5), (5, 1))"
- ]
- },
- "execution_count": 114,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.shape(M), np.shape(v)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 115,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "matrix([[7.92376781],\n",
- " [9.47121037],\n",
- " [6.98226306],\n",
- " [7.1825789 ],\n",
- " [6.67757715]])"
- ]
- },
- "execution_count": 115,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M * v"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 7.5 矩阵计算与数据处理"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 求逆"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 116,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[-2. , 1. ],\n",
- " [ 1.5, -0.5]])"
- ]
- },
- "execution_count": 116,
- "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": 117,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "-2.0000000000000004"
- ]
- },
- "execution_count": 117,
- "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": 118,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(77431, 7)"
- ]
- },
- "execution_count": 118,
- "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": 120,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(77431, 7)\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "6.197109684751585"
- ]
- },
- "execution_count": 120,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 温度数据在第三列中\n",
- "print(data.shape)\n",
- "np.mean(data[:,3])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 121,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0.6298323446656802"
- ]
- },
- "execution_count": 121,
- "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": 123,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(8.282271621340573, 68.59602320966341)"
- ]
- },
- "execution_count": 123,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.std(data[:,3]), np.var(data[:,3])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 最小值和最大值"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 124,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "-25.8"
- ]
- },
- "execution_count": 124,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 最低日平均温度\n",
- "data[:,3].min()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 125,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "28.3"
- ]
- },
- "execution_count": 125,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 最高日平均温度\n",
- "data[:,3].max()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### sum, prod, and trace"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 126,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
- ]
- },
- "execution_count": 126,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "d = np.arange(0, 10)\n",
- "d"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 127,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "45"
- ]
- },
- "execution_count": 127,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 将所有的元素相加\n",
- "np.sum(d)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 128,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "3628800"
- ]
- },
- "execution_count": 128,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 全元素积分\n",
- "np.prod(d+1)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 129,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 0, 1, 3, 6, 10, 15, 21, 28, 36, 45])"
- ]
- },
- "execution_count": 129,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 累计求和\n",
- "np.cumsum(d)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 130,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1, 2, 6, 24, 120, 720, 5040,\n",
- " 40320, 362880, 3628800])"
- ]
- },
- "execution_count": 130,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 累计乘积\n",
- "np.cumprod(d+1)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 131,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2.3246646567243014"
- ]
- },
- "execution_count": 131,
- "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": 132,
- "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": 133,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11., 12.])"
- ]
- },
- "execution_count": 133,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.unique(data[:,1]) # 列的值从1到12"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 134,
- "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": 135,
- "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": 136,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- "<matplotlib.figure.Figure at 0x7ff5664d2128>"
- ]
- },
- "metadata": {},
- "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": 137,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0.65430115, 0.12431018, 0.49599019],\n",
- " [0.59918196, 0.72089552, 0.34269067],\n",
- " [0.74769538, 0.69686536, 0.35621994],\n",
- " [0.61852787, 0.70536225, 0.06504484]])"
- ]
- },
- "execution_count": 137,
- "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": 138,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0.7476953810023619"
- ]
- },
- "execution_count": 138,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# global max\n",
- "m.max()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 139,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0.74769538, 0.72089552, 0.49599019])"
- ]
- },
- "execution_count": 139,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# max in each column\n",
- "m.max(axis=0)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 140,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0.65430115, 0.72089552, 0.74769538, 0.70536225])"
- ]
- },
- "execution_count": 140,
- "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": 141,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[0.78519728 0.15775634 0.03890868]\n",
- " [0.48267243 0.05821189 0.96613776]\n",
- " [0.76181876 0.79747884 0.85199696]\n",
- " [0.61926823 0.27633702 0.76651623]]\n"
- ]
- }
- ],
- "source": [
- "import numpy as np\n",
- "\n",
- "A = np.random.rand(4, 3)\n",
- "print(A)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 142,
- "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": 144,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0.78519728, 0.15775634, 0.03890868, 0.48267243, 0.05821189,\n",
- " 0.96613776, 0.76181876, 0.79747884, 0.85199696, 0.61926823,\n",
- " 0.27633702, 0.76651623]])"
- ]
- },
- "execution_count": 144,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "B = A.reshape((1,n*m))\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 145,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[0.78519728]\n",
- " [0.15775634]\n",
- " [0.03890868]\n",
- " [0.48267243]\n",
- " [0.05821189]\n",
- " [0.96613776]\n",
- " [0.76181876]\n",
- " [0.79747884]\n",
- " [0.85199696]\n",
- " [0.61926823]\n",
- " [0.27633702]\n",
- " [0.76651623]]\n",
- "(12, 1)\n"
- ]
- }
- ],
- "source": [
- "B2 = A.reshape((n*m, 1))\n",
- "print(B2)\n",
- "print(B2.shape)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 146,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[5. , 5. , 5. , 5. , 5. ,\n",
- " 0.96613776, 0.76181876, 0.79747884, 0.85199696, 0.61926823,\n",
- " 0.27633702, 0.76651623]])"
- ]
- },
- "execution_count": 146,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "B[0,0:5] = 5 # modify the array\n",
- "\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 147,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[5. , 5. , 5. ],\n",
- " [5. , 5. , 0.96613776],\n",
- " [0.76181876, 0.79747884, 0.85199696],\n",
- " [0.61926823, 0.27633702, 0.76651623]])"
- ]
- },
- "execution_count": 147,
- "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": 148,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([5. , 5. , 5. , 5. , 5. ,\n",
- " 0.96613776, 0.76181876, 0.79747884, 0.85199696, 0.61926823,\n",
- " 0.27633702, 0.76651623])"
- ]
- },
- "execution_count": 148,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "B = A.flatten()\n",
- "\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 149,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(12,)\n"
- ]
- }
- ],
- "source": [
- "print(B.shape)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 150,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[0.51110357 0.36543148 0.36939715 0.14022005 0.6268352 0.00636831\n",
- " 0.82890719 0.51145062 0.16072218 0.99073929 0.96970778 0.85973022\n",
- " 0.27339743 0.93029089 0.08330827 0.95720719 0.14573418 0.77709524\n",
- " 0.97026939 0.51474888 0.82234327 0.46406383 0.05258201 0.90861813\n",
- " 0.06359622 0.22060077 0.44463362 0.88191886 0.32267272 0.5203602\n",
- " 0.39421885 0.73865461 0.75810546 0.94533578 0.70099854 0.35188207\n",
- " 0.73767664 0.8464147 0.78947462 0.49024445 0.17088021 0.9221971\n",
- " 0.26637317 0.42399527 0.67094074 0.38923384 0.7553479 0.24364291\n",
- " 0.47827327 0.60831433 0.01124522 0.59944347 0.46013596 0.18677825\n",
- " 0.87114672 0.21210642 0.2111575 0.01062604 0.41290141 0.29851044]\n"
- ]
- }
- ],
- "source": [
- "T = np.random.rand(3, 4, 5)\n",
- "T2 = T.flatten()\n",
- "print(T2)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 151,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([10. , 10. , 10. , 10. , 10. ,\n",
- " 0.96613776, 0.76181876, 0.79747884, 0.85199696, 0.61926823,\n",
- " 0.27633702, 0.76651623])"
- ]
- },
- "execution_count": 151,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "B[0:5] = 10\n",
- "\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 152,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[5. , 5. , 5. ],\n",
- " [5. , 5. , 0.96613776],\n",
- " [0.76181876, 0.79747884, 0.85199696],\n",
- " [0.61926823, 0.27633702, 0.76651623]])"
- ]
- },
- "execution_count": 152,
- "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": 153,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "v = np.array([1,2,3])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 154,
- "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": 155,
- "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": 156,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(3,)\n",
- "(3, 1)\n",
- "[[1]\n",
- " [2]\n",
- " [3]]\n"
- ]
- }
- ],
- "source": [
- "# 做一个向量v的列矩阵\n",
- "v2 = v[:, np.newaxis]\n",
- "print(v.shape)\n",
- "print(v2.shape)\n",
- "print(v2)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 157,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(3, 1)"
- ]
- },
- "execution_count": 157,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 列矩阵\n",
- "v[:,np.newaxis].shape"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 158,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(1, 3)"
- ]
- },
- "execution_count": 158,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 行矩阵\n",
- "v[np.newaxis,:].shape"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "也可以通过 `np.expand_dims` 来实现类似的操作"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 159,
- "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": 161,
- "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": 162,
- "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": 163,
- "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": 164,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4])"
- ]
- },
- "execution_count": 164,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 重复每一个元素三次\n",
- "np.repeat(a, 3)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 165,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2, 1, 2, 1, 2],\n",
- " [3, 4, 3, 4, 3, 4]])"
- ]
- },
- "execution_count": 165,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# tile the matrix 3 times \n",
- "np.tile(a, 3)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 166,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2, 1, 2, 1, 2],\n",
- " [3, 4, 3, 4, 3, 4]])"
- ]
- },
- "execution_count": 166,
- "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": 167,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "b = np.array([[5, 6]])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 168,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4],\n",
- " [5, 6]])"
- ]
- },
- "execution_count": 168,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.concatenate((a, b), axis=0)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 169,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2, 5],\n",
- " [3, 4, 6]])"
- ]
- },
- "execution_count": 169,
- "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": 170,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4],\n",
- " [5, 6]])"
- ]
- },
- "execution_count": 170,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.vstack((a,b))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 171,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2, 5],\n",
- " [3, 4, 6]])"
- ]
- },
- "execution_count": 171,
- "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": 172,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4]])"
- ]
- },
- "execution_count": 172,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A = np.array([[1, 2], [3, 4]])\n",
- "\n",
- "A"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 173,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "# 现在B和A指的是同一个数组数据\n",
- "B = A "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 174,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[10, 2],\n",
- " [ 3, 4]])"
- ]
- },
- "execution_count": 174,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 改变B影响A\n",
- "B[0,0] = 10\n",
- "\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 175,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[10, 2],\n",
- " [ 3, 4]])"
- ]
- },
- "execution_count": 175,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "如果我们想避免这种引用赋值的行为,那么当我们从 `A` 复制一个新的完全独立的对象 `B` 时,我们需要使用函数 `copy` 来做一个所谓的“深度复制”:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 176,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "B = np.copy(A)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 177,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[-5, 2],\n",
- " [ 3, 4]])"
- ]
- },
- "execution_count": 177,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 现在如果我们改变B,A不受影响\n",
- "B[0,0] = -5\n",
- "\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 178,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[10, 2],\n",
- " [ 3, 4]])"
- ]
- },
- "execution_count": 178,
- "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": 179,
- "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": 180,
- "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": 181,
- "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": 182,
- "metadata": {
- "collapsed": true
- },
- "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": 183,
- "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-183-d55419725688>\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[0m\n\u001b[0m",
- "\u001b[0;32m<ipython-input-182-5d4353a11383>\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[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[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[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;32melse\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": 184,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "Theta_vec = np.vectorize(Theta)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 185,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 0, 0, 1, 1, 1, 1])"
- ]
- },
- "execution_count": 185,
- "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": 187,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def Theta(x):\n",
- " \"\"\"\n",
- " Heaviside阶跃函数的矢量感知实现。\n",
- " \"\"\"\n",
- " return 1 * (x >= 0)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 188,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 0, 0, 1, 1, 1, 1])"
- ]
- },
- "execution_count": 188,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "Theta(np.array([-3,-2,-1,0,1,2,3]))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 189,
- "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": 189,
- "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": 190,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(0, 1)"
- ]
- },
- "execution_count": 190,
- "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": 191,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4]])"
- ]
- },
- "execution_count": 191,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M = np.array([[1, 2], [3, 4]])\n",
- "M"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 192,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 192,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "(M > 2).any()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 193,
- "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": 194,
- "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": 195,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "dtype('int64')"
- ]
- },
- "execution_count": 195,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M.dtype\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 197,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1., 2.],\n",
- " [3., 4.]])"
- ]
- },
- "execution_count": 197,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M2 = M.astype(float)\n",
- "\n",
- "M2"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 198,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "dtype('float64')"
- ]
- },
- "execution_count": 198,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M2.dtype"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 199,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ True, True],\n",
- " [ True, True]])"
- ]
- },
- "execution_count": 199,
- "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.5.4"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
- }
|