12.Python科学计算和数据分析的常用扩展库:Numpy

1、Numpy介绍

  • Numpy (Numerical Python) 是python中的一个基础工具包,用以进行科学计算及数据分析,
  • Numpy中单一数据类型的多维数组以ndarray的形式存储,可进行快速矢量算术运算,
  • Numpy还可用于磁盘数据的读写以及内存映射文件的操作,实现数据的快速读写与输出,
  • Numpy也是数据分析必不可少的工具,可以进行数据清洗、数据转换等矢量化数组运算。

2、Numpy安装

# python -m pip会使用您指定为python的Python解释器来执行pip
python -m pip install numpy

3、创建ndarray数组

ndarray:数组中的所有对象必须是相同类型的,创建ndarray数组可以使用array函数传入python序列对象实现

3.1、一维数组

import numpy as np

# 创建一维数组
a = [1, 2, 3, 4, 5]
arr1 = np.array(a)
print("创建一维数组:\n", arr1)

3.2、多维数组

# 创建多维数组
b = [[1, 2, 3], [4, 5, 6]]
arr2 = np.array(b)
print("创建多维数组:\n", arr2)

3.3、shape函数

shape函数是查看每个数组各维度的大小,返回值是一个元组对象,数组是一维数组,返回值是(n,),

n表示数组的长度,数组是二维数组,返回值是(n1,n2) ,n1表示行数,n2表示列数,

对于三维数组就是包含多少个二维数组,后两个数字表示二维数组的行与列 返回值是(n1,n2,n3), n1表示几个二维数组,n2表示二维数组的行,n3表示二维数组列

# shape
print("arr1 shape: ", arr1.shape)
print("arr2 shape: ", arr2.shape)

3.4、reshape函数

reshape函数可以更改数组的结构,原数组的shape仍然保持不变,原数组与新数组是共享同一数据储存内存区域,

所以对其中一个数组元素修改,都会同时引起另一个数组内容的改变

# reshape
arr2_reshape = arr2.reshape(3,2)
print("arr2 reshape前:\n",arr2)
print("arr2 reshape后: \n",arr2_reshape)

3.5、特殊数组

# 特殊数组
print("创建都是0的一维数组:\n",np.zeros(3))
print("创建都是0的多维数组:\n",np.zeros((2,3)))
print("创建都是1的多维数组:\n",np.ones((2,3)))
print("创建没有具体数值的多维数组:\n",np.empty((2,2,3)))
print("创建指定序列数组:\n",np.arange(10))
print("创建单位数组:\n",np.eye(3,3))

4、数组的数据类型

  • 数组的数据类型保存在dtype对象中,可使用dtype函数查看

  • 创建ndarray时,dtype作为一个参数可以将一块内存解释为特定的数据类型

  • dtype的命名方式:数据类型+元素位长

  • 对已经创建好的ndarray,可以使用astype函数转换其数据类型

  • Numpy支持的数据类型(如下):

    类型名称
    int8、unit8有符号和无符号的8位整型(1个字节)
    int16、unit16有符号和无符号的16位整型(2个字节)
    int32、unit32有符号和无符号的32位整型(4个字节)
    int64、unit64有符号和无符号的64位整型(8个字节)
    float16半精度浮点数
    float32标准的单精度浮点数
    float64标准的双精度浮点数
    complex64、complex128、complex256用两个32位、64位、128位浮点数表示的复数
    bool布尔类型,True和False
    objectPython对象类型
    string_固定长度的字符串类型(每个字符1个字节)
    unicode_固定长度的unicode类型

5、数组的索引和切片

5.1、一维数组

一维numpy数组的索引和切片方法基本与python列表一致,索引:通过对数组使用中括号,中括号中填入元素的位置整数来获取目标元素。切片:通过在中括号中填入元素位置的区间来确定元素片段

import numpy as np
# 一维数组索引
arr_1d = np.arange(10)
print("arr_1d: ",arr_1d)
print("arr_1d[8]: ",arr_1d[8])
print("arr_1d[5:9]: ",arr_1d[5:9])

# 修改索引5到8的值
arr_1d[5:9] = 10
print("修改索引5到8值:",arr_1d)

5.2、二维数组

对于二维数组,每个索引位置上对应的元素不再是标量而是一维数组

# 二维数组索引
arr_2d = np.array([[1,2,3],[4,5,6]])
print("arr_2d[1]: ",arr_2d[1])
print("arr_2d[1][1]: ",arr_2d[1][1])
print("arr_2d[1,1]: ",arr_2d[1,1])

arr_2d二维数组结构:

索引01
对应数据[1,2,3][4,5,6]

5.3、多维数组

对于多维数组的索引,返回对象为降低维度之后的ndarray

# 多维数组索引
arr_3d = np.arange(16).reshape(2,2,4) #见arr_3d三维数组结构
print("创建三维数组:\n",arr_3d)
print("arr_3d[0]: ",arr_3d[0]) # 见arr_3d三维数组结构 找对应0的行数据
print("arr_3d[0,1]: ",arr_3d[0,1]) # 见arr_3d三维数组结构 先对应0的行数据,在找对应1的列数据
#修改元素值
arr_3d[0,1]=10
print("修改元素值: ",arr_3d)

arr_3d三维数组结构:

01
0[0,1,2,3][4,5,6,7]
1[8,9,10,11][12,13,14,15]

5.4、切片索引

ndarray 的切片索引只需将数组中的每一行每一列都分别看作一个列表,参考列表切片索引的方法,最后返回数组类型的数据

#切片索引
arr = np.arange(25).reshape(5,5)
print("创建二维数组:",arr)

