1. 程式人生 > >python numpy 基礎教程

python numpy 基礎教程

Numpy簡單介紹

1.Numpy是什麼

很簡單,Numpy是Python的一個科學計算的庫,提供了矩陣運算的功能,其一般與Scipy、matplotlib一起使用。其實,list已經提供了類似於矩陣的表示形式,不過numpy為我們提供了更多的函式。如果接觸過matlab、scilab,那麼numpy很好入手。 在以下的程式碼示例中,總是先匯入了numpy:(通用做法import numpu as np 簡單輸入)

>>> import numpy as np
>>> print np.version.version
1.6.2


2. 多維陣列

多維陣列的型別是:numpy.ndarray。

使用numpy.array方法

以list或tuple變數為引數產生一維陣列:

>>> print np.array([1,2,3,4])
[1 2 3 4]
>>> print np.array((1.2,2,3,4))
[ 1.2  2.   3.   4. ]
>>> print type(np.array((1.2,2,3,4)))
<type 'numpy.ndarray'>

以list或tuple變數為元素產生二維陣列或者多維陣列:

>>> x = np.array(((1,2,3),(4,5,6)))
>>> x
array([[1, 2, 3],
       [4, 5, 6]])
>>> y = np.array([[1,2,3],[4,5,6]])
>>> y
array([[1, 2, 3],
       [4, 5, 6]])

numpy資料型別設定與轉換

numpy ndarray資料型別可以通過引數dtype 設定,而且可以使用astype轉換型別,在處理檔案時候這個會很實用,注意astype 呼叫會返回一個新的陣列,也就是原始資料的一份拷貝。

numeric_strings2 = np.array(['1.23','2.34','3.45'],dtype=np.string_)

numeric_strings2
Out[32]: 
array(['1.23', '2.34', '3.45'], 
      dtype='|S4')

numeric_strings2.astype(float)
Out[33]: array([ 1.23,  2.34,  3.45])

numpy索引與切片

index 和slicing :第一數值類似陣列橫座標,第二個為縱座標

>>> x[1,2]
6
>>> y=x[:,1]
>>> y
array([2, 5])

涉及改變相關問題,我們改變上面y是否會改變x?這是特別需要關注的!

>>> y
array([2, 5])
>>> y[0] = 10
>>> y
array([10,  5])
>>> x
array([[ 1, 10,  3],
       [ 4,  5,  6]])

通過上面可以發現改變y會改變x ,因而我們可以推斷,y和x指向是同一塊記憶體空間值,系統沒有為y 新開闢空間把x值賦值過去。

arr = np.arange(10)

arr
Out[45]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

arr[4]
Out[46]: 4

arr[3:6]
Out[47]: array([3, 4, 5])

arr[3:6] = 12

arr
Out[49]: array([ 0,  1,  2, 12, 12, 12,  6,  7,  8,  9])

如上所示:當將一個標量賦值給切片時,該值會自動傳播整個切片區域,這個跟列表最重要本質區別,陣列切片是原始陣列的檢視,檢視上任何修改直接反映到源資料上面。

思考為什麼這麼設計? Numpy 設計是為了處理大資料,如果切片採用資料複製話會產生極大的效能和記憶體消耗問題。

假如說需要對陣列是一份副本而不是檢視可以如下操作:

arr_copy = arr[3:6].copy()

arr_copy[:]=24

arr_copy
Out[54]: array([24, 24, 24])

arr
Out[55]: array([ 0,  1,  2, 12, 12, 12,  6,  7,  8,  9])


再看下對list 切片修改

l=range(10)

l
Out[35]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

l[5:8] = 12
Traceback (most recent call last):

  File "<ipython-input-36-022af3ddcc9b>", line 1, in <module>
    l[5:8] = 12

TypeError: can only assign an iterable


l1= l[5:8]

l1
Out[38]: [5, 6, 7]

l1[0]=12

l1
Out[40]: [12, 6, 7]

l
Out[41]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
這裡設計到python 中深淺拷貝,其中切片屬於淺拷貝,具體參考:python深淺拷貝

多維陣列索引、切片

arr2d = np.arange(1,10).reshape(3,3)

