1. 程式人生 > >Numpy 陣列基礎操作--索引、組合、分割、複製、遍歷、轉換、序列化(四)

Numpy 陣列基礎操作--索引、組合、分割、複製、遍歷、轉換、序列化(四)

Numpy 陣列基礎操作

1.陣列索引訪問

#!/usr/bin/env python  
# encoding: utf-8  

import numpy as np

b = np.array([[1,2,3],[4,5,6],[7,8,9],[10,11,12]],dtype=int)

c = b[0,1]  #1行 第二個單元元素
# 輸出: 2

d = b[:,1]  #所有行 第二個單元元素
# 輸出: [ 2  5  8 11]

e = b[1,:]  #2行 所有單元元素
# 輸出: [4 5 6]

f = b[1,1:]  #2行 第2個單元開始以後所有元素
# 輸出: [5 6]

g = b[1,:2]  #2行 第1個單元開始到索引為2以前的所有元素
# 輸出: [4 5]

2.陣列的組合(函式)

'''
# 組合函式
#建立兩個測試陣列
# arange 建立一個含有9個元素的一維
# reshape方法,可以建立一個改變了尺寸的新陣列,原陣列的shape保持不變:
# 在這裡 reshape(3,3) 將生成一個 3個元素為一組的 3維陣列 
'''

#建立兩個測試陣列
a = np.arange(9).reshape(3,3)  
'''
 array([[0, 1, 2],  
           [3, 4, 5],  
           [6, 7, 8]])  
'''
b = 2 * a
'''
array([[ 0, 2, 4],  
       [ 6, 8, 10],  
       [12, 14, 16]])  

'''

#水平組合
np.hstack((a, b)) 
'''
array([[ 0, 1, 2, 0, 2, 4],  
       [ 3, 4, 5, 6, 8, 10],  
       [ 6, 7, 8, 12, 14, 16]]) 
'''

#通過concatenate函式並指定相應的軸 (axis=1 水平,axis=0 垂直)
con = np.concatenate((a, b), axis=1)
'''
array([[ 0, 1, 2, 0, 2, 4],  
       [ 3, 4, 5, 6, 8, 10],  
       [ 6, 7, 8, 12, 14, 16]])  
'''

#垂直組合
np.vstack((a, b))
'''
array([[ 0, 1, 2],  
       [ 3, 4, 5],  
       [ 6, 7, 8],   
       [ 0, 2, 4],  
       [ 6, 8, 10],  
       [12, 14, 16]])  

'''
#或者使用concatenate 
con = np.concatenate((a, b), axis=0)

#深度組合 dstack(就是在陣列的第三個軸(即深度)上組合,生成一個新的列表陣列)
np.dstack((a, b))  
'''
array([[[ 0, 0],  
        [ 1, 2],  
        [ 2, 4]],  
  
       [[ 3, 6],  
        [ 4, 8],  
        [ 5, 10]],  
  
       [[ 6, 12],  
        [ 7, 14],  
        [ 8, 16]]])  

'''

#行組合,行組合可將多個一維陣列作為新陣列的每一行進行組合
#對於2維陣列,其作用就像垂直組合一樣。

one = np.arange(2)
'''
array([0, 1])
'''

two = one + 2 
'''
array([2, 3])
'''

np.row_stack((one, two))
'''

array([[0, 1],  
       [2, 3]]) 
'''

#列組合(對於2維陣列,其作用就像水平組合一樣。)
np.column_stack((oned, twiceoned))  
'''
array([[0, 2],  
       [1, 3]])  
'''


3.陣列分割

在NumPy中,分割陣列的函式有hsplit、vsplit、dsplit和split。可將陣列分割成相同大小的子陣列,或指定原陣列分割的位置。

#水平分割

a = arange(9).reshape(3,3) 
'''
array([[0, 1, 2],  
       [3, 4, 5],  
       [6, 7, 8]]) 
'''

np.hsplit(a, 3) 
'''
[array([[0],  
       [3],  
       [6]]),  
 array([[1],  
       [4],  
       [7]]),  
 array([[2],  
       [5],  
       [8]])] 

'''
#方法二:用split函式並指定軸為1
np.split(a, 3, axis=1)  


#垂直分割
#垂直分割是沿著垂直的軸切分陣列:

np.vsplit(a, 3)  
'''
[array([[0, 1, 2]]), array([[3, 4, 5]]), array([[6, 7, 8]])] 
'''

#方法二
#solit函式並指定軸為1
np.split(a, 3, axis=0)

#面向深度的分割
#dsplit函式使用的是面向深度的分割
c = arange(27).reshape(3, 3, 3)  

'''
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]]])  

'''

