Numpy 的 ndarray 提供了一種將同質數據塊解釋爲多維數組對象的方式。同質,表示數組的元素必須都是相同的數據類型(如 int,float 等);解釋,表示 ndarray 的數據塊實際上是線性存儲的,並經過額外的元信息解釋爲多維數組結構:python
下面是一個 3×4 的矩陣:(使用相似 3×4×2...
這種格式表示多維數組的結構時,從左向右的數字對應表示由表及裏的維度,或稱爲軸,按索引給軸編號後可稱爲「軸 0」、「軸 1」等)shell
lang:python >>> foo array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) >>> foo.dtype dtype('int32') >>> foo.shape (3, 4) >>> foo.strides (16, 4)
這個矩陣的形狀(shape)是(3,4)或 3×4,即它有 3 個長度爲 4 的一維數組;它的 dtype 是 int32
表示它的單位元素是佔 4 字節的整型;跨度(strides)元組指的是在某一維度下爲了獲取到下一個元素須要「跨過」的字節數。可見跨度是能夠由 形狀+dtype 來肯定的。顯然這種同質的靜態數據結構在進行數值運算時效率要比 Python 內建的能夠混雜動態類型的列表要快得多。數組
dtype 支持的數字類型有: <br />數據結構
<table style="font-size:14px"> <tr><td>######################</td><td>***********************************</td></tr> <tr> <td><b>bool_</td> <td>佔一個字節的布爾類型(True/False)</td> </tr> <tr> <td><b>int_</td> <td>默認的整數類型</td> </tr> <tr> <td>intc</td> <td>與 C int 相同,一般爲 int32 或 int64</td> </tr> <tr> <td>intp</td> <td>用於索引的整數(同 C ssize_t,int32 或 int64)</td> </tr> <tr> <td>int八、1六、3二、64</td> <td>不一樣位數的整數</td> </tr> <tr> <td>uint八、1六、3二、64</td> <td>不一樣位數的無符號整數</td> </tr> <tr> <td><b>float_</td> <td>float64</td> </tr> <tr> <td>float1六、3二、64</td> <td>不一樣位數的浮點數</td> </tr> <tr> <td><b>complex_</td> <td>complex128</td> </tr> <tr> <td>complex6四、128</td> <td>不一樣位數的複數</td> </tr> </table> <br /> 上表中加粗的 **`bool_ , int_ , float_ , complex_`** 都與 Python 的內建類型 `bool , int , float , complex` 相同,實際上使用 Python 的類型名稱(int,float 等)也是合法的。`intc , intp` 的大小不定是取決於操做系統。 <br /> #建立 ndarray --- 建立數組最簡單的方法是使用 `array()` 函數:(numpy 的公約簡稱爲 np —— `import numpy as np`)less
lang:python array(object, dtype=None, copy=True, order=None, subok=False, ndmin=0)
它接受一切序列類型對象,並將其轉化爲一個 ndarray 數組,維度視序列的嵌套深度而定:ide
lang:python >>> np.array([1,2,3,4]) array([1, 2, 3, 4]) >>> np.array([[1,2],[3,4]]) array([[1, 2], [3, 4]])
數組的 dtype 會由系統自動推定,除非你顯式傳遞一個參數進去。(系統通常會默認使用 int32 或 float64)函數
除 array()
函數外,還有一些能夠用於建立數組的便捷函數: <br />工具
<table style="font-size:14px"> <tr><td>#####################</td><td>*************************************************</td></tr> <tr> <td>asarray</td> <td>將輸入轉換爲 ndarray,若輸入自己是 ndarray 就不復制</td> </tr> <tr> <td>arange</td> <td>相似於內建 range 函數,不過返回的是一個一維 ndarray</td> </tr> <tr> <td>ones、ones_like</td> <td>根據指定形狀和 dtype 建立一個全 1 數組</td> </tr> <tr> <td>zeros、zeros_like</td> <td>根據指定形狀和 dtype 建立一個全 0 數組</td> </tr> <tr> <td>empty、empty_like</td> <td>建立新數組,但只分配內存空間不賦值</td> </tr> <tr> <td>eye、identity</td> <td>建立一個正方的N×N單位矩陣(對角線爲1,其他爲0)</td> </tr> </table> <br /> `ones(shape, dtype=None, order='C')` 和 `ones_like(arr_instance, dtype=None, order='K', subok=True)` 使用示例,`zeros_like` 取一個 ndarray 爲參數,並按它的 dtype 和形狀建立全 0 數組:ui
lang:python >>> foo = np.ones((3,4),dtype=np.int32) >>> foo array([[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]) >>> bar = np.zeros_like(foo) >>> bar array([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]])
參數中的 order='C' ,order='F'
指的是元素在內存中的排序,C 表明 C 順序,指行優先;F 表明 Fortran 順序,指列優先。操作系統
np.empty()
,這個函數建立的數組裏面是有值的,除非你肯定建立的這個數組能被徹底賦值,不然後面運算起來很麻煩,這些「空值」的布爾類型是 True,並且 dropna()
方法刪不掉。想建立空的 Series ,可使用 Series(np.nan,index=???)
這樣。 <br /> #ndarray 對象的屬性###.reshape(shape) 此方法用於改變數組的形狀。雖然我以爲既然 ndarray 對象的數據塊都是線性存儲的,按說調用 .reshape()
方法的話只須要改一下數據頭中的 shape 屬性就能夠了啊,但實際上不是這樣子的!a.reshape(shape, order='C')
方法會返回一個新數組,而不是直接改變調用者的形狀。
lang:python >>> foo = np.arange(9) >>> bar = foo.reshape((3,3)) >>> bar array([[0, 1, 2], [3, 4, 5], [6, 7, 8]]) >>> foo array([0, 1, 2, 3, 4, 5, 6, 7, 8])
<br /> ###.astype(dtype) 這是一個用於轉換數組 dtype 的方法,從前面的 ndarray 數據結構能夠猜到,這種轉換必然須要建立一個新數組。若是轉換過程由於某種緣由而失敗了,就會引起一個 TypeError 異常。另外,如 `np.int32()` 這樣把 dtype 當作函數來用也是可行的,但更推薦 `.astype()` 方法:
lang:python >>> bar.astype(float) array([[ 0., 1., 2.], [ 3., 4., 5.], [ 6., 7., 8.]])
本例中使用 Python 內建的 float
當作 dtype 傳了進去,也是可行的哦,當對數據大小不敏感時就能夠這麼作。 <br /> ###.transpose(*axes) 轉置方法返回的是原數組的視圖(不復制)。由於我對多維數組也搞不太懂,就只舉個二維數組的例子吧(不給 axes 參數):
lang:python >>> foo = np.arange(8).reshape(2,4) >>> foo array([[0, 1, 2, 3], [4, 5, 6, 7]]) >>> foo.transpose() array([[0, 4], [1, 5], [2, 6], [3, 7]]) >>> foo.T array([[0, 4], [1, 5], [2, 6], [3, 7]])
數組的 .T
屬性是軸對換的快捷方式。通常在計算矩陣點積時比較方便:np.dot(arr,att.T)
。嗯,簡單的乘法(星號)是廣播運算,點積須要使用 dot()
函數。 <br /> ###.sort() ndarray 的 .sort(axis=-1, kind='quicksort', order=None)
方法可用於給數組在指定軸向上排序。好比一個 (4,3,2)的數組,它的對應軸向分別爲(2,1,0),方法默認的 axis=-1
表明最外層維度,如 「表」 裏的 「行」。
lang:python >>> a = np.array([[1,4], [3,1]]) >>> a array([[1, 4], [3, 1]]) >>> np.sort(a,0) array([[1, 1], [3, 4]]) >>> np.sort(a,1) array([[1, 4], [1, 3]])
這裏使用了外部函數 np.sort()
是爲了在演示過程當中不會影響到原數組。np.sort()
函數老是返回一份拷貝,而 .sort()
方法則會更改原數組。 <br /> ###統計方法 ndarray 對象還有一些統計方法,能夠對整個數組或某個軸向上的數據進行統計計算(軸向數字越大表明的維度越高,從 0 開始計數)。這些方法同時也能夠當作頂級函數使用。例如:
lang:python >>> arr = np.arange(12).reshape(3,4) >>> arr array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) >>> arr.sum() 66 >>> np.sum(arr) 66 >>> arr.mean(0) array([ 4., 5., 6., 7.]) >>> arr.mean(1) array([ 1.5, 5.5, 9.5]) >>> arr.mean(2) Traceback (most recent call last): File "<pyshell#35>", line 1, in <module> arr.mean(2) items *= arr.shape[ax] IndexError: tuple index out of range
基本的數組統計方法有: <br />
<table style="font-size:14px"> <tr><td>#####################</td><td>*************************************************</td></tr> <tr> <td>sum</td> <td>求和</td> </tr> <tr> <td>mean</td> <td>均值</td> </tr> <tr> <td>std,var</td> <td>標準差和方差</td> </tr> <tr> <td>min,max</td> <td>最小值和最大值</td> </tr> <tr> <td>argmin,argmax</td> <td>最小值和最大值的索引</td> </tr> <tr> <td>cumsum</td> <td>累積和</td> </tr> <tr> <td>cumprod</td> <td>累積積</td> </tr> </table> <br /> ###用於布爾型數組的方法 有兩個方法 `.any()` 和 `.all()` 能夠用於判斷某個數組中是否存在或所有爲 `True`。這兩個方法也一樣支持 axis 軸向參數:
lang:python >>> arr = np.arange(12).reshape(3,4) >>> arr array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) >>> arr.all(1) array([False, True, True], dtype=bool) >>> arr.any() True
<br /> #數組之間的運算 --- 形狀相同的數組之間的運算都會應用到元素級:
lang:python >>> foo = np.arange(6).reshape((2,3)) >>> bar = np.arange(5,-1,-1).reshape((2,3)) >>> bar array([[5, 4, 3], [2, 1, 0]]) >>> foo array([[0, 1, 2], [3, 4, 5]]) >>> foo + bar array([[5, 5, 5], [5, 5, 5]]) >>> foo * bar array([[0, 4, 6], [6, 4, 0]])
真正的問題在於不一樣大小的數組間運算時會發生什麼。廣播(broadcasting)指的是不一樣形狀的數組之間的算數運算的執行方式,這也是 Numpy 的核心內容之一。
廣播遵循的原則爲:若是兩個數組的後緣維度(trailing dimension,即從末尾開始算起的維度)的軸長度相符或其中一方的長度爲 1,則認爲它們是廣播兼容的。廣播會在缺失和(或)長度爲 1 的維度上進行。
嗯,反正我是沒看明白 ╮(╯▽╰)╭ 。本身的理解是,系統會在可能的條件下把形狀不一樣的數組補完成相同的形狀,例:
lang:python >>> foo = np.arange(5) >>> foo array([0, 1, 2, 3, 4]) >>> foo * 5 array([ 0, 5, 10, 15, 20])
5
補完成 array([5, 5, 5, 5, 5])
。 <br /> #索引和切片ndarray 的索引和切片語法與 Python 的列表類似。都是經過如 [0]
,[0:5:2]
這樣的方括號 + 冒號來完成。比較不一樣之處在於爲了方便對多維數組切片,ndarray 對象還支持使用逗號間隔的多維切片方法:[0,3]
,[0,3:9:2]
。 <br /> ###普通索引
lang:python >>> foo = np.arange(12) >>> foo array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) >>> foo[:5] array([0, 1, 2, 3, 4]) >>> foo[:5]=0 >>> foo array([ 0, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10, 11]) >>> bar = foo[:5] >>> bar[0] = 1024 >>> foo array([1024, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10, 11])
注意這裏,爲了節省內存,對 ndarray 的切片操做得到的都是對原數組的引用,所以對該引用的更改操做都會反映到原數組上。若是你想複製出一段副本,就應當使用 .copy()
方法:
lang:python >>> bar = foo[:5].copy() >>> bar[:] = 1 >>> foo array([1024, 0, 0, 0, 0, 5, 6, 7, 8, 9, 10, 11])
也許你會對這裏的 foo[:]
感興趣,這表明切所有的片,不可使用 foo = 1
這樣的賦值語句,這等於給 foo
從新指向一個新的內存地址,而非對切片元素進行操做。
前面提到的使用逗號在多維度下的切片方法:
lang:python >>> foo = np.arange(12).reshape(3,4) >>> foo array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) >>> foo[0,1] 1 >>> foo[0,::2] array([0, 2])
這種切片方法能夠看作是一種語法糖,由於最標準的對多維數組的切片方法應該是下面這樣子的,包括 Python 本來對嵌套列表的切片方法也是這樣子的:
lang:python >>> foo array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) >>> foo[0][1] 1 >>> foo[0][::2] array([0, 2])
即 foo[0,1]
與 foo[0][1]
效果相同,這種實現能夠節省時間,但不如原始方法更直觀一點。只要記住對多維數組的單層切片老是切的最外層維度這點,操做起來就不容易亂。 <br /> ###布爾型索引 布爾型索引指的是使用一個布爾型數組而非 [::]
做爲切片手段,操做會將被切片對象中對應於布爾型數組中 True
元素位置的元素返回,並老是返回一個新的副本。
lang:python >>> foo = np.arange(12).reshape(3,4) >>> bar = foo.copy() >>> bar%2==0 array([[ True, False, True, False], [ True, False, True, False], [ True, False, True, False]], dtype=bool) >>> foo[bar%2==0] array([ 0, 2, 4, 6, 8, 10])
bar%2==0
這個表達式,在 Python 的標準語法中對一個列表和一個整型應用取餘操做是非法的,你必須使用循環(如 for)遍歷列表的單個元素才行。但 numpy 很貼心地經過廣播解決了這個問題,吊不弔! <br /> ###花式索引花式索引(fancy indexing)是一個 Numpy 術語,它指的是利用整數數組進行索引,這裏的整數數組起到了index的做用。
lang:python >>> foo = np.empty((8,4),int) >>> for i in range(8): foo[i] = i >>> foo array([[0, 0, 0, 0], [1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4], [5, 5, 5, 5], [6, 6, 6, 6], [7, 7, 7, 7]]) >>> foo[[7,2,5]] array([[7, 7, 7, 7], [2, 2, 2, 2], [5, 5, 5, 5]]) >>> foo[[7,2,5],[0,2,2]] array([7, 2, 5])
foo[[7,2,5],[0,2,2]]
處兩個列表索引之間的逗號,所起的做用與上面普通索引處的做用相同,均爲在更低一級維度上索引之用。 <br /> #通用函數通用函數(即 ufunc)是一種對 ndarray 執行元素級運算的函數。通用函數依據參數的數量不一樣,可分爲一元(unary)函數和二元(binary)函數。(參數通常都是 ndarray 對象)
###一元函數
<table style="font-size:14px"> <tr> <td>abs,fabs</td> <td>整數、浮點、複數的絕對值,對於非複數,可用更快的 fabs</td> </tr> <tr> <td>sqrt</td> <td>平方根,等於 arr**0.5</td> </tr> <tr> <td>square</td> <td>平方,等於 arr**2</td> </tr> <tr> <td>exp</td> <td>以 e 爲底的指數函數</td> </tr> <tr> <td>log,log10,log2,log1p</td> <td>以 e 爲底的對數函數</td> </tr> <tr> <td>sign</td> <td>計算各元素的正負號,1(正),0(零),-1(負)</td> </tr> <tr> <td>ceil</td> <td>計算大於等於該值的最小整數</td> </tr> <tr> <td>floor</td> <td>計算小於等於該值的最大整數</td> </tr> <tr> <td>rint</td> <td>round int,四捨五入到整數</td> </tr> <tr> <td>modf</td> <td>將數組的整數和小數部分以兩個獨立數組的形式返回</td> </tr> <tr> <td>isnan</td> <td>返回一個 「哪些值是 NaN」 的布爾型數組</td> </tr> <tr> <td>isfinite,isinf</td> <td>返回是不是有窮(無窮)的布爾型數組</td> </tr> <tr> <td>cos,cosh,sin,sinh,tan,tanh</td> <td>普通和雙曲型三角函數</td> </tr> <tr> <td>arccos,arccosh...等同上</td> <td>反三角函數</td> </tr> <tr> <td>logical_not</td> <td>計算個元素 not x 的真值,等於 -arr</td> </tr> <tr> <td>unique</td> <td>計算元素惟一值並返回排序後的結果</td> </tr> </table> <br /> ###二元函數
<table style="font-size:14px"> <tr> <td>add</td> <td>加法,+</td> </tr> <tr> <td>subtract</td> <td>減法,-</td> </tr> <tr> <td>multiply</td> <td>乘法,*</td> </tr> <tr> <td>divide,floor_divide</td> <td>除法和地板除,/ 和 //</td> </tr> <tr> <td>power</td> <td>乘方,**</td> </tr> <tr> <td>maximum,fmax</td> <td>元素級最大值,fmax 將忽略 NaN</td> </tr> <tr> <td>minimum,fmin</td> <td>同上</td> </tr> <tr> <td>mod</td> <td>取模,%</td> </tr> <tr> <td>copysign</td> <td>將第二數組元素的符號複製給第一數組</td> </tr> <tr> <td>greater(_equal),less(_equal),(not_)equal</td> <td>字面意義,返回布爾數組</td> </tr> <tr> <td>logical_and,logical_or,logical_xor</td> <td>字面意義,返回布爾數組</td> </tr> </table> <br /> ###三元函數 這裏的三元函數只有一個,並且不是接受 3 個數組參數的意思。它實際上是一個條件運算函數,即 `foo if cond else bar` 這個表達式的 numpy 版——`where(condition, [x, y])`
lang:python >>> arr = np.arange(12).reshape(3,4) >>> arr array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) >>> np.where(arr%2==0,1,0) array([[1, 0, 1, 0], [1, 0, 1, 0], [1, 0, 1, 0]])