NumPy 是一个运行速度非常快的数学库,主要用于数组计算;
NumPy库不在Python的标准模块中,需要先下载NumPy库;
可以使用pip工具下载:
pip install numpy
引用NumPy库:
import numpy as np
可以通过 numpy._version_ 查看 numpy 的版本:
# 查看Numpy的版本
print("Numpy版本:", np.__version__)
# 输出:
# Numpy版本: 1.20.1
Numpy包的核心对象是 ndarray;它是一系列同类型数据的集合,以 0 下标为开始进行集合中元素的索引。
ndarray 对象是用于存放同类型元素的多维数组,每个元素在内存中都有相同存储大小的区域。
通过array函数创建 np.array(list|tuple|其他类似的数组对象)
# 参数 ndmin 可以指定数组的维度;
# 参数 dtype 可以指定数组元素的数据类型
arr = np.array((0, 1, 2), ndmin=3, dtype=float)
print("arr的元素:\n", arr)
# 输出:
# arr的元素:
# [[[0. 1. 2.]]]
np.random.random()方法 创建ndarray对象
# np.random.random()方法 创建ndarray对象
arr_random = np.random.random((2, 2))
print("arr_random的元素:\n", arr_random)
# 输出:
# arr_random的元素:
# [[0.98249212 0.38319581]
# [0.0135647 0.36293739]]
np.arange()方法:
# np.arange([start, ]stop, [step, ]dtype=None) 函数
# 类似range函数 只是不返回列表而是ndarray数组对象 dtype定义元素的数据类型
# 例如:从10-50(不含50)之间每隔10个数字选取一个数字作为数组元素,元素类型设置为float
arr_arange = np.arange(10, 50, 10, dtype=float)
print("arr_arange的元素:\n", arr_arange)
# 输出:
# arr_arange的元素:
# [10. 20. 30. 40.]
np.linspace()方法:
# np.linspace(start, stop, num=50) 函数
# 选取start和stop之间等差的num个元素
# 例如:选取1-5之间6个等差的数值作为数组的元素
arr_linspace = np.linspace(1, 5, 6)
print("arr_linspace的元素:\n", arr_linspace)
# 输出:
# arr_linspace的元素:
# [1. 1.8 2.6 3.4 4.2 5. ]
很多时候数组的元素是未知的,但是数组的维度大小可能是已经确定的;可以通过zeros,ones,empty函数快速创建固定结构的数组
np.zeros方法
# np.zeros(shape: _ShapeLike) 函数 创建的数组
# 元素默认值是 0 元素数据类型 float
# 创建和arr结构一样的元素为0的数组
# arr_zero = np.zeros(arr.shape)
arr_zero = np.zeros((1, 1, 3))
print("arr_zero的元素:\n", arr_zero)
# 输出:
# arr_zero的元素:
# [[[0. 0. 0.]]]
np.ones方法
# np.ones(shape: _ShapeLike) 函数 创建的数组
# 元素默认值是 1 元素数据类型 float
# arr_one = np.ones(arr.shape)
arr_one = np.ones((1, 1, 3))
print("arr_one的元素:\n", arr_one)
# 输出:
# arr_one的元素:
# [[[1. 1. 1.]]]
np.empty方法
# np.empty(shape: _ShapeLike) 函数 创建的数组
# 元素默认值是随机的,取决于内存状态 元素数据类型 float
# arr_empty = np.empty(arr.shape)
arr_empty = np.empty((1, 1, 3))
print("arr_empty的元素:\n", arr_empty)
# 输出:
# arr_empty的元素:
# [[[1. 1. 1.]]]
ndim 轴:rank
ndarray.ndim 数组的轴(维度)的个数:rank
轴的概念:
[0,1,2] 该数组有一个轴,轴拥有 3 个元素
[[0,1,2],[1,2,3]]该数组有 2 个轴,第1轴长度为 2,第2轴长度为 3
arr1 = np.array(range(5))
arr2 = np.array([range(10)])
arr3 = np.array([[range(15)]])
arr4 = np.array(range(20), ndmin=4)
print("arr1轴(维度)的个数:", arr1.ndim,
"\narr2轴(维度)的个数:", arr2.ndim,
"\narr3轴(维度)的个数:", arr3.ndim,
"\narr4轴(维度)的个数:", arr4.ndim)
# 输出:
# arr1轴(维度)的个数: 1
# arr2轴(维度)的个数: 2
# arr3轴(维度)的个数: 3
# arr4轴(维度)的个数: 4
shape 数组的维度:
ndarray.shape 一个tuple 表示每个维度数组的长度;tuple的每个元素对应表示每个轴的长度;tuple的长度就是数组的轴的个数;如果返回tuple(n,m) 表示该数组是个 n行 m列 的矩阵
print("arr1.shape:", arr1.shape,
"\narr2.shape:", arr2.shape,
"\narr3.shape:", arr3.shape,
"\narr4.shape:", arr4.shape)
# 输出:
# arr1.shape: (5,)
# arr2.shape: (1, 10)
# arr3.shape: (1, 1, 15)
# arr4.shape: (1, 1, 1, 20)
size 数组元素的总和:
ndarray.size 等于 ndarray.shape 返回 tuple 元素的乘积;
print("arr1.size:", arr1.size,
"\narr2.size:", arr2.size,
"\narr3.size:", arr3.size,
"\narr4.size:", arr4.size)
# 输出:
# arr1.size: 5
# arr2.size: 10
# arr3.size: 15
# arr4.size: 20
dtype 数组中元素类型的对象
arr5 = np.array(list("abc"))
arr6 = np.array(range(5))
print("arr5元素类型:", arr5.dtype.name,
"\narr6元素类型:", arr6.dtype.name)
# 输出:
# arr5元素类型: str32
# arr6元素类型: int32
itemsize 数组中每个元素的字节大小
print("arr5元素字节大小:", arr5.itemsize,
"\narr6元素字节大小:", arr6.itemsize)
# 输出:
# arr5元素字节大小: 4
# arr6元素字节大小: 4
data 包含实际数组元素的缓冲区:
由于一般通过数组的索引获取元素,所以通常不需要使用这个属性
数组上的算术运算都是应用到每个元素
一般运算 加减乘除:
如果数组的shape不同会出现:ValueError
arr_a = np.arange(5)
arr_b = np.array([6, 7, 8, 9, 10])
# 一般运算 加减乘除
print("arr_a + arr_b = ", arr_a + arr_b)
print("arr_a - arr_b = ", arr_a - arr_b)
print("arr_a * arr_b = ", arr_a * arr_b)
print("arr_a / arr_b = ", arr_a / arr_b)
# 输出:
# arr_a + arr_b = [ 6 8 10 12 14]
# arr_a - arr_b = [-6 -6 -6 -6 -6]
# arr_a * arr_b = [ 0 7 16 27 40]
# arr_a / arr_b = [0. 0.14285714 0.25 0.33333333 0.4 ]
赋值:
# 赋值 利用+= *= 可以直接改变被操作的数组而不会生成新的数组
arr_a += 1
print("arr_a 元素 +1:", arr_a)
arr_b *= 2
print("arr_b 元素 *2 :", arr_b)
# 输出:
# arr_a 元素 +1: [1 2 3 4 5]
# arr_b 元素 *2 : [12 14 16 18 20]
NumPy提供熟悉的数学函数,如:sin cos和exp等;在NumPy中称为:通函数;
max函数:
arr_a = np.array([[1, 2, 3, 4, 5],
[6, 7, 8, 9, 10]])
print("arr_a.max()元素最大值:", arr_a.max())
# 利用指定参数axis可以沿数组的指定轴进行操作
# axis=0 垂直方向,axis=1 水平方向
print("arr_a.max(axis=0)垂直方向最大值,返回结果元素数组:",
arr_a.max(axis=0))
# 输出:
# arr_a.max()元素最大值: 10
# arr_a.max(axis=0)垂直方向最大值,返回结果元素数组: [ 6 7 8 9 10]
min函数:
arr_a = np.array([[1,2, 3, 4, 5],
[6, 7, 8, 9, 10]])
print("arr_a.min()元素最小值:", arr_a.min())
# axis=0 垂直方向,axis=1 水平方向
print("arr_a.min(axis=1)水平方向最小值,返回结果元素数组:",
arr_a.min(axis=1))
# 输出:
# arr_a.min()元素最小值: 1
# arr_a.min(axis=1)水平方向最小值,返回结果元素数组: [1 6]
sum函数:
arr_a = np.array([[1,2, 3, 4, 5],
[6, 7, 8, 9, 10]])
print("arr_a.sum()元素求和:", arr_a.sum())
# 输出:
# arr_a.sum()元素求和: 55
cumsum累加函数:
arr_a = np.array([[1,2, 3, 4, 5],
[6, 7, 8, 9, 10]])
# 相当于 [1,1+2,1+2+3,1+2+3+4,...]
print("arr_a.cumsum()元素累加,返回累加结果元素的一维数组:",
arr_a.cumsum())
# 输出:
# arr_a.cumsum()元素累加,返回累加结果元素的一维数组: [ 1 3 6 10 15 21 28 36 45 55]
sin 函数:
arr_a = np.array([[1,2, 3, 4, 5],
[6, 7, 8, 9, 10]])
print("np.sin(arr_a)获取数组元素sin值:\n", np.sin(arr_a))
# 输出:
# np.sin(arr_a)获取数组元素sin值:
# [[ 0.84147098 0.90929743 0.14112001 -0.7568025 -0.95892427]
# [-0.2794155 0.6569866 0.98935825 0.41211849 -0.54402111]]
where函数:
arr_a = np.array([[1,2, 3, 4, 5],
[6, 7, 8, 9, 10]])
# np.where(condition,[x,y,]/)
# 例如:arr_a中大于5的元素,将元素值减5,小于等于5的元素+5,返回ndarray数组
print("where函数:\n",
np.where(arr_a > 5, arr_a - 5, arr_a + 5))
# 输出:
# where函数:
# [[ 6 7 8 9 10]
# [ 1 2 3 4 5]]
数组可以像Python中list一样进行索引 切片和迭代的操作;一维数组和多为数组略微不同
一维数组就可以像list一样进行索引,切片,迭代的操作
arr_b = np.arange(10)
print("一维数组索引访问 arr_b[5]:", arr_b[5])
print("一维数组切片访问 arr_b[-5:- 2]:", arr_b[-5:- 2])
for b in arr_b:
print("迭代访问一维数组arr_b:", b)
# 输出:
# 一维数组索引访问 arr_b[5]: 5
# 一维数组切片访问 arr_b[-5:- 2]: [5 6 7]
# 迭代访问一维数组arr_b: 0
# 迭代访问一维数组arr_b: 1
# ...
# 迭代访问一维数组arr_b: 8
# 迭代访问一维数组arr_b: 9
多维的数组可以对每个轴进行索引切片操作,每个轴之间用逗号隔开:
arr_a = np.array([[[1, 2, 3],
[4, 5, 6]],
[[7, 8, 9],
[10, 11, 12]]])
print("多维数组索引访问 arr_a[0, 0, 0]: ", arr_a[0, 0, 0])
# 输出:
# 多维数组索引访问 arr_a[0, 0, 0]: 1
print("多维数组切片访问 arr_a[0:1, 0:2, 0:2]:\n",
arr_a[0:1, 0:2, 0:2])
# print("多维数组切片访问 arr_a[..., 0:2, 0:2]",
# arr_a[..., 0:2, 0:2])
# print("多维数组切片访问 arr_a[:, :, :2]",
# arr_a[:, :, :2])
# 输出:
# 多维数组切片访问 arr_a[0:1, 0:2, 0:2]:
# [[[1 2]
# [4 5]]]
如果提供的索引少于轴的数量,缺少的索引将会被认为成完整的切片 : ;三个点 (…)表示会补齐索引所有需要的冒号
例如:
arr_a[...] == arr_a[:, :, :]
迭代:
多维数组迭代是对第一轴进行迭代:
只是返回第一轴的元素
arr_a = np.array([[[1, 2, 3],
[4, 5, 6]],
[[7, 8, 9],
[10, 11, 12]]])
# 多维数组迭代是对第一轴进行迭代
print("迭代访问多维数组arr_a:")
for a in arr_a:
print("\n", a)
# 输出:
# 迭代访问多维数组arr_a:
# [[1 2 3]
# [4 5 6]]
# [[ 7 8 9]
# [10 11 12]]
数组的flat属性是所有元素的迭代器;可以利用flat属性迭代多维数组中的所有元素:
arr_a = np.array([[[1, 2, 3],
[4, 5, 6]],
[[7, 8, 9],
[10, 11, 12]]])
# 数组的flat属性是所有元素的迭代器
print("数组的flat属性:", arr_a.flat)
print("利用数组的flat属性迭代多维数组所有元素:")
for a in arr_a.flat:
print(a)
# 输出:
# 数组的flat属性:
# 利用数组的flat属性迭代多维数组所有元素:
# 1
# 2
# 3
# ...
# 11
# 12
每个数组的形状都是由数组的轴和轴的元素数量决定的,可以使用各种不同的方法对数组的形状进行更改;例如:ravel(),reshape(),T方法 以及 resize()方法。
ravel(),reshape(),T方法 – 返回新数组 不会改变原始数组结构
resize()方法 – 会修改原始数组结构
定义一个数组,然后通过不同的方法对数组的形状进行更改:
arr_a = np.array([[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12]])
ravel()方法:
# ravel()方法 将数组所有元素变成一维数组
print("ravel()方法:\n", arr_a.ravel())
# 输出:
# ravel()方法:
# [ 1 2 3 4 5 6 7 8 9 10 11 12]
reshape方法:
# reshape(shape: Sequence[int])方法 改变数组的shape值
print("reshape(4, 3)方法:\n", arr_a.reshape(4, 3))
# 输出:
# reshape(4, 3)方法:
# [[ 1 2 3]
# [ 4 5 6]
# [ 7 8 9]
# [10 11 12]]
# 如果reshape()中的size设置为 -1 则会自动计算size的值
print("reshape(2,-1)方法:\n", arr_a.reshape(2, -1))
# 输出:
# reshape(2,-1)方法:
# [[ 1 2 3 4 5 6]
# [ 7 8 9 10 11 12]]
T方法 : 转置
# T方法 转置
print("T方法 转置:\n", arr_a.T)
# 输出:
# T方法 转置:
# [[ 1 5 9]
# [ 2 6 10]
# [ 3 7 11]
# [ 4 8 12]]
resize() 方法:
resize()方法 – 会修改原始数组结构
# resize() 方法
arr_a.resize(4, 3)
print("resize(4, 3)方法:\n", arr_a)
# 输出:
# resize(4, 3)方法:
# [[ 1 2 3]
# [ 4 5 6]
# [ 7 8 9]
# [10 11 12]]
定义两个数组:
arr_a = np.array([[1, 2],
[3, 4]])
arr_b = np.array([[5, 6],
[7, 8]])
np.concatenate方法:
# np.concatenate((a1, a2, a3...), axis=0, out=None, dtype=None, casting="same_kind")
# 默认axis=0,垂直方向;axis=1 水平方向
arr_c = np.concatenate((arr_a, arr_b), axis=1)
print("np.concatenate方法:\n", arr_c)
# 输出:
# np.concatenate方法:
# [[1 2 5 6]
# [3 4 7 8]]
np.vstack方法:垂直堆叠
# np.vstack(tup: Sequence[ArrayLike])方法 垂直堆叠
arr_c = np.vstack((arr_a, arr_b))
print("np.vstack方法:\n", arr_c)
# 输出:
# np.vstack方法:
# [[1 2]
# [3 4]
# [5 6]
# [7 8]]
np.hstack方法:水平堆叠
# np.hstack(tup: Sequence[ArrayLike])方法 水平堆叠
arr_c = np.hstack((arr_a, arr_b))
print("np.hstack方法:\n", arr_c)
# 输出:
# np.hstack方法:
# [[1 2 5 6]
# [3 4 7 8]]
np.dstack方法:沿着深度(高度)堆叠
# np.dstack() 方法 沿着深度(高度)堆叠
arr_c = np.dstack((arr_a, arr_b))
print("np.dstack方法:\n", arr_c)
# 输出:
# np.dstack方法:
# [[[1 5]
# [2 6]]
# [[3 7]
# [4 8]]]
定义一个数组 准备进行拆分:
arr_a = np.array([[0, 1, 2, 3, 4, 5],
['a', 'b', 'c', 'd', 'e', 'f']])
np.array_split方法:
# np.array_split(ary,indice_or_sections,axis=0)
# indice_or_sections 平均拆分的个数或者 数组 例如:[2,5] 左开右闭
# 拆分的axis=0垂直方向拆分 xis=1水平方向拆分
# xis=0垂直方向拆分
arr_b = np.array_split(arr_a, 2, axis=0)
print("np.array_split方法平均拆分数组:\n", arr_b)
# 输出: 垂直方向拆分成 2 个数组
# np.array_split方法平均拆分数组:
# [array([['0', '1', '2', '3', '4', '5']], dtype='
# array([['a', 'b', 'c', 'd', 'e', 'f']], dtype='
# axis=1水平方向拆分
arr_c = np.array_split(arr_a, [2, 5], axis=1)
print("np.array_split方法按位置拆分数组:\n", arr_c)
# print(arr_a[:, 2:5])
# 输出:
# np.array_split方法按位置拆分数组:
# [array([['0', '1'],
# ['a', 'b']], dtype='
# array([['2', '3', '4'],
# ['c', 'd', 'e']], dtype='
# array([['5'],
# ['f']], dtype='
np.hsplit():水平方向拆分
arr_b = np.hsplit(arr_a, 2)
print("np.hsplit()水平方向拆分:\n", arr_b)
# 输出:
# np.hsplit()水平方向拆分:
# [array([['0', '1', '2'],
# ['a', 'b', 'c']], dtype='
# array([['3', '4', '5'],
# ['d', 'e', 'f']], dtype='
np.vsplit() :垂直方向拆分
# np.vsplit() 垂直方向拆分
arr_b = np.vsplit(arr_a, 2)
print("np.vsplit() 垂直方向拆分:\n", arr_b)
# 输出:
# np.vsplit() 垂直方向拆分:
# [array([['0', '1', '2', '3', '4', '5']], dtype='
# array([['a', 'b', 'c', 'd', 'e', 'f']], dtype='
np.dsplit():dsplit仅适用于3维或更高维的阵列
# np.dsplit() dsplit仅适用于3维或更高维的阵列
arr_a.shape = (1, 2, 6)
arr_b = np.dsplit(arr_a, 2)
print("np.dsplit()方法拆分",arr_b)
# 输出:
# np.dsplit()方法拆分:
# [array([[['0', '1', '2'],
# ['a', 'b', 'c']]], dtype='
# array([[['3', '4', '5'],
# ['d', 'e', 'f']]], dtype='
副本就是数据的完整拷贝,对副本的修改不会影响原始数据
视图是数据的一个别称,如果对视图进行修改,会影响原始数据
简单的分配不会复制数组对象或者数组数据
只是对其进行引用
arr_a = np.arange(5)
arr_b = arr_a
print("arr_a is arr_b:", arr_b is arr_a)
# 输出:
# arr_a is arr_b: True
print("id(arr_a) == id(arr_b):", id(arr_a) == id(arr_b))
# 输出:
# id(arr_a) == id(arr_b): True
# 如果改变arr_b arr_a也会改变
arr_b[:] = 0
print("arr_b元素重新赋值为0,打印arr_a:", arr_a)
# 输出:
# arr_b元素重新赋值为0,打印arr_a: [0 0 0 0 0]
view方法创建视图:view方法创建一个查看相同数据的新数组对象
arr_a = np.arange(6)
arr_b = arr_a.view()
print("arr_a is arr_b:", arr_b is arr_a)
# 输出:
# arr_a is arr_b: False
print("id(arr_a) == id(arr_b):", id(arr_a) == id(arr_b))
# 输出:
# id(arr_a) == id(arr_b): False
# 如果改变arr_b的数据 arr_a也会改变
arr_b[:] = 0
print("arr_b元素重新赋值为0,打印arr_a:", arr_a)
# 输出:
# arr_b元素重新赋值为0,打印arr_a: [0 0 0 0 0 0]
# arr_b是通过view方法创建的新的数组对象 改变arr_b的shape不会对arr_a有影响
arr_b.shape = (2, 3)
print("arr_a.shape:",arr_a.shape)
# 输出:
# arr_a.shape: (6,)
切片数组返回视图:
修改切片数组返回的视图 会对原始数据进行修改
arr_a = np.arange(6)
arr_c = arr_a[2:4]
print("arr_c:", arr_c)
# 输出:
# arr_c: [2 3]
# 修改arr_c
arr_c[:] = 0
print("arr_a:", arr_a)
# 输出:
# arr_a: [0 1 0 0 4 5]
copy方法生成数组以及原始数组数据的完整副本:
arr_a = np.arange(6)
arr_b = arr_a.copy()
print("arr_a is arr_b:", arr_b is arr_a)
# 输出:
# arr_a is arr_b: False
print("id(arr_a) == id(arr_b):", id(arr_a) == id(arr_b))
# 输出:
# id(arr_a) == id(arr_b): False
arr_b[:] = 0
print("arr_b元素重新赋值为0,打印arr_a:", arr_a)
# 输出:
# arr_b元素重新赋值为0,打印arr_a: [0 1 2 3 4 5]
arr_b.shape = (2, 3)
print("arr_a.shape:", arr_a.shape)
# 输出:
# arr_a.shape: (6,)
如果原始数组数据较大的时候,可以先从原始数组中获取切片数组,如果不再需要对原始数据进行更改的话,可以将切片数组通过copy方法进行深拷贝一个新的数组对象。
主要参考资料:
NumPy官方的中文文档
以上就是关于Python NumPy库的一些基础用法的学习;
如果有什么不对的地方,欢迎指正!