1. 程式人生 > >用Python做資料分析之Numpy(二)

用Python做資料分析之Numpy(二)

基礎索引和切片

numpy陣列索引是一個豐富的主題,有時候給你一個數組,可能你只想對其中一部分或者個別元素進行操作,這個時候就該索引出場了。

一維陣列十分簡單,表面上與Python list是一樣的。如下:

In [60]: arr = np.arange(10)
In [61]: arr
Out[61]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
# 可以使用index選取某一個元素
In [62]: arr[5]
Out[62]: 5
# 通過切片選取相鄰的多個元素
In [63]: arr[5:8]
Out[63]: array([5, 6, 7])
In [64]: arr[5:8] = 12
In [65]: arr
Out[65]: array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])

但本質上,narray與list是不同的,區別在於,narray陣列的切面是原陣列的一個view,所謂view就是當切片部分被改變了,原陣列也會發生改變。而list的切片則是原list一部分的拷貝,切片部分是獨立的,無法通過對切片部分進行操作改變原list。之所以使用view當然是為了節約記憶體啦!

# 以下示例可以幫助理解
In [66]: arr_slice = arr[5:8]
In [67]: arr_slice
Out[67]: array([12, 12, 12])
In [68]: arr_slice[1] = 12345
In [69]: arr
Out[69]: array([ 0, 1, 2, 3, 4, 12, 12345, 12, 8, 9])
# 可以試著將arr換成list,進行上述操作

如果你擔心使用view會出問題或者有時候view不能達到目的,可以使用copy()函式,這樣就與list一樣了。

接下來看一下較為複雜一點的二維陣列

# 建立一個二維陣列
In [72]: arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
In [73]: arr2d[2]
Out[73]: array([7, 8, 9])
# 可以通過迭代的方式選擇想要的元素,如:
In [74]: arr2d[0][2]
Out[74]: 3
# narray還有一種等價的選擇元素的方法,使用逗號分割符的方式
In [75]: arr2d[0, 2]
Out[75]: 3
# 得到的結果也是一樣的

其實,二維陣列就可以看成一個有行和列的矩陣,可以通過行索引,列索引定位到想得到的元素,下面舉一個簡單的例子加以說明:

In [91]: arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
In [92]: arr2d[:2, 1:]
Out[92]: array([[2, 3], [5, 6]])

接下來介紹兩種特別的索引,它們與切片不同,返回的總是陣列子集的拷貝,也是在使用pandas時經常用到的方法:

# 1.布林索引
# 建立一個隨機二維陣列
In [100]: data = np.random.randn(3, 2)
In [101]: data
Out[101]:
array([[-1.50846056, -2.61646164],
       [ 0.85398983, -0.39198977],
       [ 0.16666416, -0.47203715]])
# 建立一個表示索引的一維陣列,每一個元素分別對應data中的一行
In [102]: names = np.array(['a', 'b', 'c'])
In [103]: names
Out[103]: array(['a', 'b', 'c'], dtype='<U1')
In [104]: data[names == 'a']
Out[104]: array([[-1.50846056, -2.61646164]])

# 2.花式索引(兩個中括號)
# 這種索引可以手動調整陣列中每行元素的位置
In [105]: data[[2, 0, 1]]
Out[105]: 
array([[ 0.16666416, -0.47203715],
       [-1.50846056, -2.61646164],
       [ 0.85398983, -0.39198977]])

最後,再提醒大家一次,這兩種方式返回的陣列不是view,切記,不是view!