我们为什么要学习NumPy??
说明:NumPy之于数值计算特别重要的原因之⼀,是因为它可以⾼效 处理⼤数组的数据。
1 NumPy的部分功能如下:
ndarray,⼀个具有⽮量算术运算和复杂⼴播能⼒的快速且节省空间的多维数组。
⽤于对整组数据进⾏快速运算的标准数学函数(⽆需编写循环)。
⽤于读写磁盘数据的⼯具以及⽤于操作内存映射⽂件的⼯具。
线性代数、随机数⽣成以及傅⾥叶变换功能。
⽤于集成由C、C++、Fortran等语⾔编写的代码的A C API。
2 选择NumPy的优势:
- NumPy是在⼀个连续的内存块中存储数据,独⽴于其他Python内置对象。NumPy的C语⾔编写的算法库可以操作内存,⽽不必进⾏类型检查或其它前期⼯作。⽐起Python的内置序列,NumPy数组使⽤的内存更少。
- NumPy可以在整个数组上执⾏复杂的计算,⽽不需要Python的for循环
1 Numpy ndarray多维数组对象
1.1 Creating ndarrays 生成
import numpy as np # 随机生成2*3的序列 data=np.random.randn(2,3) print(data) print(data*10) ''' [[ 0.06546319 -0.11897689 -1.82124962] [ 1.19808965 -0.30471992 -0.1017561 ]] [[ 0.65463189 -1.18976893 -18.21249625] [ 11.9808965 -3.04719919 -1.01756102]] ''' # 查看数组的维度 print(data.shape) # (2, 3) # 查看数组的类型 print(data.dtype) # float64
1.2 array数组
import numpy as np data=[[1,2,3,4],[5,6,7,8]] arr=np.array(data) # print(arr) # print(arr.ndim) # print(arr.shape) ''' [[1 2 3 4] [5 6 7 8]] 2 (2, 4) ''' # 生成都是0的数组 a=np.zeros(10) #相同ones是1 # print(a) # [0. 0. 0. 0. 0. 0. 0. 0. 0. 0.] a=np.zeros((2,2)) # print(a) ''' [[0. 0.] [0. 0.]] ''' # 生成0~9的数组 a=np.arange(10) #左开右闭 print(a) # [0 1 2 3 4 5 6 7 8 9]
1.3 数据类型
1)dtype查看数据的类型
a1=np.array([1,2,3],dtype=np.float64) print(a1.dtype) a2=np.array([1,2,3],dtype=np.int32) print(a2.dtype) # float64 # int32
2)astyoe数据类型的转化
a2=a2.astype(np.float64) print(a2.dtype) print(a2) ''' float64 [1. 2. 3.] '''
1.4 数组的计算
a=np.array([[1,2,3],[4,5,6],[1,2,3]]) print(a) b=a*a print(b) ''' [[1 2 3] [4 5 6] [1 2 3]] [[ 1 4 9] [16 25 36] [ 1 4 9]] ''' print(b*0.5) ''' [[ 0.5 2. 4.5] [ 8. 12.5 18. ] [ 0.5 2. 4.5]] '''
1.5 基础索引与切片
a=np.arange(10) print(a) print(a[5]) ''' [0 1 2 3 4 5 6 7 8 9] 5 ''' print(a[5:8]) # [5 6 7] # 将5-7复制给99 a[5:8]=99 print(a) # [ 0 1 2 3 4 99 99 99 8 9] a1=a[5:8] print(a1) # [99 99 99] a1[1]=123 print(a1) print(a) ''' 从输出结果可以看出复制过来的切片更改了,则原数组也会发生改变 这样Numpy在处理非常大的数组的话,不会引起内存问题 [ 99 123 99] [ 0 1 2 3 4 99 123 99 8 9] ''' b=np.array([[1,2,3],[4,5,6]]) print(b) print(b[1][2]) ''' [[1 2 3] [4 5 6]] 6 '''
1.6 布尔索引
# 这里需要注意的是,字符串型数组要与随机生成的数组保持一致 names=np.array(['Bob','Job','kangkang','Bob']) data=np.random.randn(4,4) #生成一个4*4的随机数 print(names) print(data) ''' ['Bob' 'Job' 'kangkang' 'Bob'] [[-1.23685512 -0.9903232 -0.40647589 -0.09657184] [-0.58888265 -0.9094857 1.26346656 -0.13548616] [-0.78342903 -2.02202405 -0.09077977 -0.86846325] [ 2.2965722 0.18479656 0.0219635 1.16912506]] ''' print(names=='Bob') # [ True False False True] print(data[names=='Bob']) ''' 按照bool的值,取为True的行 [[-1.23685512 -0.9903232 -0.40647589 -0.09657184] [ 2.2965722 0.18479656 0.0219635 1.16912506]] ''' print(~(names=='Bob')) # [False True True False] print(data[~(names=='Bob')]) ''' 按照bool的值,取为原False的行,也就是取反之后的True行 [[-0.58888265 -0.9094857 1.26346656 -0.13548616] [-0.78342903 -2.02202405 -0.09077977 -0.86846325]] ''' print(data[names=='Bob',1]) # [-0.9903232 0.18479656]
1.7 神奇索引
arr=np.empty((8,4)) # empty就是创建一个8*4的内存值,也就是内存有什么创建什么值 for i in range(8): arr[i]=i # print(arr) ''' [[0. 0. 0. 0.] [1. 1. 1. 1.] [2. 2. 2. 2.] [3. 3. 3. 3.] [4. 4. 4. 4.] [5. 5. 5. 5.] [6. 6. 6. 6.] [7. 7. 7. 7.]] ''' # 按照自己想要的顺序取出需要的行的数据 # print(arr[[3,5,2,0]]) ''' [[3. 3. 3. 3.] [5. 5. 5. 5.] [2. 2. 2. 2.] [0. 0. 0. 0.]] ''' # print(arr[[-1,-2]]) ''' 倒着取 [[7. 7. 7. 7.] [6. 6. 6. 6.]] ''' arr=np.arange(32).reshape((8,4)) # print(arr) ''' [[ 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]] ''' print(arr[[1,5,7,2],[0,3,1,2]]) # 最终选择的元素是:(1,0),(5,3),(7,1),(2,2),不管数组多少维,花式索引总是一维的 # [ 4 23 29 10]
1.8 数组的转置和转轴
说明:转置是重塑殴打一种特殊形式,它返回的是源数据的视图(不会进行任何复制操作)
1).T适合一、二维数组的转置
arr=np.arange(15).reshape((3,5)) # print(arr) # print(arr.T) #转置成5*3的数组 ''' [[ 0 1 2 3 4] [ 5 6 7 8 9] [10 11 12 13 14]] [[ 0 5 10] [ 1 6 11] [ 2 7 12] [ 3 8 13] [ 4 9 14]] ''' # 利用该操作计算矩阵的内积 a=np.dot(arr,arr.T) print(a) ''' [[ 30 80 130] [ 80 255 430] [130 430 730]] '''
2).transpose适合高维数组,需要用一个由轴编号的数组才能进行转置
arr=np.arange(24).reshape((2,3,4)) # print(arr) ''' [[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] [[12 13 14 15] [16 17 18 19] [20 21 22 23]]] ''' # 1、原来的轴:2*3*4对应的是(0,1,2) # print(arr.transpose((0,1,2))) ''' [[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] [[12 13 14 15] [16 17 18 19] [20 21 22 23]]] ''' # 2、现在进行轴转置:(1,0,2)对应的3*2*4 # print(arr.transpose((1,0,2))) ''' [[[ 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、现在进行轴转置:(2,1,0)对应的4*3*2 print(arr.transpose((2,1,0))) ''' [[[ 0 12] [ 4 16] [ 8 20]] [[ 1 13] [ 5 17] [ 9 21]] [[ 2 14] [ 6 18] [10 22]] [[ 3 15] [ 7 19] [11 23]]] '''
2 通用函数
说明:就是对数组的元素运算的函数
arr=np.arange(10) # print(arr) # 对arr里面的数组开根号 b=np.sqrt(arr) # print(b) ''' [0 1 2 3 4 5 6 7 8 9] [0. 1. 1.41421356 1.73205081 2. 2.23606798 2.44948974 2.64575131 2.82842712 3. ] ''' x=np.random.rand(8) y=np.random.rand(8) #通过本函数可以返回一个或一组服从“0~1”均匀分布的随机样本值。 # 随机样本取值范围是[0,1),不包括1。 # print(x) ''' [0.30064764 0.73481023 0.10527066 0.50979887 0.95441699 0.13730305 0.80034829 0.12164392] ''' # print(y) ''' [0.11402696 0.27831363 0.87334048 0.85939591 0.55736659 0.45990634 0.72938544 0.65383401] ''' # 计算x和y中元素级别最大的元素 # print(np.maximum(x,y)) ''' [0.30064764 0.73481023 0.87334048 0.85939591 0.95441699 0.45990634 0.80034829 0.65383401] ''' arr=np.random.rand(5)*5 #随机生成的数乘以5倍 #若随机生成的负数求根号,则返回nan print(arr) # [3.61367997 1.46649634 1.52355202 0.90171673 1.23587831] remainder,whole_part=np.modf(arr) # 保留小数部分 print(remainder) # [0.61367997 0.46649634 0.52355202 0.90171673 0.23587831] #保留整数部分 print(whole_part) # [3. 1. 1. 0. 1.] a=whole_part.astype(np.int32) print(a) # [1 1 3 0 3] print(np.sign(a)) # [1 1 1 1 0]
1)一元数组操作:
2)二元数组的操作:
3 利用数组进行数据处理
points=np.arange(-5,5,0.1) #从-5到5,精度0.1,共100个数 xs,ys=np.meshgrid(points,points) # 返回一个由xs, ys构成的坐标矩阵 # print(xs) # print(ys) ''' [[-5. -4.9 -4.8 ... 4.7 4.8 4.9] [-5. -4.9 -4.8 ... 4.7 4.8 4.9] [-5. -4.9 -4.8 ... 4.7 4.8 4.9] ... [-5. -4.9 -4.8 ... 4.7 4.8 4.9] [-5. -4.9 -4.8 ... 4.7 4.8 4.9] [-5. -4.9 -4.8 ... 4.7 4.8 4.9]] ''' z=np.sqrt(xs**2+ys**2) print(z) import matplotlib.pyplot as plt plt.imshow(z,cmap=plt.cm.gray) plt.colorbar() plt.title("Image plot of $\sqrt{x^2 + y^2}$ for a grid of values") plt.show()
3.1 数学和统计方法
1)生成数组,然后做聚类统计
arr=np.arange(6).reshape((2,3)) print(arr) # 1、求数组的平均数 print(arr.mean()) #或 print(np.mean(arr)) # 2.5 # 2、求和 print(arr.sum()) # 15 # 3、利用axis计算该轴上的统计值 print(arr.mean(axis=0)) #axis=0表示按列求平均值,1表示按行 # [1.5 2.5 3.5] print(arr.sum(axis=0)) #axis=0表示按列求和,1表示按行 # [3 5 7]
2)不聚合统计,由中间结果生成新的数组
arr=np.arange(8) print(arr) print(arr.cumsum()) ''' [0 1 2 3 4 5 6 7] [ 0 1 3 6 10 15 21 28] '''
3)多维数组中,累计函数(cumsum)返回的是同样大小的数组,但会根据标记轴部分聚类
arr=np.array([[0,1,2],[3,4,5],[6,7,8]]) print(arr) print(arr.cumsum(axis=0)) #同样0表示对列操作 ''' [[0 1 2] [3 4 5] [6 7 8]] [[ 0 1 2] [ 3 5 7] [ 9 12 15]] '''
4)以下列举出了数组的统计方法
3.2 排序
说明:sort()方法进行就地排序
arr=np.random.randn(6)*5 # print(arr) arr.sort() # print(arr) ''' [ -2.98478748 -2.67058322 -5.51832824 -12.23731593 -3.81424203 1.33803487] [-12.23731593 -5.51832824 -3.81424203 -2.98478748 -2.67058322 1.33803487] ''' # 多维数组可以在任何一个轴上排序,同理0表示列,1表示行 a=np.random.randn(3,3) print(a) a.sort(1) print(a) ''' [[ 0.69739385 -0.29640634 -0.54231462] [-1.60388036 0.65765065 0.11135261] [ 0.06904195 2.4380053 0.42962269]] [[-0.54231462 -0.29640634 0.69739385] [-1.60388036 0.11135261 0.65765065] [ 0.06904195 0.42962269 2.4380053 ]] '''
3.3 唯一化以及集合逻辑
说明:使用np.unique()用于找出数组中的唯一值并返回已排序的结果。也就是去除数组里面的重复值。
names=np.array(['Bob','Job','WIll','Bob']) print(np.unique(names)) # ['Bob' 'Job' 'WIll'] arr=np.array([1,2,7,4,2,1,3,4,6]) print(np.unique(arr)) # [1 2 3 4 6 7]
4 用于数组的文件输入输出
说明:Numpy能够读写磁盘上的文本数据或二进制数据。通过np.save和np.load读写磁盘数组数据的两个主要函数。默认情况下以未压缩的原始二进制格式保存在扩展名为.npy的文件中。不过用户一般选择pandas或其他工具加载文本或者表格数据。
5 线性代数
说明:线性代数包含矩阵乘法、矩阵分解、行列式以及其他方阵。Numpy提供了一个用于矩阵乘法的dot函数
一些常用的线性代数函数
x=np.array([[1,2,3],[4,5,6]]) y=np.array([[1,2],[2,3],[3,4]]) # print(x) ''' [[1 2 3] [4 5 6]] ''' # print(y) ''' [[1 2] [2 3] [3 4]] ''' # 做xy 的内积 z=x.dot(y) #等级 z=np.dot(x,y) # print(z) ''' [[14 20] [32 47]] ''' # 一个二维数组跟一个一维数组矩阵点积之后得到一维数组 c=np.ones(3) print(np.dot(x,c)) # [ 6. 15.]
6 伪随机数生成
以下是numpy.random中的部分函数
使用normal得到一个标准正态分布的4x4样本数组,这样的优势就是我们可以一次性生成大量样本值。
sample=np.random.normal(size=(4,4)) print(sample) ''' [[ 2.5075111 -0.2278162 2.27533051 0.40876153] [-0.64022587 1.15964118 -1.59200453 1.08199528] [-0.56770742 -0.43835872 -0.06797861 -0.19994357] [ 0.9548936 -1.4356151 -1.46462771 1.29446398]] '''