Numpy是Python語言中的最基礎的和最強大的科學計算和數據處理的工具包,如數據分析工具的pandas也是基於Numpy構建的,機器學習包的sklearn中也大量使用了Numpy的方法。本文介紹了Numpy的n維數組在數據處理和分析中的所有核心應用。
目錄結構:
1、如何構建Numpy數組
2、如何觀察數組的屬性的大小和形狀(shape)
3、如何從數組中提取出特定的項
4、如何從現有的數組定義新的數組
5、多維數組的重構(reshaping)和扁平化(flaflattening)
6、如何通過numpy生成序列數(sequences),重複數(repetitions)和隨機數(random)
7、總結
1、構建numpy數組的方法很多,比較常用的方法是用np.array函數對列表進行轉化。
# 通過列表創建一維數組
import numpy as np
list1 = [0,1,2,3,4]
arr1d = np.array(list1)
#打印數組和類型
print(type(arr1d))
arr1d
輸出:
<class 'numpy.ndarray'>
array([0, 1, 2, 3, 4])
數組和列表的最關鍵的區別是:數組是基於向量化操作的,列表不是,我們在實際的項目中處理的數據一般是矩陣數據結構,對於該數據以行向量或者列向量的形式進行計算,向量計算是基於數組實現的,因此數組比列表的應用更廣。
函數可以應用到數組的每一項,列表不行。
比如,不可以對列表的每一項數據都加2,這些都是錯誤的。
list1 + 2 # 錯誤
但是可以對數組的某一項數據都加2(基於上面的代碼)
# Add 2 to each element of arr1d
arr1d + 2
#> array([2, 3, 4, 5, 6])
另一個區別是已經定義的Numpy數組不可以增加數組的大小,只能通過定義一個數組來實現,但是列表可以增加大小
然而,Numpy有更多的優勢,讓我們來看看。
Numpy可以通過列表中的列表來創建二維數組。
import numpy as np
# Create a 2d array from a list of lists
list2 = [[0,1,2], [3,4,5], [6,7,8]]
arr2d = np.array(list2)
arr2d
#> array([[0, 1, 2],
#> [3, 4, 5],
#> [6, 7, 8]])
你也可以通過dtype參數來指定數組的類型,一些最常用的Numpy類型是:‘float’,‘int’,‘bool’,‘str’和’object’。
# Create a float 2d array
arr2d_f = np.array(list2, dtype='float')
arr2d_f
#> array([[ 0., 1., 2.],
#> [ 3., 4., 5.],
#> [ 6., 7., 8.]])
輸出的結果的小數點表示的是float類型,你也可以通過astype方法轉換成不同的類型。
# 轉換成‘int’類型
arr2d_f.astype('int')
#> array([[0, 1, 2],
#> [3, 4, 5],
#> [6, 7, 8]])
# 先轉換‘int’類型,再轉換‘str’類型
arr2d_f.astype('int').astype('str')
#> array([['0', '1', '2'],
#> ['3', '4', '5'],
#> ['6', '7', '8']],
#> dtype='U21')
另外一個區別就是數組要求所有的項是同一個類型,list沒有這個限制。如果你想要一個數組包含不同的類型,設置’dtype’爲’object’。
# 構建布爾類型數組
arr2d_b = np.array([1, 0, 10], dtype='bool')
arr2d_b
#> array([ True, False, True], dtype=bool)
混合數據類型使用dtype='object'
# 構建包含數值和字符串的數組
arr1d_obj = np.array([1, 'a'], dtype='object')
arr1d_obj
#> array([1, 'a'], dtype=object)
最終使用tolist()函數使數組轉化爲列表。
# Convert an array back to a list
arr1d_obj.tolist()
#> [1, 'a']
總結數組和列表的主要區別:
1、數組支持向量化操作,列表不支持;
2、數組不能改變長度,列表可以;
3、數組的每一項都是同一類型,list可以有多重的類型;
4、同樣的長度的數組所佔用的空間小於列表。
2、如何觀察數組的屬性的大小和形狀(shape)
一維數組由列表構建,二維數組arr2d由列表的列表構建,二維數組有行和列,比如矩陣,三維數組有嵌入了連個列表的列表構建。
假設跟定一個數組,我們怎麼去了解該數組的屬性。
數組的屬性包括:
數組的維度(ndim)
數組的形狀(shape)
數組的類型(dtype)
數組的大小(size)
數組元素的表示(通過索引)
import numpy as np
# 定義3行4列的二維數組
list2 = [[1, 2, 3, 4],[3, 4, 5, 6], [5, 6, 7, 8]]
arr2 = np.array(list2, dtype='float')
arr2
#> array([[ 1., 2., 3., 4.],
#> [ 3., 4., 5., 6.],
#> [ 5., 6., 7., 8.]])
使用數組的屬性:
# 形狀(shape)
print('Shape: ', arr2.shape)
# 數組類型(dtype)
print('Datatype: ', arr2.dtype)
# 數組大小(size)
print('Size: ', arr2.size)
# 數組維度(ndim)
print('Num Dimensions: ', arr2.ndim)
# 取數組第3行3列元素
print('items of 3 line 3 column: ', arr2[2,2])
#> Shape: (3, 4)
#> Datatype: float64
#> Size: 12
#> Num Dimensions: 2
#> items of 3 line 3 column: 7
3、如何從數組提取特定的項
數組的索引是從0開始計數的,與list類似。Numpy數組通過方括號的參數以選擇特定的元素。
import numpy as np
# 定義3行4列的二維數組
list2 = [[1, 2, 3, 4],[3, 4, 5, 6], [5, 6, 7, 8]]
arr2 = np.array(list2, dtype='float')
arr2
# 選擇矩陣的前兩行兩列
arr2[:2, :2]
#list2[:2, :2] # 錯誤TypeError: list indices must be integers or slices, not tuple
#> array([[ 1., 2.],
#> [ 3., 4.]])
numpy 數組支持布爾類型的索引,布爾型索引數組與過濾前(array-to-be-filtered)的數組大小相等,布爾型數組只包含True和False變量,True變量隨影的數組索引位置保留了過濾前的值。
arr2
#> array([[ 1., 2., 3., 4.],
#> [ 3., 4., 5., 6.],
#> [ 5., 6., 7., 8.]])
# 對數組每一個元素是否滿足某一條件,然後獲得布爾類型的輸出
b = arr2 > 4
b
#> array([[False, False, False, False],
#> [False, False, True, True],
#> [ True, True, True, True]], dtype=bool)
# 取布爾型數組保留的原始數組的值
arr2[b]
#> array([ 5., 6., 5., 6., 7., 8.])
3.1 如何反轉數組
# 反轉數組的行
arr2[::-1, ]
#> array([[ 5., 6., 7., 8.],
#> [ 3., 4., 5., 6.],
#> [ 1., 2., 3., 4.]])
# Reverse the row and column positions
# 反轉數組的行和列
arr2[::-1, ::-1]
#> array([[ 8., 7., 6., 5.],
#> [ 6., 5., 4., 3.],
#> [ 4., 3., 2., 1.]])
3.2 如何處理數組的缺失值(missing)和無窮大(infinite)值
缺失值可以使用np.nan對象表示,np.inf表示無窮大值,一下用二維數組舉例:
# 插入nan變量和inf變量
arr2[1,1] = np.nan # not a number
arr2[1,2] = np.inf # infinite
arr2
#> array([[ 1., 2., 3., 4.],
#> [ 3., nan, inf, 6.],
#> [ 5., 6., 7., 8.]])
# 用-1代替nan值和inf值
missing_bool = np.isnan(arr2) | np.isinf(arr2)
arr2[missing_bool] = -1
arr2
#> array([[ 1., 2., 3., 4.],
#> [ 3., -1., -1., 6.],
#> [ 5., 6., 7., 8.]])
3.3 如何計算n維數組的平均值,最小值和最大值
# 平均值,最大值,最小值
print("Mean value is: ", arr2.mean())
print("Max value is: ", arr2.max())
print("Min value is: ", arr2.min())
#> Mean value is: 3.58333333333
#> Max value is: 8.0
#> Min value is: -1.0
如果要求數組的行或者列的最小值沒使用np.amin函數:
# Row wise and column wise min
# 求數組行和列的最小值
# axis=0表示列,1表示行
print("Column wise minimum: ", np.amin(arr2, axis=0))
print("Row wise minimum: ", np.amin(arr2, axis=1))
#> Column wise minimum: [ 1. -1. -1. 4.]
#> Row wise minimum: [ 1. -1. 5.]
對數組的每個元素進行累加,得到一維數組,一維數組的大小與二維數組相同(就是自身迭代進行累加)
# 累加
np.cumsum(arr2)
#> array([ 1., 3., 6., 10., 13., 12., 11., 17., 22., 28., 35., 43.])
4、如何從現有的數組定義新的數組
如果使用賦值運算符從父數組定義新數組,新數組與父數組共佔同一個內存空間,如果改變新數組的值,那麼父數組頁相應的改變。
爲了讓新數組與父數組相互獨立,你需要使用copy()函數,所有的父數組都使用copy()方法構建新數組。
# Assign portion of arr2 to arr2a. Doesn't really create a new array.
# 分配arr2數組給新數組arr2a,下面方法並沒有定新數組
arr2a = arr2[:2,:2]
arr2a[:1, :1] = 100 # arr2相應位置也改變了
arr2
#> array([[ 100., 2., 3., 4.],
#> [ 3., -1., -1., 6.],
#> [ 5., 6., 7., 8.]])
# 賦值arr2數組的一部分給新數組arr2b
arr2b = arr2[:2, :2].copy()
arr2b[:1, :1] = 101 # arr2沒有改變
arr2
#> array([[ 100., 2., 3., 4.],
#> [ 3., -1., -1., 6.],
#> [ 5., 6., 7., 8.]])
5、多維數組的重構(reshaping)和扁平化(flattening)
重構(reshaping)是改變了數組項的排序,即改變了數組的形狀,未改變數組的維數。
扁平(flattening)是對多維數組轉化爲一維數組。
# 3x4數組重構爲4x3數組
arr2.reshape(4, 3)
#> array([[ 100., 2., 3.],
#> [ 4., 3., -1.],
#> [ -1., 6., 5.],
#> [ 6., 7., 8.]])
5.1 flatten()和ravel()的區別
數據的扁平化有兩種常用的方法,flatten()和ravel()。ravel()處理後的數組是父數組的引用,因此新數組的任何變換也會改變父數組,因其未用複製的方式構建數組,內存的使用率高,flatten()通過複製的方式構建新的數組。
# flatten方法
arr2.flatten()
#> array([ 100., 2., 3., 4., 3., -1., -1., 6., 5., 6., 7., 8.])
# flatten方法
b1 = arr2.flatten()
b1[0] = 101 # 改變b1的值並未影響arr2
arr2
#> array([[ 100., 2., 3., 4.],
#> [ 3., -1., -1., 6.],
#> [ 5., 6., 7., 8.]])
# ravel方法
b2 = arr2.ravel()
b2[0] = 101 # 改變b2值,相應的改變了arr2值
arr2
#> array([[ 101., 2., 3., 4.],
#> [ 3., -1., -1., 6.],
#> [ 5., 6., 7., 8.]])
6、如何通過numpy生成列數(sequence),重複數(repetitions)和隨機數(random)
np.arrange函數手動生成指定數目的序列數,與ndarray作用一樣。
import numpy as np
# 默認下限爲0
print(np.arange(5))
# 0 to 9,默認步數爲1
print(np.arange(0, 10))
# 遞增步數2
print(np.arange(0, 10, 2))
# 降序
print(np.arange(10, 0, -1))
#> [0 1 2 3 4]
#> [0 1 2 3 4 5 6 7 8 9]
#> [0 2 4 6 8]
#> [10 9 8 7 6 5 4 3 2 1]
上面通過np.arrange設置初始位置和結束位置來生成序列數,如果我們設置數組的元素個數,那麼就可以自動計算數組的低增值。
如構建1到50的數組,數組有10個元素,使用np.linspace總動計算數組的遞增值。
# 起始位置和結束位置分別爲1和50
np.linspace(start=1, stop=50, num=10, dtype=int)
#> array([ 1, 6, 11, 17, 22, 28, 33, 39, 44, 50])
我們注意到上面的例子的遞增值並不相等,有5和6兩個值,原因是計算遞增值採用了四捨五入的算法(rounding)。與np.linspace類似,np.logspace以對數尺寸的當時進行增長。
# 設置數組的精度爲小數點後兩位
np.set_printoptions(precision=2)
# 起點爲 10^1 and 終點爲 10^50,數組元素個數10,以10爲底數
np.logspace(start=1, stop=50, num=10, base=10)
#> array([ 1.00e+01, 2.78e+06, 7.74e+11, 2.15e+17, 5.99e+22,
#> 1.67e+28, 4.64e+33, 1.29e+39, 3.59e+44, 1.00e+50])
初始化數組的元素全爲1或者全爲0.
np.zeros([2,2])
#> array([[ 0., 0.],
#> [ 0., 0.]])
np.ones([2,2])
#> array([[ 0., 0.],
#> [ 0., 0.]])
6.1 如何構建重複的序列數
np.title重複整個的數組或者列表n次,np.repeat重複數組每一項n次。
a = [1,2,3]
# 重複數組a兩次
print('Tile: ', np.tile(a, 2))
# 重複數組a每項兩次
print('Repeat: ', np.repeat(a, 2))
#> Tile: [1 2 3 1 2 3]
#> Repeat: [1 1 2 2 3 3]
6.2 如何生成隨機數
random模塊包含的函數可以生成任一數組形狀的隨機數和統計分佈。
# 生成2行2列的[0,1)的隨機數
print(np.random.rand(2,2))
# 生成均值爲0方差爲1的2行2列的正態分佈值
print(np.random.randn(2,2))
# 生成[0,10)的2行2列的隨機整數
print(np.random.randint(0, 10, size=[2,2]))
# 生成一個[0,1)的隨機數
print(np.random.random())
# 生成[0,1)的2行2列的隨機數
print(np.random.random(size=[2,2]))
# 從給定的列表等概率抽樣10次
print(np.random.choice(['a', 'e', 'i', 'o', 'u'], size=10))
# 從給定的列表和對應的概率分佈抽樣10次
print(np.random.choice(['a', 'e', 'i', 'o', 'u'], size=10, p=[0.3, .1, 0.1, 0.4, 0.1])) # picks more o's
#> [[ 0.84 0.7 ]
#> [ 0.52 0.8 ]]
#> [[-0.06 -1.55]
#> [ 0.47 -0.04]]
#> [[4 0]
#> [8 7]]
#> 0.08737272424956832
#> [[ 0.45 0.78]
#> [ 0.03 0.74]]
#> ['i' 'a' 'e' 'e' 'a' 'u' 'o' 'e' 'i' 'u']
#> ['o' 'a' 'e' 'a' 'a' 'o' 'o' 'o' 'a' 'o']
6.3. 如何得到數組獨特(unique)的項和個數(counts)
np.unique函數去除數組中重複的元素,設置return_counts參數爲True,得到數組每一項的個數。
# 定義範圍爲[0,10),個數爲10的隨機整數數組
np.random.seed(100) # 隨機種子:限定隨機數一致
arr_rand = np.random.randint(0, 10, size=10)
print(arr_rand)
#> [8 8 3 7 7 0 4 2 5 2]
# 得到數組獨特的項和相應的個數(計數)
uniqs, counts = np.unique(arr_rand, return_counts=True)
print("Unique items : ", uniqs)
print("Counts : ", counts)
#> Unique items : [0 2 3 4 5 7 8]
#> Counts : [1 2 1 1 1 2 2]
7、總結
講解numpy一些核心的用法:
1、如何構建Numpy數組
2、如何觀察數組的屬性的大小和形狀(shape)
3、如何從數組中提取出特定的項
4、如何從現有的數組定義新的數組
5、多維數組的重構(reshaping)和扁平化(flaflattening)
6、如何通過numpy生成序列數(sequences),重複數(repetitions)和隨機數(random)