写在前面:python小白,关于numpy包的学习总结希望大家多多支持,欢迎评论交流
Numpy是一个高性能科学计算与数据分析的Python软件包,也是很多其他Python包(如pandas、matplotlib等)的依赖。目前,Numpy是开源项目,在众多开发者的支持下,它的功能在不断扩展。详细介绍可参考Numpy官网——https://numpy.org/
Numpy的核心是ndarray(N-dimensional array)对象,即数组对象,用于表达多维结构的数据,由相同类型的元素所构成。
数组对象的主要属性:
属性 | 解释 |
---|---|
ndim | 数组维数 |
shape | 数组形状(数组的维度集每一维度长度) |
size | 数组长度(组成数组的元素个数) |
dtype | 数组元素类型 |
一个数组的长度是固定的,但是数组形状和维数是可变的。
例:
import numpy as np
L = [1, 3, 2, 6]
a = np.array(L)
print(a.ndim) # 输出 1 一维数组
print(a.shape) # 输出 (4,)长度为4的一维数组
print(a.size) # 输出 4 长度为4
print(a.dtype) # 输出 int32 有符号32位的整数
数组中的元素可以是数字型,也可以是其他类型(如布尔型、字符串型、python对象型等)。
利用数组对象的astype(‘dtype’)方法可以转换数组元素为新的类型,转换类型后的数组赋值给另一个新的数组,新数组除了数据类型不一样,维数、长度都与原数组一致。
例:
b = a.astype('float')
print(b.dtype) # 输出 float64
如上面示例,Numpy中的array函数用于将序列数据(列表、元组、数组或其他序列类型)转换为数组对象。并且可以进行序列的嵌套从而创建不太维度的数组。
dtype属性用于在创建时指定数组的元素类型。
例:
L = [[1, 2, 3, 4]]
a = np.array(L) # 创建一个1*4的二维数组(类型缺省)
L = [[1], [2], [3], [4]]
a = np.array(L, dtype="f") # 创建一个4*1的二维数组(类型为float32)
创建结构数组
详细参考
数组的元素也可以是一个结构(对象),即可以包含多个不同类型的值。元素类型为结构的数组称为结构数组。结构数组类似于数据库中的表格,数组中的一个元素可认为是表格中的一个记录。
结构数组的数据类型是一个字典,字典有两个键:“names” 和 “formats”,键值分别为结构中每个值的名称序列(类似于字段名)和值的类型序列(类似于字段类型);
结构元素用元组表示,多个元组组成的列表则构成一个一维的结构数组(类似于多个字段的多个记录值
例(根据城市列表创建结构数组):
c = {"names": ["city_name", "lon", "lat", "pop"], "formats": ["S32", "f", "f", "i"]} # 定义一个字典表示结构数组的数据类型
c_type = np.dtype(c) # 字典转换为数组数据类型对象(可省略此步直接用字典赋予dtype)
cities = [("beijing", 116.37, 39.92, 21707000),
("shanghai", 121.53, 31.26, 24183300),
("guangzhou", 113.25, 23.13, 14498400)] # 创建结构数组的值
a = np.array(cities, dtype=c_type)
print(a)
'''输出:
[(b'beijing', 116.37, 39.92, 21707000)
(b'shanghai', 121.53, 31.26, 24183300)
(b'guangzhou', 113.25, 23.13, 14498400)]'''
print(a["pop"])
'''输出:[21707000 24183300 14498400]'''
print(a[0]["city_name"])
'''输出:
b'beijing' ''' # 前面的 b 表示bytes字节类型
Numpy中的arange()函数和linspace()函数用于产生由规则数据组成的一维数组,两者都是按照等间隔产生数据,前者产生为整数,后者产生为浮点数。
a = np.arange(1, 10, 1) # 前两个参数分别为设置开始值和终值,第三个参数为设置产生间隔
print(a) # 输出:[1 2 3 4 5 6 7 8 9]
a = np.linspace(1, 10, 5, endpoint=True) # 前面个分别为设置开始值和终值,第三个参数为设置产生元素个数,endpoint参数设置是否包含终值
print(a) # 输出:[ 1. 3.25 5.5 7.75 10. ]
创建由随机数(包括指定分布的随机数)组成的数组可利用numpy.random模块中的相关函数。下面以该模块中的主要函数做个示例:
a1 = np.random.rand(5) # 产生5个0~1之间的随机数组成的一维数组
print(a1) # 输出:[0.16497572 0.3738955 0.35744013 0.12073388 0.32096764]
a1 = np.random.rand(5, 5) # 产生5*5个0~1之间的随机数组成的二维数组
a2 = np.random.randn(5) # 产生正态分布随机数(浮点数)组成的数组
print(a2) # 输出:[ 0.39700688 0.3065918 -0.22865804 0.41525148 0.65744546]
a3 = np.random.randint(low=1, high=10, size=5) # 产生最小值为low,最大值为high,长度为size的随机数组成的一维数组
print(a3) # 输出:[3 2 6 6 3]
a4 = np.random.normal(loc=0, scale=1, size=5) # 产生产生均值为0,标准偏差为scale,长度为size的正态(高斯)分布的样本数组
print(a4) # 输出:[ 1.00790278 0.57669319 -1.17706228 -0.51110038 1.29667758]
a4 = np.random.permutation([2, 8, 3, 4, 1]) # 对一个序列进行随机排序,返回数组。若参数x为一个整数则利用range(x)产生序列
print(a4) # 输出:[3 1 2 4 8]
Numpy提供以下函数用于创建特定数组:
(1)ones()函数,根据指定形状和dtype创建一个全是1的数组
a = np.ones((3, 3), dtype='int')
'''输出:
[[1 1 1]
[1 1 1]
[1 1 1]]'''
ones_like()函数,以另一个数组为参数(包括形状和dtype)创建一个全是1的数组
a = np.random.rand(3, 3)
b = np.ones_like(a)
print(b)
'''输出:
[[1. 1. 1.]
[1. 1. 1.]
[1. 1. 1.]]'''
(2)zeros()函数,根据指定形状和dtype创建一个全是0的数组
b = np.zeros((3, 3))
print(b)
'''输出:
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]'''
zeros_like()函数,以另一个数组为参数(包括形状和dtype)创建一个全是0的数组
a = np.random.rand(3, 3)
b = np.zeros_like(a)
print(b)
'''输出:
[[0. 0. 0.]
[0. 0. 0.]
[0. 0. 0.]]'''
【→→(1)和(2)中的函数生成的数组的默认类型都是float64。】
(3)empty()函数,根据指定形状和dtype创建一个元素全为空的数组
b = np.empty((3, 3))
empty_like()函数,以另一个数组为参数(包括形状和dtype)创建一个元素全为空的数组
a = np.random.rand(3, 3)
b = np.empty_like(a)
空数组的输出如下形式:
[[0.00000000e+000 0.00000000e+000 0.00000000e+000]
[0.00000000e+000 0.00000000e+000 2.52961611e-321]
[1.69115935e-306 8.91238232e-313 1.44635573e-307]]
(4)eye(N, M=None)函数,创建一个二维的单位数组(对角线为1,其余全为0)
b = np.eye(N=3, M=3) # N参数为行数,M参数为列数
print(b)
'''输出:
[[1. 0. 0.]
[0. 1. 0.]
[0. 0. 1.]]'''
通过设置数组对象的shape属性值可以改变数组形状,如果shape属性中某一维的长度不确定,可以-1表示,最终的长度会根据其他维的长度自动计算。
例:
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]) # 定义一个3*4二维数组
print(a.shape) # 输出:(3, 4)
a.shape = 4, 3 # 将数组改为4*3二维数组
print(a.shape) # 输出:(4, 3)
a.shape = 2, 2, -1 # 将数组改为前两维长度为2的三维数组(第三维长度根据总长度自动计算为3)
print(a.shape) # 输出:(2, 2, 3)
(1) reshape()方法,改变数组为新的形状,如下:
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(a.shape) # 输出:(3, 4)
a_reshape = a.reshape(1, 3, -1)
print(a_reshape.shape) # 输出:(1, 3, 4)
print(a_reshape)
'''输出:
[[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]]'''
(2) transpose()方法,数组转置(类似矩阵的转置),如下:
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(a.shape) # 输出:(3, 4)
print(a)
'''输出:
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]'''
a_transpose = a.transpose()
print(a_transpose.shape) # 输出:(4,3)
print(a_transpose)
'''输出:
[[ 1 5 9]
[ 2 6 10]
[ 3 7 11]
[ 4 8 12]]'''
如果是多维数组,还可以通过维的顺序列表定义转置的方向,
如transpose(1, 0, 2),表示第0维变为第1维,第1维变为第0维,第2维不变。
如下(将上面的二维数组a_transpose第0维与第1维交换):
a_transpose1 = a_transpose.transpose(1, 0)
print(a_transpose1)
'''输出:
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]'''
(3) flatten()方法,用于将数组展平(变为一维数组),如下:
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
a_flatten = a.flatten()
print(a_flatten)
'''输出:
[ 1 2 3 4 5 6 7 8 9 10 11 12]'''
(4) squeeze()方法,用于去除数组中长度为1的轴。如果想要指定轴(axis=i),则指去除指定的长度为1的轴(如长度不为1,则会保错)
a = np.array([[[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]]]) # 三维数组,第0维长度为1
a_squeeze = a.squeeze()
print(a_squeeze)
'''输出:
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]'''
数组的索引和切片用于返回数组中某个元素或某个范围的元素,也可以用于对数组中某个元素或某个元素范围进行重新赋值。
数组的索引是通过在方括号内指定每一维的索引值来操作,如下:
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(a[1, 2]) # 输出第二行第三列的元素:7
print(a[1][2]) # 输出第二行第三列的元素:7
数组的切片是通过在方括号定义每一维的范围来实现,每一维的用i:j:k的形式表示,i、j、k分别表示开始索引值、结束索引值(但不包括该位置元素)、步长。切片和索引往往都是结合使用,即切片后通过索引返回数组的元素:
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(a[0:2]) # 输出第一行到第三行(不包括第三行)的所有元素
print(a[0:2, 0:2]) # 输出第一行、列到第三行、列(不包括第三行、列)的所有元素
注:切片操作返回的是引用的数据,对切片数据的修改会反映到原始数据中(同样原始数据的修改也会影响到切片数据),如下:
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(a[0, 0]) # 输出:1
b = a[0, 0:2]
print(b) # 输出:[1 2]
b[0] = 0
print(a[0, 0]) # 输出:0
(数组的连接是把多个数组连接到一起产生一个新的数组)
(1) vstack()函数 或 row_stack()函数,用于垂直方向连接
a = np.zeros((3, 3))
b = np.ones((3, 3))
print(np.vstack((a, b)).shape) # 输出:(6, 3)
(2) hstack()函数 或 column_stack()函数,用于水平方向连接
a = np.zeros((3, 3))
b = np.ones((3, 3))
print(np.hstack((a, b)).shape) # 输出:(3, 6)
注:column_stack()函数与hstack()函数,在对一维数组的连接操作有一定的区别,column_stack()函数得到一个二维数据,hstack()函数还是一维数组,如下:
a = np.zeros((3,))
b = np.ones((3,))
print(np.hstack((a, b)))
'''输出:[0. 0. 0. 1. 1. 1.]'''
print(np.column_stack((a, b)))
'''输出:
[[0. 1.]
[0. 1.]
[0. 1.]]'''
(数组的切分是数组连接的逆操作)
(1) hsplit()函数,用于沿水平方向对数组进行均匀切分
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
b, c = np.hsplit(a, 2)
print(b)
'''输出:
[[ 1 2]
[ 5 6]
[ 9 10]]'''
print(c)
'''输出:
[[ 3 4]
[ 7 8]
[11 12]]'''
(2) vsplit()函数,用于沿垂直方向对数组进行均匀切分
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
b, c, d = np.vsplit(a, 3)
print(b)
'''输出:
[[1 2 3 4]]'''
print(c)
'''输出:
[[5 6 7 8]]'''
print(d)
'''输出:
[[ 9 10 11 12]]'''
数组可以进行加、减、乘、除等基本数学运算,可以是数据间的运算,也可以是数组与标量之间的运算。
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
b = np.array([[12, 11, 10, 9], [8, 7, 6, 5], [4, 3, 2, 1]])
print(a + b)
'''输出:
[[13 13 13 13]
[13 13 13 13]
[13 13 13 13]]'''
print(a + 1)
'''输出:
[[ 2 3 4 5]
[ 6 7 8 9]
[10 11 12 13]]'''
c = np.array([10, 20, 30, 40])
print(a + c) # 通过broadcast机制进行不同形状数组运算
'''输出:
[[11 22 33 44]
[15 26 37 48]
[19 30 41 52]]'''
(1) 数组之间及数组和标量之间可以进行>、>=、<、<=、==、!=等比较运算,运算结果返回的数组是一个布尔型数组(True或False)。
例:
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
b = a > 5
print(b)
'''输出:
[[False False False False]
[False True True True]
[ True True True True]]'''
(2) 布尔型数组可以进行&(和)、|(或)、^(非)等逻辑运算,返回的也是布尔类型的数组。
例:
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
b = (a > 4) & (a < 8)
print(b)
'''输出:
[[False False False False]
[ True True True False]
[False False False False]]'''
(3) 如果要对数组按照某个条件表达式进行判断后重新赋值,可利用where函数,函数形式为:where(cond, xarr, yarr)
例(把数组中大于6的元素设为1,其余元素设为0):
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(np.where(a > 6, 1, 0))
'''输出:
[[0 0 0 0]
[0 0 1 1]
[1 1 1 1]]'''
Numpy中的linalg模块提供大量的线性代数函数(基于Fortran库),可对数组进行线性代数运算。
numpy.linalg模块中常用函数(图源网络):
示例:
import numpy as np
from numpy import linalg
a = np.array([[1, 2], [3, 4]])
print(linalg.inv(a))
'''输出(逆矩阵):
[[-2. 1. ]
[ 1.5 -0.5]]'''
利用Numpy中的统计函数可对数组进行统计计算,统计计算可以对整个数组的元素,也可以对某个轴。
(1) sum(),对数组中全部或某轴向的元素求和
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(a.sum()) # 输出:78
(2) mean(),计算数组的算数平均值
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(a.mean()) # 输出:6.5
(3) std()、var(),计算数组标准差、方差
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(a.std()) # 输出:3.452052529534663
print(a.var()) # 输出:11.916666666666666
(4) max()、min(),计算数组的最大值、最小值
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(a.max()) # 输出:12
print(a.min()) # 输出:1
(5) argmax()、argmin(),获取数组最大值、最小值的下标
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(a.argmax()) # 输出:11
print(a.argmin()) # 输出:0
(6) ……
此外,可以对数组按轴进行统计,
例(对数组按轴求和):
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(np.sum(a, axis=0)) # 按列求和,输出:[15 18 21 24]
print(np.sum(a, axis=1)) # 按行求和,输出:[10 26 42]
(1) sort()函数,返回一个按从小到大顺序进行排序并包含原数组中的所有元素的新数组
a = np.array([3, 3, 1, 2, 6, 1, 6, 9, 8])
print(np.sort(a)) # 输出:[1 1 2 3 3 6 6 8 9]
(2) unique()函数,返回一个按从小到大顺序进行排序并只包含原数组中不同值的元素的新数组
a = np.array([3, 3, 1, 2, 6, 1, 6, 9, 8])
print(np.unique(a)) # 输出:[1 2 3 6 8 9]
完事!