arr2d
Out[57]: 
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

arr2d[2]
Out[58]: array([7, 8, 9])

arr2d[0][2]
Out[59]: 3

arr2d[0,2]
Out[60]: 3

布林型索引

這種型別在實際程式碼中出現比較多,關注下。

names = np.array(['Bob','joe','Bob','will'])

names == 'Bob'
Out[70]: array([ True, False,  True, False], dtype=bool)

data
Out[73]: 
array([[ 0.36762706, -1.55668952,  0.84316735, -0.116842  ],
       [ 1.34023966,  1.12766186,  1.12507441, -0.68689309],
       [ 1.27392366, -0.43399617, -0.80444728,  1.60731881],
       [ 0.23361565,  1.38772715,  0.69129479, -1.19228023],
       [ 0.51353082,  0.17696698, -0.06753478,  0.80448168],
       [ 0.21773096,  0.60582802, -0.46446071,  0.83131122],
       [ 0.50569072,  0.04431685, -0.69358155, -0.9629124 ]])

data[data < 0] = 0

data
Out[75]: 
array([[ 0.36762706,  0.        ,  0.84316735,  0.        ],
       [ 1.34023966,  1.12766186,  1.12507441,  0.        ],
       [ 1.27392366,  0.        ,  0.        ,  1.60731881],
       [ 0.23361565,  1.38772715,  0.69129479,  0.        ],
       [ 0.51353082,  0.17696698,  0.        ,  0.80448168],
       [ 0.21773096,  0.60582802,  0.        ,  0.83131122],
       [ 0.50569072,  0.04431685,  0.        ,  0.        ]])

上面展示通過布林值來設定值的手段。

陣列檔案輸入輸出

在跑實驗時經常需要用到讀取檔案中的資料,其實在numpy中已經有成熟函式封裝好了可以使用

將陣列以二進位制形式格式儲存到磁碟,np.save 、np.load 函式是讀寫磁碟的兩個主要函式,預設情況下,陣列以未壓縮的原始二進位制格式儲存在副檔名為.npy的檔案中

arr = np.arange(10)
np.save('some_array',arr)

np.load('some_array.npy')
Out[80]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
存取文字檔案:

文字中存放是聚類需要資料,直接可以方便讀取到numpy array中,省去一行行讀檔案繁瑣。

arr = np.loadtxt('dataMatrix.txt',delimiter=' ')

arr
Out[82]: 
array([[ 1.        ,  1.        ,  1.        ,  1.        ,  1.        ,
         0.8125    ],
       [ 0.52882353,  0.56271186,  0.48220588,  0.53384615,  0.61651376,
         0.58285714],
       [ 0.        ,  0.        ,  0.        ,  1.        ,  1.        ,
         1.        ],
       [ 1.        ,  0.92857143,  0.91857143,  1.        ,  1.        ,
         1.        ],
       [ 1.        ,  1.        ,  1.        ,  1.        ,  1.        ,
         1.        ],
       [ 0.05285714,  0.10304348,  0.068     ,  0.06512821,  0.05492308,
         0.05244898],
       [ 0.04803279,  0.08203125,  0.05516667,  0.05517241,  0.04953488,
         0.05591549],
       [ 0.04803279,  0.08203125,  0.05516667,  0.05517241,  0.04953488,
         0.05591549]])

np.savetxt 執行相反的操作,這兩個函式在跑實驗載入資料時可以提供很多便利!!!

使用numpy.arange方法

>>> print np.arange(15)
[ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14]
>>> print type(np.arange(15))
<type 'numpy.ndarray'>
>>> print np.arange(15).reshape(3,5)
[[ 0  1  2  3  4]
 [ 5  6  7  8  9]
 [10 11 12 13 14]]
>>> print type(np.arange(15).reshape(3,5))
<type 'numpy.ndarray'>


使用numpy.linspace方法

例如,在從1到10中產生20個數:

>>> print np.linspace(1,10,20)
[  1.           1.47368421   1.94736842   2.42105263   2.89473684
   3.36842105   3.84210526   4.31578947   4.78947368   5.26315789
   5.73684211   6.21052632   6.68421053   7.15789474   7.63157895
   8.10526316   8.57894737   9.05263158   9.52631579  10.        ]


