NumPy 學習(2): 陣列的操作

Amei1314發表於2016-09-22

1. 簡單一維陣列的操作

  一維陣列的操作類似於python自身的list型別。

In [14]: arr = np.arange(10)

In [15]: arr
Out[15]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# 第六個元素值
In [16]: arr[5]
Out[16]: 5
# 第6,,7,8這三個元素的值
In [17]: arr[5:8]
Out[17]: array([5, 6, 7])

  注意: 和list型別有很大的不同的是,操作原陣列的子序列的時候,實際上就是操作原陣列的資料。這就意味著陣列中的資料沒有被複制,任何在其子序列上的操作都會對映到原陣列上。這是因為NumPy是被設計成處理大量資料的工具,如果採用複製的方式,其計算效能會大大折扣。

In [18]: arr_slice = arr[:4]

In [19]: arr_slice[:] = 20

In [20]: arr_slice
Out[20]: array([20, 20, 20, 20])
# arr_slice中更改對映到了arr中
In [21]: arr
Out[21]: array([20, 20, 20, 20,  4,  5,  6,  7,  8,  9])

  如果要執行顯示的複製操作可以通過條用copy()函式: arr[:3].copy

2. 高維維陣列上的操作

 2.1 二維陣列索引訪問:

# 產生1-9的數
In [28]: arr2d = np.arange(1,10).reshape((3,3)) In [29]: arr2d Out[29]: array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # 訪問第一行資料 In [30]: arr2d[0] Out[30]: array([1, 2, 3]) # 訪問第一行第二個資料 In [31]: arr2d[0][1] Out[31]: 2 In [32]: arr2d[0,1] Out[32]: 2

  2.2 以劃分(slice)的方式來取得部分資料:

  

  2.3 索引(index)訪問和劃分(slice)的不同

    索引是通過座標定位資料的位置並獲取其值,arr2d[[0,1],[0,1]] 實際上是獲取(0,0),(1,1)位置上的資料,是獲取交匯點上的資料。

    劃分是將設定範圍的資料提取出來,arr2d[:2, :2]實際上就是把1-2行與1-2列中的資料劃分出來,是一個區域。

In [67]: arr2d = np.arange(1,10).reshape(3,3)
# 劃分的方式劃分資料
In [68]: arr2d[:2, :2] Out[68]: array([[1, 2], [4, 5]]) # 以索引方式訪問資料 In [69]: arr2d[[0,1],[0,1]] Out[69]: array([1, 5])

    將8 * 4 的一個二維陣列的1,3,5,7行,和 4,3,2,1列重新組成一個二維陣列。如果用以下方法,肯定是不行的:

In [71]: arr = np.arange(32).reshape(8,4)

In [72]: arr
Out[72]: 
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, 27],
       [28, 29, 30, 31]])
# 錯誤的做法,其實是獲取(0,3),(2,2),(4,1),(6,0)位置上的值
In [73]: arr[[0,2,4,6],[3,2,1,0]]
Out[73]: array([ 3, 10, 17, 24])

    正確的方法:

# 先獲取1,3,5,7行的資料
In [74]: arr_temp = arr[[0,2,4,6]] In [75]: arr_temp Out[75]: array([[ 0, 1, 2, 3], [ 8, 9, 10, 11], [16, 17, 18, 19], [24, 25, 26, 27]]) # 劃分陣列,並組成新的陣列 In [76]: arr_temp[:,[3,2,1,0]] Out[76]: array([[ 3, 2, 1, 0], [11, 10, 9, 8], [19, 18, 17, 16], [27, 26, 25, 24]])

    實現此功能還可以呼叫np.ix_() 函式:

In [77]: arr[np.ix_([0,2,4,6],[3,2,1,0])]
Out[77]: 
array([[ 3,  2,  1,  0],
       [11, 10,  9,  8],
       [19, 18, 17, 16],
       [27, 26, 25, 24]])

 

  2.4 高維陣列訪問:

