|
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601 |
- {
- "cells": [
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "# Numpy - 多维数据数组软件库"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "NumPy是Python中科学计算的基本软件包。它是一个Python库,提供多维数组对象、各种派生类(如掩码数组和矩阵)和各种例程,用于对数组进行快速操作,包括数学、逻辑、形状操作、排序、选择、I/O、离散傅立叶变换、基本线性代数、基本统计操作、随机模拟等等。Numpy作为Python数据计算的基础广泛应用到数据处理、信号处理、机器学习等领域。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 1,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "# 这一行的作用会在课程4中回答\n",
- "%matplotlib inline\n",
- "import matplotlib.pyplot as plt"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 1. 简介"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "`numpy`包(模块)用在几乎所有使用Python的数值计算中,为Python提供高性能向量,矩阵和高维数据结构的模块。它是用C和Fortran语言实现的,因此当计算向量化数据(用向量和矩阵表示)时,性能非常的好。\n",
- "\n",
- "为了使用`numpy`模块,你先要像下面的例子一样导入这个模块:"
- ]
- },
- {
- "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": 5,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[1 2]\n",
- " [3 4]\n",
- " [5 6]]\n",
- "\n",
- "(3, 2)\n"
- ]
- }
- ],
- "source": [
- "# 矩阵:数组函数的参数是一个嵌套的Python列表\n",
- "M = np.array([[1, 2], [3, 4], [5, 6]])\n",
- "\n",
- "print(M)\n",
- "print()\n",
- "print(M.shape)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 6,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[[ 1 2]\n",
- " [ 3 4]\n",
- " [ 5 6]]\n",
- "\n",
- " [[ 3 4]\n",
- " [ 5 6]\n",
- " [ 7 8]]\n",
- "\n",
- " [[ 5 6]\n",
- " [ 7 8]\n",
- " [ 9 10]]\n",
- "\n",
- " [[ 7 8]\n",
- " [ 9 10]\n",
- " [11 12]]]\n",
- "\n",
- "(4, 3, 2)\n"
- ]
- }
- ],
- "source": [
- "M = np.array([[[1,2], [3,4], [5,6]], \\\n",
- " [[3,4], [5,6], [7,8]], \\\n",
- " [[5,6], [7,8], [9,10]], \\\n",
- " [[7,8], [9,10], [11,12]]])\n",
- "print(M)\n",
- "print()\n",
- "print(M.shape)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "`v`和`M`两个都是属于`numpy`模块提供的`ndarray`类型。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(numpy.ndarray, numpy.ndarray)"
- ]
- },
- "execution_count": 7,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "type(v), type(M)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "`v`和`M`之间的区别仅在于他们的形状。我们可以用属性函数`ndarray.shape`得到数组形状的信息。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 8,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(4,)"
- ]
- },
- "execution_count": 8,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "v.shape"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 9,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(4, 3, 2)"
- ]
- },
- "execution_count": 9,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M.shape"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "通过属性函数`ndarray.size`我们可以得到数组中元素的个数"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 10,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "24"
- ]
- },
- "execution_count": 10,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M.size"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "同样,我们可以用函数`numpy.shape`和`numpy.size`"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 11,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(4, 3, 2)"
- ]
- },
- "execution_count": 11,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.shape(M)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 12,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "24"
- ]
- },
- "execution_count": 12,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.size(M)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "到目前为止`numpy.ndarray`看起来非常像Python列表(或嵌套列表)。为什么不简单地使用Python列表来进行计算,而不是创建一个新的数组类型?\n",
- "\n",
- "下面有几个原因:\n",
- "\n",
- "* Python列表非常普遍。它们可以包含任何类型的对象。它们是动态类型的。它们不支持矩阵和点乘等数学函数。由于动态类型的关系,为Python列表实现这类函数的效率不是很高。\n",
- "* Numpy数组是**静态类型的**和**同构的**。元素的类型是在创建数组时确定的。\n",
- "* Numpy数组是内存高效的。\n",
- "* 由于是静态类型,数学函数的快速实现,比如“numpy”数组的乘法和加法可以用编译语言实现(使用C和Fortran).\n",
- "\n",
- "利用`ndarray`的属性函数`dtype`(数据类型),我们可以看出数组的数据是那种类型。\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 13,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "dtype('int64')"
- ]
- },
- "execution_count": 13,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M.dtype"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "如果我们试图给一个numpy数组中的元素赋一个错误类型的值,我们会得到一个错误:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 14,
- "metadata": {},
- "outputs": [
- {
- "ename": "ValueError",
- "evalue": "invalid literal for int() with base 10: 'hello'",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m<ipython-input-14-29e6520b9101>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mM\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m\"hello\"\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;31mValueError\u001b[0m: invalid literal for int() with base 10: 'hello'"
- ]
- }
- ],
- "source": [
- "M[0,0,0] = \"hello\""
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "如果我们想的话,我们可以利用`dtype`关键字参数显式地定义我们创建的数组数据类型:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 15,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 1.+0.j, 2.+0.j],\n",
- " [ 3.+0.j, 4.+0.j]])"
- ]
- },
- "execution_count": 15,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M = np.array([[1, 2], [3, 4]], dtype=complex)\n",
- "\n",
- "M"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "常规可以伴随`dtype`使用的数据类型是:`int`, `float`, `complex`, `bool`, `object`等\n",
- "\n",
- "我们也可以显式地定义数据类型的大小,例如:`int64`, `int16`, `float128`, `complex128`。"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 2.2 使用数组生成函数"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "对于较大的数组,使用显式的Python列表人为地初始化数据是不切实际的。除此之外我们可以用`numpy`的很多函数得到不同类型的数组。有一些常用的分别是:"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### arange"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 16,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[0 1 2 3 4 5 6 7 8 9]\n",
- "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]\n"
- ]
- }
- ],
- "source": [
- "# 创建一个范围\n",
- "\n",
- "x = np.arange(0, 10, 1) # 参数:start, stop, step: \n",
- "y = range(0, 10, 1)\n",
- "print(x)\n",
- "print(list(y))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 17,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ -1.00000000e+00, -9.00000000e-01, -8.00000000e-01,\n",
- " -7.00000000e-01, -6.00000000e-01, -5.00000000e-01,\n",
- " -4.00000000e-01, -3.00000000e-01, -2.00000000e-01,\n",
- " -1.00000000e-01, -2.22044605e-16, 1.00000000e-01,\n",
- " 2.00000000e-01, 3.00000000e-01, 4.00000000e-01,\n",
- " 5.00000000e-01, 6.00000000e-01, 7.00000000e-01,\n",
- " 8.00000000e-01, 9.00000000e-01])"
- ]
- },
- "execution_count": 17,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = np.arange(-1, 1, 0.1)\n",
- "\n",
- "x"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### linspace and logspace"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 18,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 0. , 2.5, 5. , 7.5, 10. ])"
- ]
- },
- "execution_count": 18,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 使用linspace两边的端点也被包含进去\n",
- "np.linspace(0, 10, 5)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 19,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1.00000000e+00, 3.03773178e+00, 9.22781435e+00,\n",
- " 2.80316249e+01, 8.51525577e+01, 2.58670631e+02,\n",
- " 7.85771994e+02, 2.38696456e+03, 7.25095809e+03,\n",
- " 2.20264658e+04])"
- ]
- },
- "execution_count": 19,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.logspace(0, 10, 10, base=np.e)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### mgrid"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 20,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "y, x = np.mgrid[0:5, 0:5] # 和MATLAB中的meshgrid类似"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 21,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0, 1, 2, 3, 4],\n",
- " [0, 1, 2, 3, 4],\n",
- " [0, 1, 2, 3, 4],\n",
- " [0, 1, 2, 3, 4],\n",
- " [0, 1, 2, 3, 4]])"
- ]
- },
- "execution_count": 21,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 22,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0, 0, 0, 0, 0],\n",
- " [1, 1, 1, 1, 1],\n",
- " [2, 2, 2, 2, 2],\n",
- " [3, 3, 3, 3, 3],\n",
- " [4, 4, 4, 4, 4]])"
- ]
- },
- "execution_count": 22,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "y"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### random data"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 23,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "from numpy import random"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 24,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[[ 0.60075727, 0.15630186],\n",
- " [ 0.46391388, 0.48506743],\n",
- " [ 0.90538112, 0.05421682],\n",
- " [ 0.91067784, 0.41880914]],\n",
- "\n",
- " [[ 0.401939 , 0.25513185],\n",
- " [ 0.9560285 , 0.93569877],\n",
- " [ 0.49896287, 0.50711783],\n",
- " [ 0.62998221, 0.66730242]],\n",
- "\n",
- " [[ 0.60034281, 0.8434142 ],\n",
- " [ 0.42196362, 0.83827481],\n",
- " [ 0.93153457, 0.95310037],\n",
- " [ 0.41858883, 0.72000682]],\n",
- "\n",
- " [[ 0.12002494, 0.70343489],\n",
- " [ 0.80214726, 0.70486782],\n",
- " [ 0.76064254, 0.32612567],\n",
- " [ 0.74482656, 0.9349365 ]],\n",
- "\n",
- " [[ 0.33768331, 0.98046756],\n",
- " [ 0.38303703, 0.86521428],\n",
- " [ 0.89907479, 0.85245774],\n",
- " [ 0.72149711, 0.53042062]]])"
- ]
- },
- "execution_count": 24,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 均匀随机数在[0,1)区间\n",
- "random.rand(5,4,2)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 25,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[-1.07161172, 0.2853217 , 0.82574605, 1.22819547, -0.689047 ],\n",
- " [-1.54305909, 1.1029265 , -0.24372088, 0.54787454, 0.6766109 ],\n",
- " [ 0.31528874, 1.27435741, -0.36794574, 1.44889016, 0.62586719],\n",
- " [ 2.61776877, -1.33597369, -0.65109595, -0.63723391, 0.4643783 ],\n",
- " [ 0.68060333, 0.26735137, -0.90570425, -0.0126227 , -0.78972399]])"
- ]
- },
- "execution_count": 25,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 标准正态分布随机数\n",
- "random.randn(5,5)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### diag"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 26,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 0, 0],\n",
- " [0, 2, 0],\n",
- " [0, 0, 3]])"
- ]
- },
- "execution_count": 26,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 一个对角矩阵\n",
- "np.diag([1,2,3])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 27,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[0, 0, 0, 0],\n",
- " [1, 0, 0, 0],\n",
- " [0, 2, 0, 0],\n",
- " [0, 0, 3, 0]])"
- ]
- },
- "execution_count": 27,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 从主对角线偏移的对角线\n",
- "np.diag([1,2,3], k=-1) "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### zeros and ones"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 28,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 0., 0., 0.],\n",
- " [ 0., 0., 0.],\n",
- " [ 0., 0., 0.]])"
- ]
- },
- "execution_count": 28,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.zeros((3,3))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 29,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 1., 1., 1.],\n",
- " [ 1., 1., 1.],\n",
- " [ 1., 1., 1.]])"
- ]
- },
- "execution_count": 29,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.ones((3,3))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 3. 文件 I/O"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 3.1 逗号分隔值 (CSV)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "对于数据文件来说一种非常常见的文件格式是逗号分割值(CSV),或者有关的格式例如TSV(制表符分隔的值)。为了从这些文件中读取数据到Numpy数组中,我们可以用`numpy.genfromtxt`函数。例如:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 30,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "1800 1 1 -6.1 -6.1 -6.1 1\r\n",
- "1800 1 2 -15.4 -15.4 -15.4 1\r\n",
- "1800 1 3 -15.0 -15.0 -15.0 1\r\n",
- "1800 1 4 -19.3 -19.3 -19.3 1\r\n",
- "1800 1 5 -16.8 -16.8 -16.8 1\r\n",
- "1800 1 6 -11.4 -11.4 -11.4 1\r\n",
- "1800 1 7 -7.6 -7.6 -7.6 1\r\n",
- "1800 1 8 -7.1 -7.1 -7.1 1\r\n",
- "1800 1 9 -10.1 -10.1 -10.1 1\r\n",
- "1800 1 10 -9.5 -9.5 -9.5 1\r\n"
- ]
- }
- ],
- "source": [
- "!head stockholm_td_adj.dat"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 31,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "\n",
- "data = np.genfromtxt('stockholm_td_adj.dat')"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 32,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(77431, 7)"
- ]
- },
- "execution_count": 32,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "data.shape"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 33,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/png": "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\n",
- "text/plain": [
- "<matplotlib.figure.Figure at 0x7f77f28c9630>"
- ]
- },
- "metadata": {},
- "output_type": "display_data"
- }
- ],
- "source": [
- "%matplotlib inline\n",
- "import matplotlib.pyplot as plt\n",
- "\n",
- "fig, ax = plt.subplots(figsize=(14,4))\n",
- "ax.plot(data[:,0]+data[:,1]/12.0+data[:,2]/365, data[:,5])\n",
- "ax.axis('tight')\n",
- "ax.set_title('tempeatures in Stockholm')\n",
- "ax.set_xlabel('year')\n",
- "ax.set_ylabel('temperature (C)');"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "使用`numpy.savetxt`我们可以将一个Numpy数组以CSV格式存入:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 34,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 0.40419895, 0.08427188, 0.22161405],\n",
- " [ 0.40852999, 0.67285392, 0.53940215],\n",
- " [ 0.7443418 , 0.24683784, 0.14915745]])"
- ]
- },
- "execution_count": 34,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M = np.random.rand(3,3)\n",
- "\n",
- "M"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 35,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "np.savetxt(\"random-matrix.csv\", M)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 36,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "4.041989508578403001e-01 8.427188388757345106e-02 2.216140492488108960e-01\r\n",
- "4.085299911201277778e-01 6.728539192793956403e-01 5.394021463624912860e-01\r\n",
- "7.443417960136956557e-01 2.468378376599027479e-01 1.491574504522330535e-01\r\n"
- ]
- }
- ],
- "source": [
- "!cat random-matrix.csv"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 37,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "0.40420 0.08427 0.22161\r\n",
- "0.40853 0.67285 0.53940\r\n",
- "0.74434 0.24684 0.14916\r\n"
- ]
- }
- ],
- "source": [
- "np.savetxt(\"random-matrix.csv\", M, fmt='%.5f') # fmt 确定格式\n",
- "\n",
- "!cat random-matrix.csv"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 3.2 numpy 的本地文件格式"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "当存储和读取numpy数组时非常有用。利用函数`numpy.save`和`numpy.load`:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 38,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "random-matrix.npy: data\r\n"
- ]
- }
- ],
- "source": [
- "np.save(\"random-matrix.npy\", M)\n",
- "\n",
- "!file random-matrix.npy"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 39,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 0.40419895, 0.08427188, 0.22161405],\n",
- " [ 0.40852999, 0.67285392, 0.53940215],\n",
- " [ 0.7443418 , 0.24683784, 0.14915745]])"
- ]
- },
- "execution_count": 39,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.load(\"random-matrix.npy\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 4. 更多Numpy数组的性质"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 40,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "int64\n",
- "8\n"
- ]
- }
- ],
- "source": [
- "M = np.array([[1, 2], [3, 4], [5, 6]])\n",
- "\n",
- "print(M.dtype)\n",
- "print(M.itemsize) # 每个元素的字节数\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 41,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "48"
- ]
- },
- "execution_count": 41,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M.nbytes # 字节数"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 42,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "2"
- ]
- },
- "execution_count": 42,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M.ndim # 维度"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 5. 操作数组"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 5.1 索引"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "我们可以用方括号和下标索引元素:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 43,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1"
- ]
- },
- "execution_count": 43,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "v = np.array([1, 2, 3, 4, 5])\n",
- "\n",
- "# v 是一个向量,仅仅只有一维,取一个索引\n",
- "v[0]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 44,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "4\n",
- "4\n",
- "[3 4]\n"
- ]
- }
- ],
- "source": [
- "# M 是一个矩阵或者是一个二维的数组,取两个索引 \n",
- "print(M[1,1])\n",
- "print(M[1][1])\n",
- "print(M[1])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "如果我们省略了一个多维数组的索引,它将会返回整行(或者,总的来说,一个 N-1 维的数组)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 45,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4],\n",
- " [5, 6]])"
- ]
- },
- "execution_count": 45,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 46,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([3, 4])"
- ]
- },
- "execution_count": 46,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M[1]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "相同的事情可以利用`:`而不是索引来实现:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 47,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([3, 4])"
- ]
- },
- "execution_count": 47,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M[1,:] # 行 1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 48,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([2, 4, 6])"
- ]
- },
- "execution_count": 48,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M[:,1] # 列 1"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "我们可以用索引赋新的值给数组中的元素:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 49,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "M[0,0] = 1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 50,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4],\n",
- " [5, 6]])"
- ]
- },
- "execution_count": 50,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 51,
- "metadata": {
- "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": 53,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([1, 2, 3, 4, 5])"
- ]
- },
- "execution_count": 53,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A = np.array([1,2,3,4,5])\n",
- "A"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 54,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([2, 3])"
- ]
- },
- "execution_count": 54,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A[1:3]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "切片索引到的数据是 *可变的* : 如果它们被分配了一个新值,那么从其中提取切片的原始数组将被修改:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 55,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1, -2, -3, 4, 5])"
- ]
- },
- "execution_count": 55,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A[1:3] = [-2,-3] # auto convert type\n",
- "A[1:3] = np.array([-2, -3]) \n",
- "\n",
- "A"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "我们可以省略 `M[lower:upper:step]` 中任意的三个值"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 56,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1, -2, -3, 4, 5])"
- ]
- },
- "execution_count": 56,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A[::] # lower, upper, step 都取默认值"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 57,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1, -2, -3, 4, 5])"
- ]
- },
- "execution_count": 57,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A[:]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 58,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1, -3, 5])"
- ]
- },
- "execution_count": 58,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A[::2] # step is 2, lower and upper 代表数组的开始和结束"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 59,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1, -2, -3])"
- ]
- },
- "execution_count": 59,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A[:3] # 前3个元素"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 60,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([4, 5])"
- ]
- },
- "execution_count": 60,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A[3:] # 从索引3开始的元素"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "负索引计数从数组的结束(正索引从开始):"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 61,
- "metadata": {
- "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",
- " [20 21 22 23 24]\n",
- " [30 31 32 33 34]]\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, 2, 3]\n",
- "print(A[row_indices])\n",
- "print(A)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 68,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([11, 21, 34])"
- ]
- },
- "execution_count": 68,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "col_indices = [1, 1, -1] # 索引-1 代表最后一个元素\n",
- "A[row_indices, col_indices]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "我们也可以使用索引掩码:如果索引掩码是一个数据类型`bool`的Numpy数组,那么一个元素被选择(True)或不(False)取决于索引掩码在每个元素位置的值:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 69,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 1, 2, 3, 4])"
- ]
- },
- "execution_count": 69,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "B = np.array([n for n in range(5)])\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 70,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 2])"
- ]
- },
- "execution_count": 70,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "row_mask = np.array([True, False, True, False, False])\n",
- "B[row_mask]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 71,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 2])"
- ]
- },
- "execution_count": 71,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 相同的事情\n",
- "row_mask = np.array([1,0,1,0,0], dtype=bool)\n",
- "B[row_mask]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "这个特性对于有条件地从数组中选择元素非常有用,例如使用比较运算符:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 72,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 0. , 0.5, 1. , 1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5, 5. ,\n",
- " 5.5, 6. , 6.5, 7. , 7.5, 8. , 8.5, 9. , 9.5])"
- ]
- },
- "execution_count": 72,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = np.arange(0, 10, 0.5)\n",
- "x"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 73,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([False, False, False, False, False, False, False, False, False,\n",
- " False, False, True, True, True, True, False, False, False,\n",
- " False, False], dtype=bool)"
- ]
- },
- "execution_count": 73,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "mask = (5 < x) * (x < 7.5)\n",
- "\n",
- "mask"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 74,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 5.5, 6. , 6.5, 7. ])"
- ]
- },
- "execution_count": 74,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x[mask]"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 75,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 3.5, 4. , 4.5, 5. , 5.5])"
- ]
- },
- "execution_count": 75,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x[(3<x) * (x<6)]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 6. 用于从数组中提取数据和创建数组的函数"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 6.1 where"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "索引掩码可以使用`where`函数转换为位置索引"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 76,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(array([11, 12, 13, 14]),)"
- ]
- },
- "execution_count": 76,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x = np.arange(0, 10, 0.5)\n",
- "mask = (5 < x) * (x < 7.5)\n",
- "\n",
- "indices = np.where(mask)\n",
- "\n",
- "indices"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 77,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 5.5, 6. , 6.5, 7. ])"
- ]
- },
- "execution_count": 77,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "x[indices] # 这个索引等同于花式索引x[mask]"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 6.2 diag"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "使用diag函数,我们还可以提取一个数组的对角线和亚对角线:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 78,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 0, 11, 22, 33, 44])"
- ]
- },
- "execution_count": 78,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.diag(A)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 79,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([10, 21, 32, 43])"
- ]
- },
- "execution_count": 79,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.diag(A, -1)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 7. 线性代数"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "向量化代码是使用Python/Numpy编写高效数值计算的关键。这意味着尽可能多的程序应该用矩阵和向量运算来表示,比如矩阵-矩阵乘法。"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 7.1 Scalar-array 操作"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "我们可以使用常用的算术运算符来对标量数组进行乘、加、减和除运算。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 80,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "import numpy as np\n",
- "\n",
- "v1 = np.arange(0, 5)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 81,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 2, 4, 6, 8])"
- ]
- },
- "execution_count": 81,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "v1 * 2"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 82,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([2, 3, 4, 5, 6])"
- ]
- },
- "execution_count": 82,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "v1 + 2"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 85,
- "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": 86,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 0.89071845, 0.43820802, 0.00174379],\n",
- " [ 0.09145823, 0.43255262, 0.92711999]])"
- ]
- },
- "execution_count": 86,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A = np.random.rand(2, 3)\n",
- "\n",
- "A * A # element-wise 乘法"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 87,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1., 4.])"
- ]
- },
- "execution_count": 87,
- "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": 88,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "((2, 3), (2,))"
- ]
- },
- "execution_count": 88,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A.shape, v1.shape"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 89,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 0.94377881, 0.60484122],\n",
- " [ 0.66197282, 1.31537465],\n",
- " [ 0.04175867, 1.9257414 ]])"
- ]
- },
- "execution_count": 89,
- "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": 90,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 0.59643286, 0.4653348 , 0.57741635, 1.17254174, 0.72793731],\n",
- " [ 1.47806455, 1.31240663, 1.20235573, 1.39309699, 1.66608997],\n",
- " [ 0.80131817, 0.65322256, 0.72681869, 0.8706077 , 0.88596163],\n",
- " [ 0.2958791 , 0.40685724, 0.41545881, 0.65695879, 0.50382293],\n",
- " [ 0.95206345, 0.9416232 , 0.77704822, 0.71930884, 1.14732818]])"
- ]
- },
- "execution_count": 90,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A = np.random.rand(5, 5)\n",
- "v1 = np.random.rand(5, 1)\n",
- "\n",
- "np.dot(A, A)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 91,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 0.75186642],\n",
- " [ 1.39057812],\n",
- " [ 0.92080638],\n",
- " [ 0.43070795],\n",
- " [ 0.6868286 ]])"
- ]
- },
- "execution_count": 91,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.dot(A, v1)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 92,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 1.23992683]])"
- ]
- },
- "execution_count": 92,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.dot(v1.T, v1)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "另外,我们可以将数组对象投到`matrix`类型上。这将改变标准算术运算符`+, -, *` 的行为,以使用矩阵代数。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 93,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "M = np.matrix(A)\n",
- "v = np.matrix(v1).T # make it a column vector"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 94,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "matrix([[ 0.46260903, 0.26998047, 0.92455144, 0.15331421, 0.27336725]])"
- ]
- },
- "execution_count": 94,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "v"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 95,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "matrix([[ 0.59643286, 0.4653348 , 0.57741635, 1.17254174, 0.72793731],\n",
- " [ 1.47806455, 1.31240663, 1.20235573, 1.39309699, 1.66608997],\n",
- " [ 0.80131817, 0.65322256, 0.72681869, 0.8706077 , 0.88596163],\n",
- " [ 0.2958791 , 0.40685724, 0.41545881, 0.65695879, 0.50382293],\n",
- " [ 0.95206345, 0.9416232 , 0.77704822, 0.71930884, 1.14732818]])"
- ]
- },
- "execution_count": 95,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M * M"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 96,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "matrix([[ 0.75186642],\n",
- " [ 1.39057812],\n",
- " [ 0.92080638],\n",
- " [ 0.43070795],\n",
- " [ 0.6868286 ]])"
- ]
- },
- "execution_count": 96,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M * v.T"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 97,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "matrix([[ 1.23992683]])"
- ]
- },
- "execution_count": 97,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 內积\n",
- "v * v.T"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "如果我们尝试用不相配的矩阵形状加,减或者乘我们会得到错误:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 98,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "v = np.matrix([1,2,3,4,5,6]).T"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 99,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "((5, 5), (6, 1))"
- ]
- },
- "execution_count": 99,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.shape(M), np.shape(v)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 100,
- "metadata": {},
- "outputs": [
- {
- "ename": "ValueError",
- "evalue": "shapes (5,5) and (6,1) not aligned: 5 (dim 1) != 6 (dim 0)",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m<ipython-input-100-995fb48ad0cc>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mM\u001b[0m \u001b[0;34m*\u001b[0m \u001b[0mv\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
- "\u001b[0;32m~/anaconda3/envs/dl/lib/python3.5/site-packages/numpy/matrixlib/defmatrix.py\u001b[0m in \u001b[0;36m__mul__\u001b[0;34m(self, other)\u001b[0m\n\u001b[1;32m 307\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mother\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mN\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mndarray\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 308\u001b[0m \u001b[0;31m# This promotes 1-D vectors to row vectors\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 309\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mN\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0masmatrix\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mother\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 310\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misscalar\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mother\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mhasattr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mother\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'__rmul__'\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 311\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mN\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mother\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n",
- "\u001b[0;31mValueError\u001b[0m: shapes (5,5) and (6,1) not aligned: 5 (dim 1) != 6 (dim 0)"
- ]
- }
- ],
- "source": [
- "M * v"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 7.5 矩阵计算与数据处理"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 求逆"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 101,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[-2. , 1. ],\n",
- " [ 1.5, -0.5]])"
- ]
- },
- "execution_count": 101,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "C = np.array([[1, 2], [3, 4]])\n",
- "np.linalg.inv(C) # equivalent to C.I "
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 行列式"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 102,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "-2.0000000000000004"
- ]
- },
- "execution_count": 102,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.linalg.det(C)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 数据统计\n",
- "通常将数据集存储在Numpy数组中是非常有用的。Numpy提供了许多函数用于计算数组中数据集的统计。\n",
- "\n",
- "例如,让我们从上面使用的斯德哥尔摩温度数据集计算一些属性。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 103,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(77431, 7)"
- ]
- },
- "execution_count": 103,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "import numpy as np\n",
- "data = np.genfromtxt('stockholm_td_adj.dat')\n",
- "\n",
- "# 提醒一下,温度数据集存储在数据变量中:\n",
- "np.shape(data)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### mean"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 104,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(77431, 7)\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "6.1971096847515854"
- ]
- },
- "execution_count": 104,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 温度数据在第三列中\n",
- "print(data.shape)\n",
- "np.mean(data[:,3])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 105,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0.37336549310896566"
- ]
- },
- "execution_count": 105,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A = np.random.rand(4, 3)\n",
- "np.mean(A)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "在过去的200年里,斯德哥尔摩每天的平均气温大约是6.2 C。"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 标准差和方差"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 106,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(8.2822716213405734, 68.596023209663414)"
- ]
- },
- "execution_count": 106,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.std(data[:,3]), np.var(data[:,3])"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### 最小值和最大值"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 107,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "-25.800000000000001"
- ]
- },
- "execution_count": 107,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 最低日平均温度\n",
- "data[:,3].min()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 108,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "28.300000000000001"
- ]
- },
- "execution_count": 108,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 最高日平均温度\n",
- "data[:,3].max()"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "#### sum, prod, and trace"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 109,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])"
- ]
- },
- "execution_count": 109,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "d = np.arange(0, 10)\n",
- "d"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 110,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "45"
- ]
- },
- "execution_count": 110,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 将所有的元素相加\n",
- "np.sum(d)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 111,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "3628800"
- ]
- },
- "execution_count": 111,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 全元素积分\n",
- "np.prod(d+1)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 112,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 0, 1, 3, 6, 10, 15, 21, 28, 36, 45])"
- ]
- },
- "execution_count": 112,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 累计求和\n",
- "np.cumsum(d)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 113,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1, 2, 6, 24, 120, 720, 5040,\n",
- " 40320, 362880, 3628800])"
- ]
- },
- "execution_count": 113,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 累计乘积\n",
- "np.cumprod(d+1)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 114,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "1.5215651271981643"
- ]
- },
- "execution_count": 114,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 计算对角线元素的和,和diag(A).sum()一样\n",
- "np.trace(A)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 7.6 数组子集的计算"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "我们可以使用索引、花式索引和从数组中提取数据的其他方法(如上所述)来计算数组中的数据子集。\n",
- "\n",
- "例如,让我们回到温度数据集:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 115,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "1800 1 1 -6.1 -6.1 -6.1 1\r\n",
- "1800 1 2 -15.4 -15.4 -15.4 1\r\n",
- "1800 1 3 -15.0 -15.0 -15.0 1\r\n"
- ]
- }
- ],
- "source": [
- "!head -n 3 stockholm_td_adj.dat"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "数据集的格式是:年,月,日,日平均气温,低,高,位置。\n",
- "\n",
- "如果我们对某个特定月份的平均温度感兴趣,比如二月,然后我们可以创建一个索引掩码,使用它来选择当月的数据:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 116,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 1., 2., 3., 4., 5., 6., 7., 8., 9., 10., 11.,\n",
- " 12.])"
- ]
- },
- "execution_count": 116,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.unique(data[:,1]) # 列的值从1到12"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 117,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[False False False ..., False False False]\n"
- ]
- }
- ],
- "source": [
- "mask_feb = data[:,1] == 2\n",
- "print(mask_feb)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 118,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "-3.21210957074\n",
- "5.09039076877\n"
- ]
- }
- ],
- "source": [
- "# 温度数据实在第三行\n",
- "print(np.mean(data[mask_feb,3]))\n",
- "print(np.std(data[mask_feb,3]))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "有了这些工具,我们就有了非常强大的数据处理能力。例如,提取每年每个月的平均气温只需要几行代码:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 119,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "image/png": "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\ngg==\n",
- "text/plain": [
- "<matplotlib.figure.Figure at 0x7f77f34a06a0>"
- ]
- },
- "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": 120,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 0.7859115 , 0.57245351, 0.70048786],\n",
- " [ 0.75468424, 0.7693271 , 0.77223336],\n",
- " [ 0.50666828, 0.37495119, 0.39477823],\n",
- " [ 0.19709589, 0.55104521, 0.34702979]])"
- ]
- },
- "execution_count": 120,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "import numpy as np\n",
- "\n",
- "m = np.random.rand(4,3)\n",
- "m"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 121,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "0.78591149819839246"
- ]
- },
- "execution_count": 121,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# global max\n",
- "m.max()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 122,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 0.7859115 , 0.7693271 , 0.77223336])"
- ]
- },
- "execution_count": 122,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# max in each column\n",
- "m.max(axis=0)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 123,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 0.7859115 , 0.77223336, 0.50666828, 0.55104521])"
- ]
- },
- "execution_count": 123,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# max in each row\n",
- "m.max(axis=1)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "许多其他的在`array` 和`matrix`类中的函数和方法接受同样(可选的)的关键字参数`axis`"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 8. 阵列的重塑、调整大小和堆叠"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "Numpy数组的形状可以被确定而无需复制底层数据,这使得即使对于大型数组也能有较快的操作。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 124,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[ 0.06650096 0.91326422 0.03565397]\n",
- " [ 0.37877941 0.50446487 0.17133194]\n",
- " [ 0.04761933 0.56795134 0.26191768]\n",
- " [ 0.1140937 0.63724791 0.57817114]]\n"
- ]
- }
- ],
- "source": [
- "import numpy as np\n",
- "\n",
- "A = np.random.rand(4, 3)\n",
- "print(A)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 125,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "4 3\n"
- ]
- }
- ],
- "source": [
- "n, m = A.shape\n",
- "print(n, m)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 126,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 0.06650096, 0.91326422, 0.03565397, 0.37877941, 0.50446487,\n",
- " 0.17133194, 0.04761933, 0.56795134, 0.26191768, 0.1140937 ,\n",
- " 0.63724791, 0.57817114]])"
- ]
- },
- "execution_count": 126,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "B = A.reshape((1,n*m))\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 127,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[ 0.06650096]\n",
- " [ 0.91326422]\n",
- " [ 0.03565397]\n",
- " [ 0.37877941]\n",
- " [ 0.50446487]\n",
- " [ 0.17133194]\n",
- " [ 0.04761933]\n",
- " [ 0.56795134]\n",
- " [ 0.26191768]\n",
- " [ 0.1140937 ]\n",
- " [ 0.63724791]\n",
- " [ 0.57817114]]\n",
- "(12, 1)\n"
- ]
- }
- ],
- "source": [
- "B2 = A.reshape((n*m, 1))\n",
- "print(B2)\n",
- "print(B2.shape)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 128,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 5. , 5. , 5. , 5. , 5. ,\n",
- " 0.17133194, 0.04761933, 0.56795134, 0.26191768, 0.1140937 ,\n",
- " 0.63724791, 0.57817114]])"
- ]
- },
- "execution_count": 128,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "B[0,0:5] = 5 # modify the array\n",
- "\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 129,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 5. , 5. , 5. ],\n",
- " [ 5. , 5. , 0.17133194],\n",
- " [ 0.04761933, 0.56795134, 0.26191768],\n",
- " [ 0.1140937 , 0.63724791, 0.57817114]])"
- ]
- },
- "execution_count": 129,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A # and the original variable is also changed. B is only a different view of the same data"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "We can also use the function `flatten` to make a higher-dimensional array into a vector. But this function create a copy of the data."
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 130,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 5. , 5. , 5. , 5. , 5. ,\n",
- " 0.17133194, 0.04761933, 0.56795134, 0.26191768, 0.1140937 ,\n",
- " 0.63724791, 0.57817114])"
- ]
- },
- "execution_count": 130,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "B = A.flatten()\n",
- "\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 131,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(12,)\n"
- ]
- }
- ],
- "source": [
- "print(B.shape)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 132,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[ 0.57131106 0.01124787 0.5370255 0.32295524 0.85349977 0.41314537\n",
- " 0.79981407 0.91790164 0.98459974 0.16475998 0.36345135 0.56568769\n",
- " 0.7032834 0.35611198 0.17611077 0.50105324 0.97298389 0.61007586\n",
- " 0.158854 0.94232554 0.24567912 0.24977344 0.26494364 0.03283923\n",
- " 0.51372832 0.26859095 0.18560484 0.19277174 0.25820657 0.90178094\n",
- " 0.92294036 0.36334338 0.88235257 0.71770501 0.77425693 0.51968121\n",
- " 0.30215987 0.75715079 0.0141675 0.07317587 0.83447121 0.94042718\n",
- " 0.094036 0.67506697 0.13013729 0.69917346 0.72056592 0.5559409\n",
- " 0.16920435 0.22056616 0.77663693 0.68573271 0.5572755 0.65410685\n",
- " 0.23982851 0.82249988 0.51395373 0.46991862 0.34405511 0.90384578]\n"
- ]
- }
- ],
- "source": [
- "T = np.random.rand(3, 4, 5)\n",
- "T2 = T.flatten()\n",
- "print(T2)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 133,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([ 10. , 10. , 10. , 10. ,\n",
- " 10. , 0.17133194, 0.04761933, 0.56795134,\n",
- " 0.26191768, 0.1140937 , 0.63724791, 0.57817114])"
- ]
- },
- "execution_count": 133,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "B[0:5] = 10\n",
- "\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 134,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 5. , 5. , 5. ],\n",
- " [ 5. , 5. , 0.17133194],\n",
- " [ 0.04761933, 0.56795134, 0.26191768],\n",
- " [ 0.1140937 , 0.63724791, 0.57817114]])"
- ]
- },
- "execution_count": 134,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A # 现在A并没有改变,因为B的数值是A的复制,并不指向同样的值。"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 9. 添加、删除维度:newaxis、squeeze"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "当矩阵乘法的时候,需要两个矩阵的对应的纬度保持一致才可以正确执行,有了`newaxis`,我们可以在数组中插入新的维度,例如将一个向量转换为列或行矩阵:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 135,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "v = np.array([1,2,3])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 136,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(3,)\n",
- "[1 2 3]\n"
- ]
- }
- ],
- "source": [
- "print(np.shape(v))\n",
- "print(v)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 137,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(3, 1)\n",
- "[[1]\n",
- " [2]\n",
- " [3]]\n"
- ]
- }
- ],
- "source": [
- "v2 = v.reshape(3, 1)\n",
- "print(v2.shape)\n",
- "print(v2)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 138,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(3,)\n",
- "(3, 1)\n"
- ]
- }
- ],
- "source": [
- "# 做一个向量v的列矩阵\n",
- "v2 = v[:, np.newaxis]\n",
- "print(v.shape)\n",
- "print(v2.shape)\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 139,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(3, 1)"
- ]
- },
- "execution_count": 139,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 列矩阵\n",
- "v[:,np.newaxis].shape"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 140,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(1, 3)"
- ]
- },
- "execution_count": 140,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 行矩阵\n",
- "v[np.newaxis,:].shape"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "也可以通过 `np.expand_dims` 来实现类似的操作"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 141,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(3, 1)\n",
- "[[1]\n",
- " [2]\n",
- " [3]]\n"
- ]
- }
- ],
- "source": [
- "v = np.array([1,2,3])\n",
- "v3 = np.expand_dims(v, 1)\n",
- "print(v3.shape)\n",
- "print(v3)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "在某些情况,需要将纬度为1的那个纬度删除掉,可以使用`np.squeeze`实现"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 142,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(1, 2, 3)\n",
- "[[[1 2 3]\n",
- " [2 3 4]]]\n"
- ]
- }
- ],
- "source": [
- "arr = np.array([[[1, 2, 3], [2, 3, 4]]])\n",
- "print(arr.shape)\n",
- "print(arr)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 143,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "(2, 3)\n",
- "[[1 2 3]\n",
- " [2 3 4]]\n"
- ]
- }
- ],
- "source": [
- "# 实际上第一个纬度为`1`,我们不需要\n",
- "arr2 = np.squeeze(arr, 0)\n",
- "print(arr2.shape)\n",
- "print(arr2)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "需要注意:只有数组长度在该纬度上为1,那么该纬度才可以被删除;否则会报错。"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 10. 叠加和重复数组"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "利用函数`repeat`, `tile`, `vstack`, `hstack`, 和`concatenate` 可以用较小的向量和矩阵来创建更大的向量和矩阵。"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 10.1 tile and repeat"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 144,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[[1 2]\n",
- " [3 4]]\n"
- ]
- }
- ],
- "source": [
- "a = np.array([[1, 2], [3, 4]])\n",
- "print(a)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 145,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4])"
- ]
- },
- "execution_count": 145,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 重复每一个元素三次\n",
- "np.repeat(a, 3)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 146,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2, 1, 2, 1, 2],\n",
- " [3, 4, 3, 4, 3, 4]])"
- ]
- },
- "execution_count": 146,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# tile the matrix 3 times \n",
- "np.tile(a, 3)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 147,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2, 1, 2, 1, 2],\n",
- " [3, 4, 3, 4, 3, 4]])"
- ]
- },
- "execution_count": 147,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 更好的方案\n",
- "np.tile(a, (1, 3))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 148,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4],\n",
- " [1, 2],\n",
- " [3, 4],\n",
- " [1, 2],\n",
- " [3, 4]])"
- ]
- },
- "execution_count": 148,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.tile(a, (3, 1))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 10.2 concatenate"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 149,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "b = np.array([[5, 6]])"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 150,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4],\n",
- " [5, 6]])"
- ]
- },
- "execution_count": 150,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.concatenate((a, b), axis=0)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 151,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2, 5],\n",
- " [3, 4, 6]])"
- ]
- },
- "execution_count": 151,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.concatenate((a, b.T), axis=1)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "### 10.3 hstack and vstack"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 152,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4],\n",
- " [5, 6]])"
- ]
- },
- "execution_count": 152,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.vstack((a,b))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 153,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2, 5],\n",
- " [3, 4, 6]])"
- ]
- },
- "execution_count": 153,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "np.hstack((a,b.T))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 11. 复制和“深度复制”"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "为了获得高性能,Python中的赋值通常不复制底层对象。例如,在函数之间传递对象时,通过引用传递从而避免不必要的大量内存复制。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 154,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4]])"
- ]
- },
- "execution_count": 154,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A = np.array([[1, 2], [3, 4]])\n",
- "\n",
- "A"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 155,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "# 现在B和A指的是同一个数组数据\n",
- "B = A "
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 156,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[10, 2],\n",
- " [ 3, 4]])"
- ]
- },
- "execution_count": 156,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 改变B影响A\n",
- "B[0,0] = 10\n",
- "\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 157,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[10, 2],\n",
- " [ 3, 4]])"
- ]
- },
- "execution_count": 157,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "如果我们想避免这种引用赋值的行为,那么当我们从 `A` 复制一个新的完全独立的对象 `B` 时,我们需要使用函数 `copy` 来做一个所谓的“深度复制”:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 158,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "B = np.copy(A)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 159,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[-5, 2],\n",
- " [ 3, 4]])"
- ]
- },
- "execution_count": 159,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 现在如果我们改变B,A不受影响\n",
- "B[0,0] = -5\n",
- "\n",
- "B"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 160,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[10, 2],\n",
- " [ 3, 4]])"
- ]
- },
- "execution_count": 160,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "A"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 12. 遍历数组元素"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "通常,我们希望尽可能避免遍历数组元素(不惜一切代价)。原因是在像Python(或MATLAB)这样的解释语言中,迭代与向量化操作相比真的很慢。\n",
- "\n",
- "然而,有时迭代是不可避免的。对于这种情况,Python的For循环是最方便的遍历数组的方法:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 161,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "1\n",
- "2\n",
- "3\n",
- "4\n"
- ]
- }
- ],
- "source": [
- "v = np.array([1,2,3,4])\n",
- "\n",
- "for element in v:\n",
- " print(element)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 162,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "row [1 2]\n",
- "1\n",
- "2\n",
- "row [3 4]\n",
- "3\n",
- "4\n"
- ]
- }
- ],
- "source": [
- "M = np.array([[1,2], [3,4]])\n",
- "\n",
- "for row in M:\n",
- " print(\"row\", row)\n",
- " \n",
- " for element in row:\n",
- " print(element)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "当我们需要去\n",
- "当我们需要遍历一个数组的每个元素并修改它的元素时,使用`enumerate`函数可以方便地在`for`循环中获得元素及其索引:"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 163,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "row_idx 0 row [1 2]\n",
- "col_idx 0 element 1\n",
- "col_idx 1 element 2\n",
- "row_idx 1 row [3 4]\n",
- "col_idx 0 element 3\n",
- "col_idx 1 element 4\n"
- ]
- }
- ],
- "source": [
- "for row_idx, row in enumerate(M):\n",
- " print(\"row_idx\", row_idx, \"row\", row)\n",
- " \n",
- " for col_idx, element in enumerate(row):\n",
- " print(\"col_idx\", col_idx, \"element\", element)\n",
- " \n",
- " # 更新矩阵:对每个元素求平方\n",
- " M[row_idx, col_idx] = element ** 2"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 164,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 1, 4],\n",
- " [ 9, 16]])"
- ]
- },
- "execution_count": 164,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 现在矩阵里的每一个元素都已经求得平方\n",
- "M"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 13. 向量化功能"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "正如前面多次提到的,为了获得良好的性能,我们应该尽量避免对向量和矩阵中的元素进行循环,而应该使用向量化算法。将标量算法转换为向量化算法的第一步是确保我们编写的函数使用向量输入。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 165,
- "metadata": {
- "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": 166,
- "metadata": {
- "scrolled": true
- },
- "outputs": [
- {
- "ename": "ValueError",
- "evalue": "The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()",
- "output_type": "error",
- "traceback": [
- "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
- "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)",
- "\u001b[0;32m<ipython-input-166-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-165-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": 167,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "Theta_vec = np.vectorize(Theta)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 168,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 0, 0, 1, 1, 1, 1])"
- ]
- },
- "execution_count": 168,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "Theta_vec(np.array([-3,-2,-1,0,1,2,3]))"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "我们也可以实现从一开始就接受矢量输入的函数(需要更多的计算,但可能会有更好的性能):"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 169,
- "metadata": {
- "collapsed": true
- },
- "outputs": [],
- "source": [
- "def Theta(x):\n",
- " \"\"\"\n",
- " Heaviside阶跃函数的矢量感知实现。\n",
- " \"\"\"\n",
- " return 1 * (x >= 0)"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 170,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([0, 0, 0, 1, 1, 1, 1])"
- ]
- },
- "execution_count": 170,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "Theta(np.array([-3,-2,-1,0,1,2,3]))"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 171,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "[False False False True True True True]\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "array([0, 0, 0, 1, 1, 1, 1])"
- ]
- },
- "execution_count": 171,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "a = np.array([-3,-2,-1,0,1,2,3])\n",
- "b = a>=0\n",
- "print(b)\n",
- "b*1"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 172,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "(0, 1)"
- ]
- },
- "execution_count": 172,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "# 同样适用于标量\n",
- "Theta(-1.2), Theta(2.6)"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 14. 在条件中使用数组"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "当在条件中使用数组时,例如`if`语句和其他布尔表达,一个需要用`any`或者`all`,这让数组任何或者所有元素都等于`True`。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 173,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[1, 2],\n",
- " [3, 4]])"
- ]
- },
- "execution_count": 173,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M = np.array([[1, 2], [3, 4]])\n",
- "M"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 174,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "True"
- ]
- },
- "execution_count": 174,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "(M > 2).any()"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 175,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "at least one element in M is larger than 2\n"
- ]
- }
- ],
- "source": [
- "if (M > 2).any():\n",
- " print(\"at least one element in M is larger than 2\")\n",
- "else:\n",
- " print(\"no element in M is larger than 2\")"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 176,
- "metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "all elements in M are not larger than 5\n"
- ]
- }
- ],
- "source": [
- "if (M > 5).all():\n",
- " print(\"all elements in M are larger than 5\")\n",
- "else:\n",
- " print(\"all elements in M are not larger than 5\")"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 15. 类型转换"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "因为Numpy数组是*静态类型*,数组的类型一旦创建就不会改变。但是我们可以用`astype`函数(参见类似的“asarray”函数)显式地转换一个数组的类型到其他的类型,这总是创建一个新类型的新数组。"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 177,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "dtype('int64')"
- ]
- },
- "execution_count": 177,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M.dtype\n"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 178,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ 1., 2.],\n",
- " [ 3., 4.]])"
- ]
- },
- "execution_count": 178,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M2 = M.astype(float)\n",
- "\n",
- "M2"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 179,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "dtype('float64')"
- ]
- },
- "execution_count": 179,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M2.dtype"
- ]
- },
- {
- "cell_type": "code",
- "execution_count": 180,
- "metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "array([[ True, True],\n",
- " [ True, True]], dtype=bool)"
- ]
- },
- "execution_count": 180,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "M3 = M.astype(bool)\n",
- "\n",
- "M3"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "## 16. 进一步学习"
- ]
- },
- {
- "cell_type": "markdown",
- "metadata": {},
- "source": [
- "* [NumPy 简易教程](https://www.runoob.com/numpy/numpy-tutorial.html)\n",
- "* [NumPy 官方用户指南](https://www.numpy.org.cn/user/)\n",
- "* [NumPy 官方参考手册](https://www.numpy.org.cn/reference/)\n",
- "* [一个针对MATLAB使用者的Numpy教程](https://numpy.org/doc/stable/user/numpy-for-matlab-users.html)"
- ]
- }
- ],
- "metadata": {
- "kernelspec": {
- "display_name": "Python 3",
- "language": "python",
- "name": "python3"
- },
- "language_info": {
- "codemirror_mode": {
- "name": "ipython",
- "version": 3
- },
- "file_extension": ".py",
- "mimetype": "text/x-python",
- "name": "python",
- "nbconvert_exporter": "python",
- "pygments_lexer": "ipython3",
- "version": "3.5.4"
- }
- },
- "nbformat": 4,
- "nbformat_minor": 1
- }
|