第四課 - NumPy 入門
本課內(nèi)容:
- 0. 導(dǎo)入 NumPy 包
- 1. 創(chuàng)建 NumPy 數(shù)組
- 2. 索引和切片
- 3. 讀取文件
- 4. 布爾型索引
- 5. 數(shù)組的運(yùn)算
- 6. 常用函數(shù)舉例
NumPy 是 Numerical Python 的簡(jiǎn)稱庆尘,是 Python 科學(xué)計(jì)算的核心包犹褒。其強(qiáng)大的科學(xué)計(jì)算能力在很多高級(jí)包中得到應(yīng)用。比如,在后續(xù)課程中的 pandas 就是基于 NumPy 的一種工具包翻屈。
numpy主要特點(diǎn)
- 使用向量化操作以簡(jiǎn)化數(shù)據(jù)處理瞳脓,包括取子集锋玲,過濾蜗字,和變形等等。
- 高效的數(shù)據(jù)總結(jié)娩缰,排序功能灸撰。
- numpy數(shù)組中的元素只能是同一種數(shù)據(jù)類型
- numpy數(shù)組的運(yùn)算,更簡(jiǎn)潔且高效
0. 導(dǎo)入 NumPy 包
import numpy as np
1. 創(chuàng)建 NumPy 數(shù)組
numpy的一個(gè)重要對(duì)象(object)是 ndarray拼坎, 也稱 NumPy 數(shù)組
- ndarray 是 Multidimensional Array的縮寫浮毯,中文稱為多(multi)維(dimensional)數(shù)組(array)。
- 數(shù)組可以存儲(chǔ)大量數(shù)據(jù)并在其進(jìn)行數(shù)學(xué)運(yùn)算泰鸡,我們可以使用數(shù)組在一塊數(shù)據(jù)上進(jìn)行操作從而避免使用循環(huán)來操作單個(gè)元素亲轨。
1-1. 一維數(shù)組
value = [1,2,3]
arr1d = np.array(value)
arr1d
輸出:array([1, 2, 3])
& type(arr1d) # 查看數(shù)據(jù)類型
輸出:numpy.ndarray
& arr1d.ndim # 查看維度,返回1鸟顺,說明是一維數(shù)組
輸出:1
1-2. 二維數(shù)組
value = [[1,2,3],[4,5,6]] # 從二維列表中創(chuàng)建二維數(shù)組
arr2d = np.array(value)
arr2d
輸出:array([[1, 2, 3],
[4, 5, 6]])
二維數(shù)組就類似一個(gè)矩陣
| 1 2 3 |
| 4 5 6 |
- 0軸 (axis=0) 是列,也就是垂直方向
- 1軸 (axis=1) 是行器虾,也就是水平方向
- 矩陣對(duì)于數(shù)據(jù)分析來說讯嫂,是一個(gè)重要的概念,一般用列來代表觀測(cè)對(duì)象的各種屬性兆沙、特征欧芽,用行來記錄每一個(gè)觀測(cè)對(duì)象的一組測(cè)量數(shù)據(jù)。
& arr2d.ndim #查看維度葛圃,返回2千扔,代表二維數(shù)組
輸出:2
& arr2d.shape
輸出:(2, 3) # 注意,結(jié)果存儲(chǔ)在一個(gè)元組里
- 使用shape來查看行數(shù)以及列數(shù)
- arr2d是一個(gè)兩行三列的二維數(shù)組
1-3. 其他快速創(chuàng)建數(shù)組的函數(shù)
- 一維數(shù)組
np.zeros(5) # 創(chuàng)建全0數(shù)組
輸出:array([ 0., 0., 0., 0., 0.])
np.empty(10) # 創(chuàng)建空數(shù)組库正,其元素的值不一定為0曲楚,它返回的是一些未初始化的垃圾值。
輸出:array([ -1.72723371e-077, 2.00389882e+000, 1.94100914e-080,
3.90719476e-086, 2.28191497e+232, 4.08955235e-080,
2.55671117e+161, 1.98854918e-081, 3.03467606e-086,
6.95335581e-309])
np.ones(5) # 創(chuàng)建元素都為1的數(shù)組
輸出:array([ 1., 1., 1., 1., 1.])
np.arange(10)
- np.arange 類似于Python中的range函數(shù)褥符,是它的數(shù)組版
- 數(shù)組元素從0 到 9
輸出:array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
np.arange(2, 10, 2)
- 10以內(nèi)的偶數(shù)構(gòu)成數(shù)組
- arange() 中的參數(shù)分別是:起始值龙誊,終值(不被包含),步長(zhǎng)(類似等差數(shù)列)
輸出:array([2, 4, 6, 8])
np.random.rand(5) # 創(chuàng)建 [0, 1) 之間的隨機(jī)數(shù)
輸出:array([ 0.78408467, 0.38615392, 0.20028395, 0.4741344 , 0.8794998 ])
np.random.randint(1, 10, size=8) # 創(chuàng)建指定范圍內(nèi)的隨機(jī)整數(shù)
輸出:array([6, 4, 9, 2, 2, 3, 1, 3])
- 二維數(shù)組
np.zeros((2,3)) # 輸入的是元組
輸出:array([[ 0., 0., 0.],
[ 0., 0., 0.]])
np.empty((3,3))
輸出:array([[ 4.94065646e-324, 9.88131292e-324, 1.48219694e-323],
[ 1.97626258e-323, 2.47032823e-323, 2.96439388e-323],
[ 3.45845952e-323, 3.95252517e-323, 4.44659081e-323]])
In [17]:
np.random.rand(3,5)
輸出:array([[ 0.61108731, 0.28309232, 0.3224213 , 0.97465818, 0.67250497],
[ 0.42063949, 0.97061055, 0.63820155, 0.53084675, 0.65285927],
[ 0.36935495, 0.4308036 , 0.40956562, 0.42018877, 0.78010878]])
np.random.randint(1, 10, size=(3,5))
輸出:array([[9, 5, 7, 9, 4],
[2, 6, 6, 7, 3],
[6, 7, 4, 5, 1]])
2. 索引和切片
選取數(shù)組中的元素或者是數(shù)據(jù)的子集
使用[ ]運(yùn)算符對(duì)數(shù)進(jìn)行切片和索引等操作
2-1. 一維數(shù)組
- 一維數(shù)組的索引和切片喷楣,與Python列表差不多
arr = np.arange(10) # 創(chuàng)建一個(gè)一維的數(shù)組
arr
輸出:array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
arr[3] # 一維數(shù)組的索引
輸出:3
arr[3:7] # 一維數(shù)組的切片
輸出:array([3, 4, 5, 6])
* 數(shù)組切片是原始數(shù)組的視圖趟大,也就是說數(shù)據(jù)不會(huì)被復(fù)制鹤树,任何修改都會(huì)影響到原有的數(shù)組上。
arr2 = arr[3:7]
arr2[0] = 13
arr # arr的元素被改變了
輸出:array([ 0, 1, 2, 13, 4, 5, 6, 7, 8, 9])
* 如果要對(duì)數(shù)組的切片進(jìn)行復(fù)制逊朽,需要使用.copy()
方法
arr = np.arange(10)
arr3 = arr[3:7].copy() # 使用.copy()
arr3[0] = 13
arr # arr的元素沒有被改變
輸出:array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
2-2. 二維數(shù)組
mat = np.arange(1,17) # 用一維數(shù)組來生成二維數(shù)組
mat.shape = (4, 4)
mat
輸出:array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, 15, 16]])
- 獲取二維數(shù)組的某一行
- 對(duì)于二維數(shù)組罕伯,每個(gè)索引對(duì)應(yīng)的是一個(gè)一維數(shù)組!
mat[0] # 對(duì)應(yīng)第0行
輸出:array([1, 2, 3, 4])
* 獲取二維數(shù)組的行
* mat[起始行:終結(jié)行] :從起始行開始叽讳,但不包括終結(jié)行
* mat[起始行:] : 從起始行到最后一行
* mat[: 終結(jié)行] : 從第0行到終結(jié)行但不包括終結(jié)行
mat[1:3] #等價(jià)于mat[[1,2]]
輸出:array([[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
- 類似于列表切片追他,查看第二和第三行
- ndarray的切片是沿著行方向的
- 和列表切片一樣,第三行是不包括的
* 獲取二維數(shù)組的行和列
* 查看某一個(gè)元素绽榛,有兩種方式
mat[1][3] # 先獲取第一行湿酸,再查找第三列
輸出:8
mat[1,3] # 用一個(gè)逗號(hào)來隔開行和列的索引
輸出:8
* 索引和切片的混用
方括號(hào)第一個(gè)參數(shù)指定要取的行位置,第二個(gè)參數(shù)指定要取得列位置灭美,中間使用逗號(hào)隔開
mat[0:3, 1] # 取出第0行到第2行推溃,第1列
輸出:array([ 2, 6, 10])
mat[2:, 2:]
輸出:array([[11, 12],
[15, 16]])
- 可以同時(shí)在行和列同時(shí)做切片
- 取出第1行到最后一行,第2列到第3列
3. 讀取文件
wine_data = np.genfromtxt('winequality-red.csv', delimiter=';', skip_header=1)
wine_data
輸出:array([[ 7.4 , 0.7 , 0. , ..., 0.56 , 9.4 , 5. ],
[ 7.8 , 0.88 , 0. , ..., 0.68 , 9.8 , 5. ],
[ 7.8 , 0.76 , 0.04 , ..., 0.65 , 9.8 , 5. ],
...,
[ 6.3 , 0.51 , 0.13 , ..., 0.75 , 11. , 6. ],
[ 5.9 , 0.645, 0.12 , ..., 0.71 , 10.2 , 5. ],
[ 6. , 0.31 , 0.47 , ..., 0.66 , 11. , 6. ]])
讀取紅酒品質(zhì)數(shù)據(jù)届腐,原數(shù)據(jù)以分號(hào)進(jìn)行分隔铁坎,并且跳過第一行
數(shù)據(jù)文件中第一行是字段名,屬于字符串類型犁苏,而numpy數(shù)組的所有元素必須是一致的數(shù)據(jù)類型硬萍,故需要跳過第一行,否則會(huì)出錯(cuò)围详。
wine_data.shape # 查看數(shù)組的形狀朴乖,行和列
輸出:(1599, 12)
wine_data.dtype # 查看數(shù)組中元素的類型
輸出:dtype('float64')
wine = wine_data[:10, [8,10,11]]
- 取前10行數(shù)據(jù)中的8,10助赞,11列,分別對(duì)應(yīng)紅酒的PH值买羞、酒精度、質(zhì)量評(píng)分這三類屬性#
為簡(jiǎn)單起見雹食,后續(xù)將使用這組數(shù)據(jù)進(jìn)行分析示例
wine
輸出:array([[ 3.51, 9.4 , 5. ],
[ 3.2 , 9.8 , 5. ],
[ 3.26, 9.8 , 5. ],
[ 3.16, 9.8 , 6. ],
[ 3.51, 9.4 , 5. ],
[ 3.51, 9.4 , 5. ],
[ 3.3 , 9.4 , 5. ],
[ 3.39, 10. , 7. ],
[ 3.36, 9.5 , 7. ],
[ 3.35, 10.5 , 5. ]])
4. 布爾型索引
- 之前的切片索引方法是通過指定行或列的位置來取一個(gè)數(shù)組的一部分
- 顧名思義畜普,布爾索引是通過一個(gè)布爾型數(shù)組來確定所需要的行或者列的位置
- 當(dāng)行或列位置對(duì)應(yīng)的布爾索引為True的時(shí)候,我們會(huì)保留這個(gè)行或列群叶。反之吃挑,當(dāng)對(duì)應(yīng)的布爾索引為False的時(shí)候,則不選取街立。
例1:獲取評(píng)分大于5的紅酒數(shù)據(jù)
wine[:, 2] > 5# 第2列數(shù)據(jù)代表質(zhì)量評(píng)分
輸出:array([False, False, False, True, False, False, False, True, True, False], dtype=bool)
wine[wine[:, 2] > 5]
輸出:array([[ 3.16, 9.8 , 6. ],
[ 3.39, 10. , 7. ],
[ 3.36, 9.5 , 7. ]])
例2:獲取評(píng)分大于5舶衬,且酒精度大于等于10的紅酒數(shù)據(jù)
mask = (wine[:,2] > 5) & (wine[:,1] >= 10)
mask
- 第1列代表酒精度,第2列代表評(píng)分
- 使用布爾運(yùn)算符 (& , | ) 來組合多個(gè)布爾條件
輸出:array([False, False, False, False, False, False, False, True, False, False], dtype=bool)
wine[mask]
輸出:array([[ 3.39, 10. , 7. ]])
5. 數(shù)組的運(yùn)算
5-1. 數(shù)組與單個(gè)數(shù)之間的運(yùn)算
mat / 2 # 每個(gè)元素都除以2
輸出:array([[ 0.5, 1. , 1.5, 2. ],
[ 2.5, 3. , 3.5, 4. ],
[ 4.5, 5. , 5.5, 6. ],
[ 6.5, 7. , 7.5, 8. ]])
mat ** 2 # 每個(gè)元素都平方
輸出:array([[ 1, 4, 9, 16],
[ 25, 36, 49, 64],
[ 81, 100, 121, 144],
[169, 196, 225, 256]])
(mat + 100) / 100
輸出:array([[ 1.01, 1.02, 1.03, 1.04],
[ 1.05, 1.06, 1.07, 1.08],
[ 1.09, 1.1 , 1.11, 1.12],
[ 1.13, 1.14, 1.15, 1.16]])
例:將紅酒評(píng)分?jǐn)?shù)據(jù)轉(zhuǎn)換成百分制赎离,即原評(píng)分乘以10
score = wine[:, 2] # 獲取評(píng)分?jǐn)?shù)據(jù)的數(shù)組
score
輸出:array([ 5., 5., 5., 6., 5., 5., 5., 7., 7., 5.])
score * 10
輸出:array([ 50., 50., 50., 60., 50., 50., 50., 70., 70., 50.])
- Numpy 數(shù)組的任何算數(shù)運(yùn)算约炎,都會(huì)將運(yùn)算運(yùn)用到元素級(jí)別。
- 這樣的矢量化運(yùn)算是NumPy 數(shù)組的優(yōu)勢(shì), Python列表要實(shí)現(xiàn)這一操作就需要編寫循環(huán)圾浅。
5-2. 數(shù)組與數(shù)組之間的運(yùn)算
- 兩個(gè)行列數(shù)相符的數(shù)列可以進(jìn)行運(yùn)算
- 運(yùn)算操作將應(yīng)用到數(shù)列中對(duì)應(yīng)的每一個(gè)元素
mat + mat # 兩個(gè)數(shù)組相加
輸出:array([[ 2, 4, 6, 8],
[10, 12, 14, 16],
[18, 20, 22, 24],
[26, 28, 30, 32]])
np.add(mat, mat)
輸出:array([[ 2, 4, 6, 8],
[10, 12, 14, 16],
[18, 20, 22, 24],
[26, 28, 30, 32]])
mat * mat
- 兩個(gè)數(shù)組相乘掠手, 也可以使用np.multiply函數(shù)實(shí)現(xiàn)
- 對(duì)應(yīng)元素之間的乘法,不同于線性代數(shù)中的矩陣相乘
輸出:array([[ 1, 4, 9, 16],
[ 25, 36, 49, 64],
[ 81, 100, 121, 144],
[169, 196, 225, 256]])
例:將每一行的紅酒數(shù)據(jù)與第0行數(shù)據(jù)進(jìn)行比較狸捕,即計(jì)算與第0行數(shù)據(jù)的差值
wine - wine[0]
- 注意喷鸽,這里兩個(gè)數(shù)組的大小不同
- 大小不同的數(shù)組之間的運(yùn)算叫做廣播
輸出:array([[ 0. , 0. , 0. ],
[-0.31, 0.4 , 0. ],
[-0.25, 0.4 , 0. ],
[-0.35, 0.4 , 1. ],
[ 0. , 0. , 0. ],
[ 0. , 0. , 0. ],
[-0.21, 0. , 0. ],
[-0.12, 0.6 , 2. ],
[-0.15, 0.1 , 2. ],
[-0.16, 1.1 , 0. ]])
6. 常用函數(shù)舉例
wine
輸出:array([[ 3.51, 9.4 , 5. ],
[ 3.2 , 9.8 , 5. ],
[ 3.26, 9.8 , 5. ],
[ 3.16, 9.8 , 6. ],
[ 3.51, 9.4 , 5. ],
[ 3.51, 9.4 , 5. ],
[ 3.3 , 9.4 , 5. ],
[ 3.39, 10. , 7. ],
[ 3.36, 9.5 , 7. ],
[ 3.35, 10.5 , 5. ]])
例1:計(jì)算紅酒數(shù)據(jù)每一個(gè)屬性的平均值(即每一列數(shù)據(jù)的平均值)
np.sum(wine)
- 首先用np.sum()獲取數(shù)據(jù)的和
- 這里將數(shù)組中的所有元素相加了,但是我們想要的是每一列數(shù)據(jù)的和
輸出:185.55000000000001
np.sum(wine, axis=0) # 使用axis參數(shù)來設(shè)置求和的方式灸拍, axis=0表示對(duì)列求和做祝,axis=1表示對(duì)行求和
輸出:array([ 33.55, 97. , 55. ])
np.sum(wine, axis=0) / len(wine) # 每列的總和除以行數(shù),得到每列的均值
輸出:array([ 3.355, 9.7 , 5.5 ])
np.mean(wine, axis=0) # 直接使用np.mean()函數(shù)鸡岗,但記得設(shè)置axis參數(shù)
輸出:array([ 3.355, 9.7 , 5.5 ])
例2:找到紅酒數(shù)據(jù)每一項(xiàng)屬性中的最大和最小值
np.max(wine, axis=0)
輸出:array([ 3.51, 10.5 , 7. ])
np.min(wine, axis=0)
輸出:array([ 3.16, 9.4 , 5. ])
例3:將紅酒數(shù)據(jù)中的PH值數(shù)據(jù)進(jìn)行排序
np.sort(wine[:, 0])
輸出:array([ 3.16, 3.2 , 3.26, 3.3 , 3.35, 3.36, 3.39, 3.51, 3.51, 3.51])
例4:找出紅酒數(shù)據(jù)中都有哪幾種評(píng)分混槐,即求評(píng)分?jǐn)?shù)據(jù)中不重復(fù)的打分
np.unique(wine[:,2])
輸出:array([ 5., 6., 7.])
例5:生成一組新的數(shù)據(jù),如果評(píng)分大于5轩性,其值為‘Good’声登;如果評(píng)分小于等于5,其值為‘Bad'
new = list() # 使用循環(huán)和判斷語句
for s in wine[:,2] :
if s > 5 :
new.append('Good')
else:
new.append('Bad')
new
輸出:['Bad', 'Bad', 'Bad', 'Good', 'Bad', 'Bad', 'Bad', 'Good', 'Good', 'Bad']
[('Good' if s > 5 else 'Bad') for s in wine[:,2]] # 使用列表解析
輸出:['Bad', 'Bad', 'Bad', 'Good', 'Bad', 'Bad', 'Bad', 'Good', 'Good', 'Bad']
np.where(wine[:,2] > 5, 'Good', 'Bad') # 使用np.where()函數(shù)
輸出:array(['Bad', 'Bad', 'Bad', 'Good', 'Bad', 'Bad', 'Bad', 'Good', 'Good',
'Bad'],
dtype='<U4')