# 用reshape生成三維陣列
In [33]: arr3d = np.arange(1,13).reshape((2,2,3)) In [34]: arr3d Out[34]: array([[[ 1, 2, 3], [ 4, 5, 6]], [[ 7, 8, 9], [10, 11, 12]]]) # 用傳統的array函式生成三維陣列 In [35]: arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]) In [36]: arr3d Out[36]: array([[[ 1, 2, 3], [ 4, 5, 6]], [[ 7, 8, 9], [10, 11, 12]]]) # arr3d[0]是一個2*3的陣列 In [37]: arr3d[0] Out[37]: array([[1, 2, 3], [4, 5, 6]]) # arr3d[0,0]是一個一維陣列 In [38]: arr3d[0,0] Out[38]: array([1, 2, 3]) In [39]: arr3d[0,0,0] Out[39]: 1

  2.5 陣列賦值操作:

# 第一個2 * 3 陣列的值全變為 32
In [40]: arr3d[0] = 32 In [41]: arr3d Out[41]: array([[[32, 32, 32], [32, 32, 32]], [[ 7, 8, 9], [10, 11, 12]]]) In [42]: old_values = arr3d[0] # 將一個2 *3 的陣列賦給arr3d[0] In [43]: arr3d[0] = old_values In [44]: arr3d Out[44]: array([[[32, 32, 32], [32, 32, 32]], [[ 7, 8, 9], [10, 11, 12]]])


3. 布林索引
  資料準備:

# 七個名字
In [2]: names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe']) In [3]: names Out[3]: array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'], dtype='|S4') # 生成7行,4列的隨機陣列,每一行對應names中一個人的資料 In [4]: data = randn(7,4) In [5]: data Out[5]: array([[ 0.54643196, 0.98876451, 1.55499825, 1.88240798], [ 1.39695977, -1.59576937, 0.42445372, 1.73588157], [ 0.61992879, -0.13706965, 1.87869165, 1.28724149], [ 0.59114346, -0.50032077, 1.29182197, 0.54644327], [ 0.59344412, -0.06566168, -0.01759809, 0.22191015], [-1.57663889, -0.08607805, -0.36048361, -0.94029737], [-0.32203015, 0.59462972, 1.10737098, -1.9473386 ]])

  用布林陣列篩選二維陣列的行,布林陣列的大小和二維陣列的行數要相同


In [12]: names=="Bob" Out[12]: array([ True, False, False, True, False, False, False], dtype=bool)
# 選取 Bob 的資料 In [
13]: data[names == "Bob"] Out[13]: array([[ 0.54643196, 0.98876451, 1.55499825, 1.88240798], [ 0.59114346, -0.50032077, 1.29182197, 0.54644327]])

  布林索引和普通索引混合使用:

In [13]: data[names == "Bob"]
Out[13]: 
array([[ 0.54643196,  0.98876451,  1.55499825,  1.88240798],
       [ 0.59114346, -0.50032077,  1.29182197,  0.54644327]])

In [14]: data[names == "Bob",2:]
Out[14]: 
array([[ 1.55499825,  1.88240798],
       [ 1.29182197,  0.54644327]])

  “與或非“操作。 python 中的 and , or 等關鍵字在這裡不能實現

# 或操作
In [20]: (names == 'Bob') | (names == 'Will')
Out[20]: array([ True, False,  True,  True,  True, False, False], dtype=bool)
# 與操作
In [21]: (names == 'Bob') & (names == 'Will')
Out[21]: array([False, False, False, False, False, False, False], dtype=bool)
# 下邊兩種 非操作
In [22]: names != "Bob"
Out[22]: array([False,  True,  True, False,  True,  True,  True], dtype=bool)

In [23]: -(names == "Bob")
Out[23]: array([False,  True,  True, False,  True,  True,  True], dtype=bool)


  二維布林型別索引:

In [24]: data < 0
Out[24]: 
array([[False, False, False, False],
       [False,  True, False, False],
       [False,  True, False, False],
       [False,  True, False, False],
       [False,  True,  True, False],
       [ True,  True,  True,  True],
       [ True, False, False,  True]], dtype=bool)
# 將小於0的元素的值改為0
In [25]: data[ data < 0] = 0

In [26]: data
Out[26]: 
array([[ 0.54643196,  0.98876451,  1.55499825,  1.88240798],
       [ 1.39695977,  0.        ,  0.42445372,  1.73588157],
       [ 0.61992879,  0.        ,  1.87869165,  1.28724149],
       [ 0.59114346,  0.        ,  1.29182197,  0.54644327],
       [ 0.59344412,  0.        ,  0.        ,  0.22191015],
       [ 0.        ,  0.        ,  0.        ,  0.        ],
       [ 0.        ,  0.59462972,  1.10737098,  0.        ]])

 

 

 

相關文章