Numpy 🔢
NumPy 是 的简称,是高性能计算和数据分析的基础包。
包含了多维数组以及多维数组的操作。
Anaconda中已经集成了NumPy,可以直接使用。如果想要自行安装的话,可以使用流行的Python 包安装程序 pip 来安装 NumPy。
在 CMD 或命令行中执行:
pip install numpy
Numpy 的核心是 ,这个对象封装了同质数据类型的n维数组。
它的主要优点就是 : 使你能够在整个数据块上快速高效地进行数学运算。
Numpy是一个第三方库,约定俗成的导入方式如下:
pythonimport numpy as nppython#查看numpy版本 np.__version__ # '1.26.4'
一、数组的创建
np.array可以把 list,tuple 或者其他的序列模式的数据转创建为np.array默认创建一个新的 ndarray。
np.array([1,2,3]) # array([1, 2, 3])#创建数组
arr1 = np.array([3, 5, 0.7, -4, 6.2, 0])
arr1 # array([ 3. , 5. , 0.7, -4. , 6.2, 0. ])创建 array 数组时numpy 内部会 ,方式是向上兼容
比如说只有 int 和 float 时 ,那么全部变成 float
要是有 int , float 和 str 时 ,全部变成 str
二、数组的算术运算
x = np.array([1,2,3])
y = np.array([1,4,6])x # array([1, 2, 3])y # array([1, 4, 6])# 对应元素相加
x+y # array([2, 6, 9])# 对应元素相减
x-y # array([ 0, -2, -3])# 对应元素相乘
x*y # array([ 1, 8, 18])# 对应元素相除
x/y # array([1. , 0.5, 0.5])x == y # array([ True, False, False])#空值不等于任何值
np.nan != np.nan # True这里需要注意的是,数组x 和 数组y 的元素个数是相同的(两者均是元素个数为3 的一维数组)
当两者元素个数相同时,可以对各个元素进行算术运算。
如果元素个数不同,则会报错,所以保持元素个数一致非常重要。
此外,Numpy 数组不仅可以进行对应元素的算术运算,
还可以和单一的数值(标量)组合起来进行运算( 这个功能也被称为广播,后面会详细介绍 ),
比如:
x = np.array([1,2,4])x/2 # array([0.5, 1. , 2. ])x + 5 # array([6, 7, 9])三、创建N维数组
Numpy不仅可以生成一维数组,也可以生成多维数组。
比如,可以生成如下的二维数组:
#创建二维数组
arr2 = np.array([[5,6,7,8,9],[4,3,2,1,0]])
arr2
# array([[5, 6, 7, 8, 9],
# [4, 3, 2, 1, 0]])# 查看数组的形状(返回一个包含数组维度的元祖)
arr2.shape # (2, 5)
# ps : 一维两个元素-->代表两行,二维五个元素-->代表五列# 查看数组的元素类型
arr2.dtype # dtype('int32')# 查看数组的维数
arr2.ndim # 2
# ps: ndim 对应英文 : ndarray dimension# 查看数组的元素个数
arr2.size # 10二维数组也可以进行算术运算:
A = np.array([[1,2],[3,4]])
B = np.array([[5,6],[7,8]])A
# array([[1, 2],
# [3, 4]])B
# array([[5, 6],
# [7, 8]])# 对应元素相加
A + B
# array([[ 6, 8],
# [10, 12]])# 对应元素相减
A - B
# array([[-4, -4],
# [-4, -4]])# 对应元素与标量做运算
A/2
# array([[0.5, 1. ],
# [1.5, 2. ]])和一维数组一样,二维数组的算术运算也可以在形状相同的两个数组间以对应元素的方式进行。
并且,也可以通过标量对二维数组进行算术运算。这也是基于广播的功能。
【补充】二维数组等价于矩阵( Python 中有专门的矩阵函数 ),
在大多数情况下二维数组都可以当做矩阵来用,但是在矩阵运算的时候,两者就有些微差别了:
# array 对应元素相乘
A * B
# array([[ 5, 12],
# [21, 32]])# numpy 创建 matrix 矩阵
np.matrix([[1,2],[3,4]])
# matrix([[1, 2],
# [3, 4]])C = np.matrix([[1,2],[3,4]])
D = np.matrix([[5,6],[7,8]])C
# matrix([[1, 2],
# [3, 4]])D
# matrix([[5, 6],
# [7, 8]])# 矩阵乘法
C * D
# matrix([[19, 22],
# [43, 50]])
"""
ps: [
[ (1*5 + 2*7) , (1*6 + 2*8) ],
[ (3*5 + 4*7) , (3*6 + 4*8) ] ]
"""创建三维数组:
arr3 = np.array(range(5),ndmin=3)
# ps : ndmin 其实也是指定维度,翻译过来多了个num而已
# ndarray dimension num : ndmin
arr3
# array([[[0, 1, 2, 3, 4]]])arr3.shape
# (1, 1, 5)
# ps: 一维有一个元素,二维有一个元素,三维有五个元素arr3.ndim
# 3【注意】:NumPy 要求数组必须包含同一类型的数据。
如果类型不匹配,NumPy 将会自行转换。
np.array([1,2,3,"4"])
# array(['1', '2', '3', '4'], dtype='<U11')np.array([1.2,3,4])
# array([1.2, 3. , 4. ])np.array([1.2,4,"5"])
# array(['1.2', '4', '5'], dtype='<U32')四、常用数组
- 全 0 数组
np.zeros(5)
# array([0., 0., 0., 0., 0.])- 全 1 数组
np.ones(6)
# array([1., 1., 1., 1., 1., 1.])- 随机数组 ( 常用 )
# 生成指定形状的[0,1)的随机数组
np.random.rand(3)
# array([0.7149227 , 0.98581753, 0.81324916])np.random.rand(2,3)
# array([[0.60382813, 0.56889898, 0.97365216],
# [0.80949954, 0.18880049, 0.98146314]])# 生成指定形状、指定范围的随机整型数组
# 示例 : 范围 1 - 9 , 形状 (3,6)
np.random.randint(1, 10, (3, 6))
# array([[3, 5, 5, 9, 5, 7],
# [8, 2, 5, 9, 3, 1],
# [4, 9, 4, 4, 8, 7]])# 生成指定形状的满足标准正态分布的随机数组
# 正态分布 : normal distribution
np.random.randn(4,2,3)
"""
array([[[-0.2065384 , 0.73334483, -0.5518795 ],
[-1.20666084, -0.37861971, -0.66011676]],
[[ 2.20020631, 0.7932815 , -0.33847726],
[-1.06936983, 0.12741519, 1.2327438 ]],
[[-1.2937449 , 0.58172602, -0.04288274],
[ 2.1401154 , 1.22998523, -1.06962492]],
[[-0.83617812, -0.40632949, 0.65289765],
[ 0.44221594, 0.35359116, 0.33528315]]])
"""# 设置随机数种子
# ps:设置随机数种子限制在同一个cell里,不同cell不起作用
# 设置之后多次运行结果不变
np.random.seed(666)
a = np.random.randn(2, 3)
a
# array([[ 0.82418808, 0.479966 , 1.17346801],
# [ 0.90904807, -0.57172145, -0.10949727]])- 线性序列
np.arange(2,11,3)
# ps : np.arange(起点, 终点(不包含), 步长)
# array([2, 5, 8])np.linspace(1,5,num=50,endpoint=True)
# ps: np.linspace(起点,终点,(num=)在这个区间等距生成多少个数,(endpoint=)包不包括终点)
"""
array([1. , 1.08163265, 1.16326531, 1.24489796, 1.32653061,
1.40816327, 1.48979592, 1.57142857, 1.65306122, 1.73469388,
1.81632653, 1.89795918, 1.97959184, 2.06122449, 2.14285714,
2.2244898 , 2.30612245, 2.3877551 , 2.46938776, 2.55102041,
2.63265306, 2.71428571, 2.79591837, 2.87755102, 2.95918367,
3.04081633, 3.12244898, 3.20408163, 3.28571429, 3.36734694,
3.44897959, 3.53061224, 3.6122449 , 3.69387755, 3.7755102 ,
3.85714286, 3.93877551, 4.02040816, 4.10204082, 4.18367347,
4.26530612, 4.34693878, 4.42857143, 4.51020408, 4.59183673,
4.67346939, 4.75510204, 4.83673469, 4.91836735, 5. ])
"""五、数组的形状变换
m = np.random.randint(1, 10,(3, 4))
m
# ps : np.random.randint(起点, 终点(不包括),数组形状)
"""
array([[5, 2, 8, 5],
[5, 2, 8, 6],
[3, 3, 3, 7]])
"""m.shape
# (3,4)p = m.reshape(2,6) #不改变原数组,生成一个新对象
p
"""
array([[5, 2, 8, 5, 5, 2],
[8, 6, 3, 3, 3, 7]])
"""m #不改变原数组
"""
array([[5, 2, 8, 5],
[5, 2, 8, 6],
[3, 3, 3, 7]])
"""m.reshape(1,-1) #把原数组改为一行,-1是用来占位
# array([[5, 2, 8, 5, 5, 2, 8, 6, 3, 3, 3, 7]])m.reshape(1,-1).shape
# (1, 12)m.reshape(-1,1) #把原数组变为一列,-1也是用来占位
"""
array([[5],
[2],
[8],
[5],
[5],
[2],
[8],
[6],
[3],
[3],
[3],
[7]])
"""m.reshape(-1,1).shape
# (12, 1)m.flatten() #与.reshape(1,-1)作用相似,不同之处在于flatten把数组降维成一维
# array([5, 2, 8, 5, 5, 2, 8, 6, 3, 3, 3, 7])m.ravel() #与 flatten作用相似
# array([5, 2, 8, 5, 5, 2, 8, 6, 3, 3, 3, 7])n = np.random.rand(2,4) # 创建一个随机的两行四列的,用于下面转置
n
"""
array([[0.35932938, 0.42014544, 0.2026436 , 0.63279787],
[0.18935861, 0.1308497 , 0.75765845, 0.34158167]])
"""n.T #转置
"""
array([[0.35932938, 0.18935861],
[0.42014544, 0.1308497 ],
[0.2026436 , 0.75765845],
[0.63279787, 0.34158167]])
"""六、数组的索引和切片
a = np.random.randint(1, 10,(3, 4)) # 范围 [1,10)的 3行4列的 整数的 数组
a
"""
array([[1, 1, 5, 7],
[8, 9, 3, 9],
[2, 1, 9, 3]])
"""a[0] # 索引取值
# array([1, 1, 5, 7])a[1:3] # 切片取值
"""
array([[8, 9, 3, 9],
[2, 1, 9, 3]])
"""a[0][2] # 索引链式取值 (先行索引,后列索引)
# 5a[0,2] #等价于a[0][2]
# ps : a[行索引,列索引]
# 5a>5
"""
array([[False, False, False, True],
[ True, True, False, True],
[False, False, True, False]])
"""a[a>5] # 布尔索引取值
# ps:把布尔索引传进中括号,会取为True的值
# array([7, 8, 9, 9, 9])a[:2]
# ps : a[行索引,列索引] / a[行切片,列切片]
# a[:2] : 行切片为(:2) , 即对行取 0 - 1 行 , 列全部取(列不做要求)
"""
array([[1, 1, 5, 7],
[8, 9, 3, 9]])
"""a[:2,1:3] # a[行切片,列切片]
# ps: 对行取 0-1 行 , 对列取 1-2列
"""
array([[1, 5],
[9, 3]])
"""七、广播功能
术语
广播是指 NumPy 在 的能力。广播可以简单理解为用于不同大小数组的计算(加、减、乘、除等)的一组规则。
如果数组的形状相同,则对相应元素逐个计算:
pythona = np.array([0,1,2]) b = np.array([5,5,5]) a+b # array([5, 6, 7])
- 如果数组的形状不同,则需要用到广播机制

np.arange(3)
# array([0, 1, 2])# 图示第一种情况
np.arange(3)+5
# array([5, 6, 7])# 图示第二种情况
np.ones((3,3)) + np.arange(3)
"""
array([[1., 2., 3.],
[1., 2., 3.],
[1., 2., 3.]])
"""# 图示第三种情况
np.arange(3).reshape((3,1)) + np.arange(3)
"""
array([[0, 1, 2],
[1, 2, 3],
[2, 3, 4]])
"""Numpy的广播遵循一组严格的规则:
- 规则1:如果两个数组的维度数不相同,那么小维度数组的形状将会在最左边补1
- 规则2:如果两个数组的形状在任何一个维度上都不匹配,那么数组的形状会沿着维度为1的维度扩展以匹配另外一个数组的形状
- 规则3:如果两个数组的形状在任何一个维度上都不匹配并且没有任何一个维度为1,则会引发异常无法广播
