NumPy库是用于科学计算的一个开源Python扩充程序库,是其他数据分析包的基础包,它为Python提供了高性能数组与矩阵运算处理能力。
2.1 ndarray多维数组
NumPy库为Python带来了真正的ndarray多维数组功能。ndarray对象是一个快速而灵活的数据集容器
2.1.1 创建ndarray数组
NumPy库能将序列数据(列表、元组、数组或其他序列类型)转换为ndarray数组
import numpy as npdata1 = [5,7,9,20] #列表
arr1 = np.array(data1)
arr1array([ 5, 7, 9, 20])data2 = (5,7,9,20) #元组
arr2 = np.array(data2)
arr2array([ 5, 7, 9, 20])data3 = [[1,2,3,4],[5,6,7,8]] #对于多维数组的创建,使用嵌套序列数据即可完成
arr3 = np.array(data3)
arr3array([[1, 2, 3, 4],
[5, 6, 7, 8]])arr3.shape #shape是ndarray维度大小的元组(2, 4)arr3.dtype #dtype是解释说明ndarray数据类型的对象dtype('int32')data4 = [1,2,2,3.45,5] #当序列中有整数和浮点数时,NumPy会把数组的dtype定义为浮点数据类型
arr4 = np.array(data4)
arr4array([1. , 2. , 2. , 3.45, 5. ])arr4.dtypedtype('float64')
特殊数组
np.zeros(8) #zeros函数可以创建指定长度或形状的全0数组array([0., 0., 0., 0., 0., 0., 0., 0.])np.ones(4) #ones函数可以创建指定长度或形状的全1数组array([1., 1., 1., 1.])np.ones((4,6)) # ones函数可以创建指定长度或形状的全1数组array([[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1., 1.]])np.empty((2,3,2)) #mpty函数可以创建一个没有具体值的数组(即垃圾值)array([[[9.42595773e-312, 2.81617418e-322],
[0.00000000e+000, 0.00000000e+000],
[6.23060065e-307, 2.42336543e-057]],
[[7.11697381e-091, 2.03997512e+184],
[1.53389691e-052, 4.74680389e+174],
[6.48224660e+170, 4.93432906e+257]]])np.arange(10) #arange函数类似于Python的内置函数range,但是arange函数主要用于创建数组array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])arr3array([[1, 2, 3, 4],
[5, 6, 7, 8]])arr5 = np.ones_like(arr3) #ones_like函数可以根据传入的数组形状和dtype创建全1数组。
arr5array([[1, 1, 1, 1],
[1, 1, 1, 1]])arr5.dtypedtype('int32')
2.1.2 ndarray对象属性
data = [[2,4,5],[3,5,7]]
arr = np.array(data)
arrarray([[2, 4, 5],
[3, 5, 7]])arr.ndim #数据轴的个数2arr.size #元组的总个数6arr.itemsize #每个元素的字节大小
#arr数组的数据类型是int32位的,
#对于计算机而言,1个字节是8位,所以arr的itemsize属性值为4。4arr.dtype #数据类型dtype('int32')
2.1.3 ndarray数据类型
数组的数据类型有很多,读者只需要记住最常见的几种数据类型即可,如浮点数(float)、整数(int)、复数(complex)、布尔值(bool)、字符串(string_)和Python对象(object)。
arr1 = np.arange(6)
arr1array([0, 1, 2, 3, 4, 5])arr1.dtypedtype('int32')arr2 = arr1.astype(np.float64)
arr2array([0., 1., 2., 3., 4., 5.])arr2.dtypedtype('float64')arr3 = arr1.astype("string_") #对于创建好的ndarray,可通过astype方法进行数据类型的转换
arr3array([b'0', b'1', b'2', b'3', b'4', b'5'], dtype='|S11')arr3.dtypedtype('S11')arr3array([b'0', b'1', b'2', b'3', b'4', b'5'], dtype='|S11')arr3.astype(np.int32) #如果数组是字符串类型且全是数字的话,也可以通过astype方法将其转换为数值类型array([0, 1, 2, 3, 4, 5])arr = np.array(['2','hello'])
arrarray(['2', 'hello'], dtype='<U5')arr.astype("int32") #但如果字符串中有字符时,转换时就会报错,如图2.15所示。---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_30528/2154082202.py in <module>
----> 1 arr.astype("int32") #但如果字符串中有字符时,转换时就会报错,如图2.15所示。
ValueError: invalid literal for int() with base 10: 'hello'arr1 = np.arange(10)
arr1.dtypedtype('int32')arr2 = np.ones(5)
arr2.dtypedtype('float64')arr3= arr1.astype(arr2.dtype) #astype方法也可以通过另外一个数组的dtype进行转换
arr3.dtypedtype('float64')arr = np.arange(3)
arr.dtypedtype('int32')arr.astype("float64") #astype方法会创建一个新的数组,并不会改变原有数组的数据类型array([0., 1., 2.])arrarray([0, 1, 2])
2.1.4 数组变换
1.数组重塑
arr = np.arange(9)
arrarray([0, 1, 2, 3, 4, 5, 6, 7, 8])arr.reshape((3,3)) #对于定义好的数组,可以通过reshape方法改变其数据维度。传入的参数为新维度的元组,array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])arr = np.array([[3,4,5],[1,2,3]])
arr.reshape((3,2)) #多维数组也可以被重塑array([[3, 4],
[5, 1],
[2, 3]])arr = np.arange(12)
arr.reshape((3,-1)) #reshape的参数中的一维参数可以设置为-1,表示数组的维度可以通过数据本身来推断array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])arr = np.arange(10).reshape((5,2))
arrarray([[0, 1],
[2, 3],
[4, 5],
[6, 7],
[8, 9]])arr.ravel() #与reshape相反的方法是数据散开(ravel)数据或扁平化(flatten)array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])arr.flatten()array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])arr #数据重塑不会改变原数组。array([[0, 1],
[2, 3],
[4, 5],
[6, 7],
[8, 9]])
2.数组合并
arr1 = np.arange(12).reshape((3,-1))
arr1array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])arr2 = np.arange(12,24).reshape((3,4))
arr2array([[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]])np.concatenate([arr1,arr2],axis = 0)
#数组合并用于几个数组间的操作,concatenate方法通过指定轴方向,将多个数组合并在一起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]])np.concatenate([arr1,arr2],axis = 1)array([[ 0, 1, 2, 3, 12, 13, 14, 15],
[ 4, 5, 6, 7, 16, 17, 18, 19],
[ 8, 9, 10, 11, 20, 21, 22, 23]])np.vstack((arr1,arr2))
#NumPy中提供了几个比较简单易懂的方法,也可以进行数组合并,如vstack和hstackarray([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]])np.hstack((arr1,arr2))array([[ 0, 1, 2, 3, 12, 13, 14, 15],
[ 4, 5, 6, 7, 16, 17, 18, 19],
[ 8, 9, 10, 11, 20, 21, 22, 23]])
3.数组拆分
arr = np.arange(12).reshape((6,2))
arrarray([[ 0, 1],
[ 2, 3],
[ 4, 5],
[ 6, 7],
[ 8, 9],
[10, 11]])np.split(arr,[2,4])
#数组拆分是数组合并的相反操作,通过split方法可以将数组拆分为多个数组[array([[0, 1],
[2, 3]]),
array([[4, 5],
[6, 7]]),
array([[ 8, 9],
[10, 11]])]
4.数组转置和轴对换
arr = np.arange(12).reshape(3,4)
arrarray([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])arr.transpose((1,0))
#转置是数组重塑的一种特殊形式,可以通过transpose方法进行转置
#transpose方法需要传入轴编号组成的元组,这样就完成了数组的转置array([[ 0, 4, 8],
[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11]])arr.T
#除了使用transpose方法外,数组有着T属性,可用于数组的转置array([[ 0, 4, 8],
[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11]])arr = np.arange(16).reshape((2,2,4))
arrarray([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])arr.swapaxes(1,2) #ndarray的swapaxes方法用于轴对换array([[[ 0, 4],
[ 1, 5],
[ 2, 6],
[ 3, 7]],
[[ 8, 12],
[ 9, 13],
[10, 14],
[11, 15]]])
2.1.5 NumPy的随机数函数
arr = np.random.randint(100,200,size=(5,4))
#可以通过randint函数生成整数随机数
arrarray([[148, 112, 119, 144],
[194, 123, 131, 172],
[147, 104, 168, 165],
[101, 116, 131, 195],
[160, 149, 194, 173]])arr = np.random.randn(2,3,5)
#如randn函数,例如,生成平均数为0,标准差为1的正态分布的随机数
arrarray([[[-0.48274113, 0.07529806, -1.81740745, 1.286357 ,
-2.55607301],
[ 1.07998934, -0.31404883, -2.297629 , -0.66385757,
0.95792075],
[-0.51302191, -2.53759601, -0.26012523, 0.71636383,
2.57003766]],
[[ 1.9540761 , 1.07840586, -0.24478286, 0.8714337 ,
0.70059484],
[-0.14210736, 0.09356213, -2.96823017, -0.55159717,
-1.63454057],
[-0.31135985, -1.52214541, 1.18820464, 1.96057804,
-0.59961429]]])arr = np.random.normal(4,5,size=(3,5))
#通过normal函数生成指定均值和标准差的正态分布的数组
arrarray([[ 1.03057369e+01, 2.59867561e-01, 1.43530708e+01,
5.99577642e+00, 1.41228837e-01],
[-1.56586338e+00, 1.99540963e+00, 7.90100440e+00,
1.64716969e+00, -7.06954944e+00],
[ 4.79296269e+00, 5.51927601e-03, 7.69985462e+00,
-8.28181420e+00, 7.95558205e+00]])arr = np.random.randint(100,200,size=(5,4))
arrarray([[107, 142, 175, 160],
[122, 124, 178, 193],
[149, 123, 198, 100],
[170, 165, 165, 139],
[116, 151, 111, 189]])np.random.permutation(arr) #对一个序列随机排序,不改变原数组array([[170, 165, 165, 139],
[116, 151, 111, 189],
[149, 123, 198, 100],
[122, 124, 178, 193],
[107, 142, 175, 160]])arrarray([[107, 142, 175, 160],
[122, 124, 178, 193],
[149, 123, 198, 100],
[170, 165, 165, 139],
[116, 151, 111, 189]])np.random.shuffle(arr) #对一个序列随机排序,改变原数组
arrarray([[170, 165, 165, 139],
[122, 124, 178, 193],
[107, 142, 175, 160],
[149, 123, 198, 100],
[116, 151, 111, 189]])
2.2 数组的索引和切片
2.2.1 数组的索引
import numpy as nparr = np.arange(10)
arrarray([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])arr[3] #一维数组的索引类似Python列表3arr[-1]9arr[2] = 123
arrarray([ 0, 1, 123, 3, 4, 5, 6, 7, 8, 9])arr = np.arange(15).reshape(3,5)
arrarray([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])arr[0] # 对于二维数组,可在单个或多个轴向上完成切片array([0, 1, 2, 3, 4])arr[2]array([10, 11, 12, 13, 14])arr[0][3] #如果需要获取各个元素3
2.2.2 数组的切片
arr = np.arange(6)
arrarray([0, 1, 2, 3, 4, 5])arr[2:5]array([2, 3, 4])arr = np.arange(12).reshape(4,3)
arrarray([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])arr[2:] #当在中括号中输入一个参数时,数组就会按照0轴(也就是第一轴)方向进行切片array([[ 6, 7, 8],
[ 9, 10, 11]])arrarray([[ 0, 1, 2],
[ 3, 4, 5],
[ 6, 7, 8],
[ 9, 10, 11]])arr[:,1]
# 通过传入多个参数(可以是整数索引和切片),即可完成任意数据的获取
# 只有使用冒号才会选取整个轴。array([ 1, 4, 7, 10])arr[:,1:2]array([[ 1],
[ 4],
[ 7],
[10]])arr[2:,1:]array([[ 7, 8],
[10, 11]])
2.3 数组的运算
2.3.1 数组和标量间的运算
arr = np.array([1,2,3])
arr*10array([10, 20, 30])arr*arrarray([1, 4, 9])arr-arrarray([0, 0, 0])arr = np.random.randn(3,3)
arrarray([[-1.10434004, -0.38970982, 0.68926712],
[-1.11139007, -0.60620091, -0.43321889],
[-0.18284226, 1.65765572, -0.79486849]])np.abs(arr) # 通过abs函数求绝对值array([[1.10434004, 0.38970982, 0.68926712],
[1.11139007, 0.60620091, 0.43321889],
[0.18284226, 1.65765572, 0.79486849]])np.square(arr) #square函数求平方array([[1.21956692, 0.15187374, 0.47508917],
[1.23518789, 0.36747954, 0.1876786 ],
[0.03343129, 2.74782248, 0.63181591]])arr1 = np.random.randint(1,10,size=(5))
arr1array([9, 1, 8, 2, 3])arr2 = np.random.randint(1,10,size = (5))
arr2array([8, 8, 8, 1, 8])np.add(arr1,arr2) #add函数用于两个数组的相加array([17, 9, 16, 3, 11])np.minimum(arr1,arr2) #minimum函数可以计算元素最小值array([8, 1, 8, 1, 3])arr = np.random.normal(2,4,size = (6))
arrarray([ 5.06802817, -1.26210681, -2.55346754, -5.70727512, 3.25494685,
5.86244808])np.modf(arr)
# 有些通用函数还可以返回两个数组,例如modf函数,可以返回数组元素的小数和整数部分(array([ 0.06802817, -0.26210681, -0.55346754, -0.70727512, 0.25494685,
0.86244808]),
array([ 5., -1., -2., -5., 3., 5.]))
2.3.3 条件逻辑运算
arr1 = np.array([1,2,3,4])
arr2 = np.array([5,6,7,8])
cond = np.array([True,False,False,True])
result = np.where(cond,arr1,arr2)
result
#如果需要通过cond的值来选取arr1和arr2的值,
#当cond为True时,选择arr1的值,否则选择arr2的值array([1, 6, 7, 4])arr = np.random.randn(4,4)
arrarray([[-0.09650043, 0.31929566, 0.67190973, -0.951201 ],
[ 1.10148109, 0.91289976, 1.24039204, -2.09494457],
[-1.47448762, -1.61059505, -0.02424096, -1.00035527],
[-1.71134107, -0.73639959, -0.63883441, 0.67764956]])new_arr = np.where(arr>0,1,-1)
new_arrarray([[-1, 1, 1, -1],
[ 1, 1, 1, -1],
[-1, -1, -1, -1],
[-1, -1, -1, 1]])
2.3.4 统计运算
arr = np.random.randn(4,4)
arrarray([[-0.33407573, 1.89601251, -0.25068698, 1.09899693],
[-0.7436235 , 0.96724716, 2.51586733, 0.78559764],
[-0.61260085, -0.1447176 , 0.75132781, 0.91617282],
[-0.33995589, -1.61785421, -0.12434649, 1.02720805]])arr.sum()5.790568998522431arr.mean()0.36191056240765196arr.std() #std函数用于求标准差1.0283623213025257arrarray([[-0.33407573, 1.89601251, -0.25068698, 1.09899693],
[-0.7436235 , 0.96724716, 2.51586733, 0.78559764],
[-0.61260085, -0.1447176 , 0.75132781, 0.91617282],
[-0.33995589, -1.61785421, -0.12434649, 1.02720805]])arr.mean(axis = 1) #用于计算指定轴方向的统计值array([ 0.60256168, 0.88127216, 0.22754555, -0.26373714])arr.sum(0)array([-2.03025597, 1.10068786, 2.89216167, 3.82797544])arr = np.arange(9).reshape(3,3)
arrarray([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])arr.cumsum(0) #所有元素的累积和array([[ 0, 1, 2],
[ 3, 5, 7],
[ 9, 12, 15]], dtype=int32)arr.cumprod(1) #所有元素的累积积array([[ 0, 0, 0],
[ 3, 12, 60],
[ 6, 42, 336]], dtype=int32)
2.3.5 布尔型数组运算
arr = np.random.randn(20)
arrarray([-0.20661816, 0.10874043, -0.40256083, -0.19071145, -1.26373101,
1.56890466, -1.01231556, -0.18248971, 1.23433954, -0.64327127,
-1.64106717, -1.20622075, 0.96636457, -0.13955697, 1.31806702,
-1.18310487, 0.02948617, -2.16793703, 0.88963934, 1.01751536])arr = np.array([True,False,False,True])
arrarray([ True, False, False, True])arr.any() #any方法用于测试数组中是否存在一个或多个TrueTruearr.all() #all方法用于检查数组中的所有值是否为TrueFalse
2.3.6 排序
arr = np.random.randn(10)
arrarray([-2.08464944, 1.79606612, 0.88671682, -1.5369521 , -1.46048203,
1.18515803, 2.20130482, -0.32108926, -0.7320761 , 0.12610864])arr.sort()
arrarray([-2.08464944, -1.5369521 , -1.46048203, -0.7320761 , -0.32108926,
0.12610864, 0.88671682, 1.18515803, 1.79606612, 2.20130482])arr = np.random.randn(5,3)
arrarray([[-0.90307983, -0.54527699, 0.5234602 ],
[ 0.01153178, -0.87114807, -0.07794886],
[-0.34698081, -0.07907388, 0.60341693],
[-0.06539896, -0.34155509, 1.37263374],
[-0.5427262 , -0.09412761, 1.20774627]])arr.sort(1) #对于多维数组,可以通过指定轴方向进行排
arrarray([[-0.90307983, -0.54527699, 0.5234602 ],
[-0.87114807, -0.07794886, 0.01153178],
[-0.34698081, -0.07907388, 0.60341693],
[-0.34155509, -0.06539896, 1.37263374],
[-0.5427262 , -0.09412761, 1.20774627]])
2.4 数组的存取
arr = np.arange(12).reshape(3,4)
arrarray([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])np.savetxt("che1ex1.csv",arr,fmt="%d",delimiter=",")arr = np.loadtxt("che1ex1.csv",delimiter=",")
arrarray([[ 0., 1., 2., 3.],
[ 4., 5., 6., 7.],
[ 8., 9., 10., 11.]])from PIL import Imageim = np.array(Image.open("C:/Users/itcast/Desktop/image/1.jpg"))
print(im.shape,im.dtype)(598, 601, 3) uint8im #通过图中的代码可以看出,图像转换成三维数组后,维度分别为宽度、长度和RGB值。array([[[128, 129, 131],
[ 16, 4, 0],
[246, 208, 61],
...,
[255, 209, 10],
[243, 208, 56],
[ 11, 4, 0]],
[[129, 130, 132],
[ 14, 2, 0],
[246, 208, 61],
...,
[255, 209, 10],
[243, 208, 56],
[ 12, 5, 0]],
[[123, 124, 126],
[ 20, 8, 0],
[246, 208, 61],
...,
[255, 209, 10],
[243, 208, 56],
[ 11, 4, 0]],
...,
[[139, 139, 137],
[251, 243, 197],
[248, 221, 90],
...,
[255, 219, 51],
[248, 217, 90],
[ 8, 5, 0]],
[[120, 120, 118],
[255, 255, 212],
[243, 216, 85],
...,
[255, 219, 51],
[248, 217, 90],
[255, 255, 216]],
[[116, 116, 114],
[255, 255, 212],
[237, 210, 79],
...,
[255, 220, 52],
[249, 218, 91],
[255, 255, 218]]], dtype=uint8)b = [200,200,200] -im
new_im = Image.fromarray(b.astype("uint8"))
new_im.save('C:/Users/itcast/Desktop/image/3.jpg')
联系客服