使用numpy.zeros,numpy.ones,numpy.eye等方法可以構造特定的矩陣

>>> print np.zeros((3,4))
[[ 0.  0.  0.  0.]
 [ 0.  0.  0.  0.]
 [ 0.  0.  0.  0.]]
>>> print np.ones((3,4))
[[ 1.  1.  1.  1.]
 [ 1.  1.  1.  1.]
 [ 1.  1.  1.  1.]]
>>> print np.eye(3)
[[ 1.  0.  0.]
 [ 0.  1.  0.]
 [ 0.  0.  1.]]


獲取陣列的屬性:

>>> a = np.zeros((2,2,2))
>>> print a.ndim   #陣列的維數
3
>>> print a.shape  #陣列每一維的大小
(2, 2, 2)
>>> print a.size   #陣列的元素數
8
>>> print a.dtype  #元素型別
float64
>>> print a.itemsize  #每個元素所佔的位元組數
8

Memory layout

The following attributes contain information about the memory layout of the array:

Information about the memory layout of the array.
Tuple of array dimensions.
Tuple of bytes to step in each dimension when traversing an array.
Number of array dimensions.
Python buffer object pointing to the start of the array’s data.
Number of elements in the array.
Length of one array element in bytes.
Total bytes consumed by the elements of the array.
Base object if memory is from some other object.

Array methods

Anndarrayobject has many methods which operate on or with the array in some fashion, typically returning an array result. These methods are briefly explained below. (Each method’s docstring has a more complete description.)

用到比較多函式示例:

>>> x
array([[[ 0,  1,  2],
        [ 3,  4,  5],
        [ 6,  7,  8]],

       [[ 9, 10, 11],
        [12, 13, 14],
        [15, 16, 17]],

       [[18, 19, 20],
        [21, 22, 23],
        [24, 25, 26]]])
>>> x.sum(axis=1)
array([[ 9, 12, 15],
       [36, 39, 42],
       [63, 66, 69]])
>>> x.sum(axis=2)
array([[ 3, 12, 21],
       [30, 39, 48],
       [57, 66, 75]])
>>> np.sum([[0, 1], [0, 5]])
6
>>> np.sum([[0, 1], [0, 5]], axis=0)
array([0, 6])
>>> np.sum([[0, 1], [0, 5]], axis=1)
array([1, 5])


合併陣列

使用numpy下的vstack(垂直方向)和hstack(水平方向)函式:

>>> a = np.ones((2,2))
>>> b = np.eye(2)
>>> print np.vstack((a,b))
[[ 1.  1.]
 [ 1.  1.]
 [ 1.  0.]
 [ 0.  1.]]
>>> print np.hstack((a,b))
[[ 1.  1.  1.  0.]
 [ 1.  1.  0.  1.]]

看一下這兩個函式有沒有涉及到淺拷貝這種問題:

>>> c = np.hstack((a,b))
>>> print c
[[ 1.  1.  1.  0.]
 [ 1.  1.  0.  1.]]
>>> a[1,1] = 5
>>> b[1,1] = 5
>>> print c
[[ 1.  1.  1.  0.]
 [ 1.  1.  0.  1.]]


通過上面可以知道,這裡進行是深拷貝,而不是引用指向同一位置的淺拷貝。

深拷貝陣列

陣列物件自帶了淺拷貝和深拷貝的方法,但是一般用深拷貝多一些:

>>> a = np.ones((2,2))
>>> b = a
>>> b is a
True
>>> c = a.copy()  #深拷貝
>>> c is a
False

基本的矩陣運算

轉置:

>>> a = np.array([[1,0],[2,3]])
>>> print a
[[1 0]
 [2 3]]
>>> print a.transpose()
[[1 2]
 [0 3]]


numpy.linalg模組中有很多關於矩陣運算的方法:

特徵值、特徵向量:

>>> a = np.array([[1,0],[2,3]])

>>> nplg.eig(a)
(array([ 3.,  1.]), array([[ 0.        ,  0.70710678],
       [ 1.        , -0.70710678]]))