np.dsplit(c, 3) 
'''
[array([[[ 0],  
        [ 3],  
        [ 6]],  
  
       [[ 9],  
        [12],  
        [15]],  
  
       [[18],  
        [21],  
        [24]]]),  
 array([[[ 1],  
        [ 4],  
        [ 7]],  
  
       [[10],  
        [13],  
        [16]],  
  
       [[19],  
        [22],  
        [25]]]),  
 array([[[ 2],  
        [ 5],  
        [ 8]],  
  
       [[11],  
        [14],  
        [17]],  
  
       [[20],  
        [23],  
        [26]]])]  
'''

4.判斷陣列是否共享記憶體,也是用來直接判斷資料是複製的還是映象的

#方法一:
a = np.arange(50)
b = a.reshape((5, 10))
print (b.base is a)

#方法二:
print (np.may_share_memory(a, b))

#方法三:
print (b.flags['OWNDATA'])  #False -- apparently this is a view
e = np.ravel(b[:, 2])
print (e.flags['OWNDATA'])  #True -- Apparently this is a new numpy object.

5.陣列複製和映象( view )

1.)完全不復制 ,簡單的賦值,而不復制陣列物件或它們的資料。

a = np.arange(12)  
b = a      #不建立新物件  
b is a     # a和b是同一個陣列物件的兩個名字
#  true
    
b.shape = 3,4    #也改變了a的形狀 
print a.shape
'''
(3, 4)
'''

2.) view的用法 檢視方法創造一個新的陣列物件指向同一資料。

事實上,沒有任何資料型別是固定的,主要取決於如何看待這片資料的記憶體區域。
在numpy.ndarray.view中,提供對記憶體區域不同的切割方式,來完成資料型別的轉換,而無須要對資料進行額外的copy,來節約記憶體空間。

c = a.view()  
c is a  
# false

c.base is a      #c是a持有資料的映象 
#true

c.shape = 2,6    # a的形狀沒變
print(a.shape)  # (3, 4) 

c[0,4] = 1234        #a的資料改變了
print  a
'''
array([[   0,    1,    2,    3],  
       [1234,    5,    6,    7],  
       [   8,    9,   10,   11]])
'''

3.)切片陣列返回它的一個檢視
s = a[ : , 1:3]     # 獲得每一行1,2處的元素
s[:] = 10           # s[:] 是s的映象。注意區別s=10 and s[:]=10 
print a
'''
array([[   0,   10,   10,    3],  
       [1234,   10,   10,    7],  
       [   8,   10,   10,   11]])  
'''

4.)深複製,這個複製方法完全複製陣列和它的資料。
d = a.copy()       #建立了一個含有新資料的新陣列物件
d is a
#False

d.base is a        #d和a現在沒有任何關係
#False  

d[0,0] = 9999
print a
'''
array([[   0,   10,   10,    3],  
       [1234,   10,   10,    7],  
       [   8,   10,   10,   11]]) 
'''

5.)在影象處理中的應用

當需要對輸入影象三個通道進行相同的處理時,使用cv2.split和cv2.merge是相當浪費資源的,因為任何一個通道的資料對處理來說都是一樣的,我們可以用view來將其轉換為一維矩陣後再做處理,這要不需要額外的記憶體開銷和時間開銷。

def createFlatView(array):  
    """Return a 1D view of an array of any dimensionality."""  
    flatView = array.view()  
    flatView.shape = array.size  
    return flatView  


5.陣列遍歷

a = np.arange(9).reshape(3,3) 
for row in a:
  print row 
'''
[0 1 2]
[3 4 5]
[6 7 8]

'''

#對陣列中每個元素都進行處理,可以使用flat屬性,該屬性是一個數組元素迭代器:
for element in a.flat:
  print element
'''
0 1 2 3 4 5 6 7 8
'''

6.資料型別轉換
np.float64(42) # to float64
#42.0

np.int8(42.0)  # to int8
#42

np.bool(42)   # to bool
#True  

np.bool(42.0)  # to bool
#True  

np.float(True)  # to float
#1.0 


#函式的引數中可以指定引數的型別
arange(7, dtype=uint16)  
    array([0, 1, 2, 3, 4, 5, 6], dtype=uint16)

6.陣列序列化和反序列化

序列化是將物件狀態轉換為可保持或傳輸的形式的過程。序列化的補集是反序列化,後者將流轉換為物件。這兩個過程一起保證資料易於儲存和傳輸。

python 提供pickle, cPickle 物件序列化/反序列化

這裡使用numpy 提供的函式

#預定義資料欄位名稱和型別  
table = np.loadtxt('example.txt',dtype='names': ('ID', 'Result', 'Type'),\  
    'formats': ('S4', 'f4', 'i2'))  
np.savetxt('somenewfile.txt')#序列化  
#二進位制檔案載入,儲存  
data = np.empty((1000, 1000))  
np.save('test.npy', data)  
np.savez('test.npz', data)#採用壓縮  
newdata = np.load('test.npy')   

7.陣列中最大值最小值
mat.max(0)#n維陣列axis=0維度的最小值,最大值  
mat.min(0)# 


參考和轉載: