NumPy库
这篇文章主要内容来源于Python、Numpy 教程 | NumPy 中文和python常用库 - NumPy 和 sklearn入门 - ML小菜鸟 - 博客园 (cnblogs.com)
1.1 导入NumPy库
import numpy as np
1.2 numpy.array 与 list的关系与区别
a = [1,2,3,4,5,6] # python内置数组结构
b = np.array(a) # numpy数组结构
list特点:
- list中保存的元素可以是不同类型的,可以是str,整型等等
- list数组中的每个元素的存储都需要1个指针和1个数据
- list实际保存的是数据的“存放地址”,这会带来额外的内存消耗
当想要减少内存的消耗的情况下,可以将list替换成np.array,这样可以节约很多空间,而且Numpy数组是执行更快数值计算的优秀容器。
1.3 NumPy的常用操作
常用操作
# 以下为创建一维数组的基本方法
a = np.array([0, 1, 2, 3, 4])
b = np.array((0, 1, 2, 3, 4))
c = np.arange(5)
d = np.linspace(0, 2*np.pi, 5)
# 输出结果
print(a) # >>>[0 1 2 3 4]
print(b) # >>>[0 1 2 3 4]
print(c) # >>>[0 1 2 3 4]
print(d) # >>>[ 0. 1.57079633 3.14159265 4.71238898 6.28318531]
print(a[3]) # >>>3
上面的代码显示了创建数组的4种不同方法。最基本的方法是将序列传递给NumPy的array()函数; 你可以传递任何序列(类数组),而不仅仅是常见的列表(list)数据类型。
当print具有不同长度数字的数组时,会自动补齐(如d),这能便于查看矩阵。
对数组的索引和list的操作类似(如a[3])
创建一个二维数组
# 二位数组创建
a = np.array([[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25],
[26, 27, 28 ,29, 30],
[31, 32, 33, 34, 35]])
print(a[2,4]) # >>>25
如上示代码,创建一个二维数组的时候,我们可传递一个“列表的列表”给array()函数。以此类推,一个三维数组的创建就需要给array()函数传递一个“列表的列表的列表”,更高维的以此类推。
当我们想要索引一个二维数组时,我们需要给定所需的行和列的索引(如a[2,4])
多维数组切片
a = np.array([[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25],
[26, 27, 28 ,29, 30],
[31, 32, 33, 34, 35]])
print(a[0, 1:4]) # >>>[12 13 14]
print(a[1:4, 0]) # >>>[16 21 26]
print(a[::2,::2]) # >>>[[11 13 15]
# [21 23 25]
# [31 33 35]]
print(a[:, 1]) # >>>[12 17 22 27 32]
通过对每个以逗号分隔的维度执行单独的切片,可以对多维数组进行切片。因此,对于二维数组,第一片定义了行的切片,第二片定义了列的切片。
图来自NumPy中文网
数组属性
在使用 NumPy 时,你会想知道数组的某些信息。很幸运,在这个包里边包含了很多便捷的方法,可以给你想要的信息。
# 查看数组属性
a = np.array([[11, 12, 13, 14, 15],
[16, 17, 18, 19, 20],
[21, 22, 23, 24, 25],
[26, 27, 28 ,29, 30],
[31, 32, 33, 34, 35]])
print(type(a)) # >>><class 'numpy.ndarray'>
print(a.dtype) # >>>int64
print(a.size) # >>>25
print(a.shape) # >>>(5, 5)
print(a.itemsize) # >>>8
print(a.ndim) # >>>2
print(a.nbytes) # >>>200
a的类型实际上为’ndarray’
数组的形状是它有多少行和列,上面的数组有5行和5列,所以它的形状是(5,5)。
itemsize
属性是每个项占用的字节数。这个数组的数据类型是int 64,一个int 64中有64位,一个字节中有8位,除以64除以8,你就可以得到它占用了多少字节,在本例中是8。
ndim
属性是数组的维数。这个有2个。例如,向量只有1。
nbytes
属性是数组中的所有数据消耗掉的字节数。你应该注意到,这并不计算数组的开销,因此数组占用的实际空间将稍微大一点。
使用数组
基本操作符
# 基本操作符
a = np.arange(25)
a = a.reshape((5, 5))
b = np.array([10, 62, 1, 14, 2, 56, 79, 2, 1, 45,
4, 92, 5, 55, 63, 43, 35, 6, 53, 24,
56, 3, 56, 44, 78])
b = b.reshape((5,5))
print(a + b)
print(a - b)
print(a * b)
print(a / b)
print(a ** 2)
print(a < b)
print(a > b)
print(a.dot(b))
当我们对两个array进行运算的时候,实际上是对每个元素进行了运算。如(a + b)实际上就是将a,素组中的每一个元素分别进行相加,结果同样输出为一个数组。
注意,当进行逻辑运算(< >)时,返回的是一个布尔型数组:
print(a < b)
[[ True True False True False]
[ True True False False True]
[False True False True True]
[ True True False True True]
[ True False True True True]]
dot() 函数计算两个数组的点积。它返回的是一个标量(只有大小没有方向的一个值)而不是数组。
(还没弄懂QAQ)
数组特殊运算符
# dot, sum, min, max, cumsum
a = np.arange(10)
print(a.sum()) # >>>45
print(a.min()) # >>>0
print(a.max()) # >>>9
print(a.cumsum()) # >>>[ 0 1 3 6 10 15 21 28 36 45]
sum()
、min()
和max()
函数的作用非常明显。将所有元素相加,找出最小和最大元素。
cumsum()
函数首先将第一个元素和第二个元素相加,并将其存储在一个列表中,然后将该结果添加到第三个元素中,全部执行完毕后返回相加后的列表(也许前缀和有用?)
索引进阶
花式索引
# 花式索引
a = np.arange(0, 100, 10)
indices = [1, 5, -1]
b = a[indices]
print(a) # >>>[ 0 10 20 30 40 50 60 70 80 90]
print(b) # >>>[10 50 90]
可以使用 一个数组对另一个数组进行索引
布尔屏蔽
# 布尔屏蔽
import matplotlib.pyplot as plt
a = np.linspace(0, 2 * np.pi, 50)
b = np.sin(a)
plt.plot(a,b)
mask = b >= 0
plt.plot(a[mask], b[mask], 'bo')
mask = (b >= 0) & (a <= np.pi / 2)
plt.plot(a[mask], b[mask], 'go')
plt.show()