Python库Numpy入门
NumPy是Python中科学计算的基本包。它是一个Python库,提供多维数组对象、各种派生对象(如掩码数组和矩阵),以及用于对数组进行快速操作的各种例程,包括数学、逻辑、形状操作、排序、选择、I/O、离散傅立叶变换、基本线性代数、基本统计运算、随机模拟等等。
numpy的核心是ndarray对象,这是一个多维数组。
安装
用pip安装
pip install numpy
官网下载
基本使用
多维数组概念
在numpy中, 维度(dimensions) 被称作 轴(axes) 。
[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]]
在上面这个数组中,有两个轴,即是二维数组(二维空间)。第一个轴有三个元素,即分别为[ 0 1 2 3 4 ]
、[ 5 6 7 8 9 ]
和[ 10 11 12 13 14 ]
,长度为3。第二个轴有五个元素,即长度为5。
创建一个数组
numpy数组的类为ndarray,这有别于python标准库中的array.array。
以下为创建numpy数组的示例:
# 先导入numpy,别称为np
import numpy as np
# 生成一个5x3的二维数组a
a = np.arange(15).reshape(5,3)
print(a)
# 将会输出:
# [[ 0 1 2]
# [ 3 4 5]
# [ 6 7 8]
# [ 9 10 11]
# [12 13 14]]
除此之外,ndarray还有多种属性,如下:
# 数组的维数
print(a.ndim)
# 结果:2
# 表示数组为2维空间
# 数组的形状
print(a.shape)
# 结果:(5,3)
# 表示数组为5x3的二维数组
# 数组的类型(data type)
print(a.dtype)
# 数组中每个元素的大小(bit)
print(a.itemsize)
# 输出数组在内存中的真实数据
# 通常不会用到该属性
print(a.data)
同样,也能通过python标准库中的列表来创建numpy数组:
# 调用np.array()方法即可把列表转换成数组
a = np.array([1,2,3])
# 同样浮点型也适用
a = np.array([1.2,2.4,1.8])
# 还可以转换成多维数组
b = np.array([(1.5, 2, 3), (4, 5, 6)])
print(b)
# 结果:
# [[1.5 2. 3. ]
# [4. 5. 6. ]]
b = np.array([[1, 2], [1, 2]], dtype=complex)
# complex是复数类型
为了提高效率,numpy还提供了创建空数组的方法:
# 创建全为0的2x3的二维数组
np.zeros((2,3))
# 创建全为1的2x3x4的三维数组
np.ones((2,3,4))
# 创建空数组(数据值取决于内存,即随机)
np.empty((2,3))
我们再回顾本段落第一个示例,里面用的arange方法可以生成一个递增或者递减的序列:
# np.arange(start,stop,step)
# 起始 结束 步进
# 创建一个从[0,5)的一个一维数组
a = np.arange(5)
print(a)
# 结果:[0 1 2 3 4]
# 创建一个从[10,30),步进为5的一维数组
a = np.arange(10,30,5)
# 结果:[10 15 20 25]
# 也可以是递减的
a = np.arange(30,10,-5)
# 结果:[30 25 20 15]
如果想生成带小数的序列,推荐使用linspace方法,它可以生成一个等间隔的序列:
# np.linspace(start,stop,num)
# 起始 结束 数的个数
# 把[0,5]等间距的分成6个数
d = np.linspace(0, 5, 6)
print(d)
# 结果:[0. 1. 2. 3. 4. 5.]
# 注意:间距=(stop-start)/(num-1)
# 计算sin(x)在[0,2π]区间内等间距的10个点的数值
from numpy import pi
x = np.linspace(0, 2 * np.pi, 10)
f = np.sin(x)
print(f)
# 结果:[ 0.00000000e+00 6.42787610e-01 9.84807753e-01 8.66025404e-01
# 3.42020143e-01 -3.42020143e-01 -8.66025404e-01 -9.84807753e-01
# -6.42787610e-01 -2.44929360e-16]
这些序列还可以用reshape()
方法重新分配为新的多维数组:
# 创建一个1~10的5x2的二维数组
a = np.arange(1,11).reshape(5,2)
数组操作(基本运算)
先生成两个ndarray的变量:
a = np.array([10, 10, 10])
# [10,10,10]
b = np.arange(3)
# [0 ,1 ,2]
进行如下运算:
# a数组减去b数组
a - b
# 得到:[10,9,8]
# b数组的2次幂
b**2
# 得到:[0,1,4]
# b数组是否小于1
b < 1
# 得到:[True, False, False]
以下是多维数组的运算:
A = np.array([[1,1],
[0,1]])
B = np.array([[2,0],
[3,4]])
# 矩阵对应元素相乘
A * B
# 得到:
# [[2 0]
# [0 4]]
# 以下运算才是矩阵的相乘(线性代数)
A @ B
# 得到:
# [[5 4]
# [3 4]]
A.dot(B)
# 以上也能实现矩阵相乘 等同于 A@B
# 一个数乘以矩阵
3 * B
# 得到:
# [[ 6 0]
# [ 9 12]]
A *= 3
# 相当于 A = A * 3
B += A
# 相当于 B = B + A
其他常见的运算:
# 复数运算
np.exp(B * 2j)
# j代表复数
# 求和(数组内所有元素的和)
np.sum(B)
# 求最小元素
np.min(B)
# 求最大元素
np.max(B)
索引和切片
一维数组
对于一维数组而言,和Python自带的列表操作十分的相似:
# 产生10个元素的数组
a = np.arange(10)
# [0 1 2 3 4 5 6 7 8 9]
# 索引为3的元素表示为
a[3] # 3
# 注意索引从0~9共十个数
# 还可以进行切片 输出索引2,3的数
a[2:4] # [2 3]
# 也可以设置步长
# 如下可以实现逆序该数组
a[::-1] # [9 8 7 6 5 4 3 2 1 0]
# 遍历每一个元素
for t in a:
print(t)
多维数组
在多维数组中,对于每一个轴都有一个索引。
以下是二维数组操作的示例:
# [[ 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]]
a = np.arange(30).reshape(5,6)
# 取第3行第4个元素
# 索引依次为2,3
a[2,3] # 15
# 当然也能进行切片
# 第一个索引表明只保留第2,3行
# 第二个索引表明取全部元素
a[1:3,:] # [[12 13 14 15 16 17]
# [18 19 20 21 22 23]]
对于N维数组,跟二维数组类似,a[1,2,3, ...]
,有N个索引可以使用。
形状操作
最常用的方法还是reshape()
方法,示例如下:
# 3行4列的矩阵
a = np.arange(12).reshape(3, 4)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# 改变成6行2列的矩阵
a = a.reshape(6, 2)
# [[ 0 1]
# [ 2 3]
# [ 4 5]
# [ 6 7]
# [ 8 9]
# [10 11]]
# 改变成2x3x2的三维数组
a = a.reshape(2, 3, 2)
# [[[ 0 1]
# [ 2 3]
# [ 4 5]]
# [[ 6 7]
# [ 8 9]
# [10 11]]]
还可以用ravel()
方法将多维数组展开为1维数组,即列表:
# 2x3x2的三维数组
a = np.arange(12).reshape(2, 3, 2)
# 展开为一维数组
a = a.ravel()
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
ndarray中还有一个T
的属性,可以获得该矩阵的转置:
# 3行4列的矩阵
a = np.arange(12).reshape(3, 4)
# 输出a的转置
print(a.T)
# [[ 0 4 8]
# [ 1 5 9]
# [ 2 6 10]
# [ 3 7 11]]
# 变成4行3列的了,元素也转置了
相比于reshape()
只能返回一个修改后的数组,resize()
方法可以直接修改当前的数组,不用接受返回值,如下示例:
# 3行4列的矩阵
a = np.arange(12).reshape(3, 4)
# 以下两句代码的作用是相同的
a = a.reshape(4, 3)
a.resize(4, 3)
# 打印a
print(a)
拼接和分离数组
拼接
垂直拼接
np.vstack()
水平拼接
np.hstack()
分离
垂直分离
np.vsplit()
水平分离
np.hsplit()
数组拷贝
类似Python中的对象,以下代码并不能直接复制数组:
a = np.arange(12).reshape(3, 4)
b = a
# a和b实际是相同的
print(a is bs)
# True
浅拷贝
浅拷贝并不复制里面的元素,也就是说两个变量共享里面的元素,如下示例:
a = np.arange(12).reshape(3, 4)
# b是a的浅拷贝
b = a.view()
# b中的元素不是自己的
print(b.flags.owndata)
# False
# b改变形状并不会影响a
b.resize((4,3))
print(b)
# [[ 0 1 2]
# [ 3 4 5]
# [ 6 7 8]
# [ 9 10 11]]
print(a)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
# 但是改变b中的元素会影响a的元素
b[0, 0] = 100
print(a)
# [[100 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
深拷贝
使用copy()
方法可以完全拷贝里面的所有元素,让他们成为两个完全独立的变量:
a = np.arange(12).reshape(3, 4)
b = a.copy()
# 此时无论b中元素怎么改变都不会影响a的任何元素