print("取出索引为2:3对应的值是7,8:",arr[1,2:4])
print("取出行索引1:2,列索引2:3的二维数组:",arr[1:3,2:4])
print("取出第三列之后的二维数组:",arr[:,2:]) # 2: 表示选取索引为2之后的所有列
print("行方向隔行取数,列方向取第三列之后的二维数组:",arr[::2,2:]) # ::2 表示取出所有行数据,2表示步长

5.5、布尔型索引

布尔型数据作为数组的索引时,会根据布尔数组的True或者False值筛选对应轴上的数据

布尔型索引不仅可以设置正向条件,还可以设置反向条件:

  • != 表示不等于
  • 表示对于条件的否定
  • logical_not函数用于设置反向条件
# 使用布尔型索引选取arr2数据
'''
arr2: [[ 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]]
'''
arr2 = np.arange(25).reshape(5,5)
# 设置一个x作为筛选条件
x = np.array([0,1,2,3,1])
print("判断x是否等于1:",x==1)

print("索引x=1时对应arr2中的数据:",arr2[x==1])
# 布尔型数组的长度必须跟被索引的轴长度一致
print("布尔型索引与切片结合使用:",arr2[x==1,3:])

# 布尔型反向索引
print(arr2[x != 1])
print(arr2[~(x == 1)])
print(arr2[np.logical_not(x==1)])

# 多条件筛选
print("多条件筛选: ",arr2[(x==1)|(x==0)])

# 布尔型筛选索引修改值
arr2_copy = arr2.copy()
arr2[arr2>15]=20
print("修改之前:",arr2_copy)
print("修改之后:",arr2)

6、函数调用

6.1、统计运算

Numpy提供一些数学函数,可以直接对整个数组或者某个轴向上的数据进行数学统计计算。比如:求和公式、求平均值、方差、标准差、最大值、最小值、累计和、累计积、最大最小元素的索引等。

import numpy as np

#统计运算
arr = np.arange(25).reshape(5,5)
print("对所有元素求和:",arr.sum())
print("求所有元素的均值:",arr.mean())
print("求所有元素的标准差:",arr.std())
print("求所有元素的方差:",arr.var())
print("求元素中的最大值:",arr.max())
print("求元素中的最小值:",arr.min())
print("求所有元素的累计和:",arr.cumsum())
print("求所有元素的累计积:",arr.cumprod())
print("求最小元素的索引:",arr.argmin())
print("求最大元素的索引:",arr.argmax())

6.2、矩阵运算

Numpy中的二维数组可以被看作是矩阵,矩阵运算对应的是元素量级,Numpy中矩阵运算的相关函数:矩阵的转置函数(.T)、矩阵的点乘(.dot)、矩阵的迹(trace)等

#矩阵的转置:转置是将矩阵中的元素行列对调,得到一个新的矩阵,Numpy中使用 arr.T函数返回矩阵的转置矩阵
arr1 = np.arange(9).reshape(3,3)
print("arr1: ",arr1)
print("转置矩阵: ",arr1.T)

#矩阵的逆:逆矩阵使用np.linalg.inv函数获得
arr2 = np.arange(1,10).reshape(3,3)
print("arr2:",arr2)
print("逆矩阵:",np.linalg.inv(arr2))

#矩阵的加减法:两矩阵相加减,直接使用加减号即可,但要保证两矩阵的结构相同
arr3 = np.arange(9).reshape(3,3)
print("矩阵相加:",arr1+arr3)
print("矩阵相减:",arr1-arr3)

'''
矩阵的乘法:将第一个矩阵的第m行元素与第二矩阵的第n列元素对应相乘并求和,
得到结果矩阵中(m,n)对应的元素.(对应第一矩阵使用.dot函数,传入第二个矩阵的转置矩阵作为函数参数)

矩阵的点乘:是两个结构相同的矩阵对应元素相乘
'''
print("矩阵arr1点乘arr3:",arr1*arr3)
print("arr1乘arr3:",arr1.dot(arr3.T))

#矩阵的迹:在线性代数中,矩阵的迹为矩阵主对角线上各元素的总和,Numpy使用np.trace函数获取矩阵的迹
print("arr1的迹:",np.trace(arr1))

'''
特征值、特征向量 :
如果一个矩阵A是n阶方阵,存在常量m和非零n维向量x,使得Ax=mx,那么称m是矩阵A的一个特征值,向量x为特征值m对应的特征向量
'''
m,x = np.linalg.eig(arr2)
print("特征值:",m)
print("特征向量:",x)

6.3、数据处理

6.3.1、排序

Numpy中的sort函数可对数组做排序处理,当函数中的参数axis=0时,每一列上的元素按照行的方向排序,axis=1时每一行上的元素按照列的方向排序

# 排序
arr4 = np.array([[3,1,2],[4,3,5],[7,5,1]])
print("排序前:",arr4)
arr4_sort = np.sort(arr4,axis=1)
print("排序后:",arr4)
print("按行排序后:",arr4_sort)
print("-------------------------------------")
arr5 = np.array([[3,1,2],[4,3,5],[7,5,1]])
print("排序前:",arr5)
arr5_sort = np.sort(arr5,axis=0)
print("排序后:",arr5)
print("按列排序后:",arr5_sort)

6.3.2、去重

Numpy中提供列对一维数组去重的unique函数,该函数的返回值为数组中按照从小到大的顺序排序的非重复元素的元组或列表

# 去重
arr6 = np.array([1,3,6,4,2,2,1,0])
print("去重后的元素: ",np.unique(arr6))

7、文件读写

Numpy提供了文件读取和写入函数loadtxt和savetxt

7.1、写入文件

arr7 = np.arange(9).reshape(3,3)
np.savetxt("arr7.txt",arr7)

7.2、读取文件

a7 = np.loadtxt("arr7.txt")
print("文件读取内容:",a7)