Skip to content

1.NumPy简介与数组基础计算

1.1 NumPy 简介

NumPy 库是 Python 的一种开源的数值计算扩展,主要用于数组计算。这种工具可用来存储和处理大型矩阵,比 Python 自身的嵌套列表 (nested list structure) 结构要高效得多(该结构也可以用来表示矩阵 (matrix))。在数据处理任务上,NumPy 是 Pandas 一个较好的补充,有更为丰富的计算函数和更快的计算速度。NumPy 包含:

  • 一个强大的 N 维数组对象 ndarray
  • 广播功能函数
  • 整合 C/C++/Fortran 代码的工具
  • 线性代数、傅里叶变换、随机数生成等功能

NumPy 导入:

python
conda install numpy # 或 pip3 install numpy
import numpy as np

1.2 NumPy 数组基础

1.2.1 创建数组

(1) 创建一维数组

  1. 打印结果和列表相似
  2. 使用 np.array 方法生成
  3. 一维数组仅需要使用一对 []
  4. 该数组的元素数据类型是 int64
python
arr = np.array([1, 2, 3, 4, 5])  
arr = np.array([1, 2, 3], dtype='int64')  # 创建时指定数据类型

(2) 创建多维数组

  1. 可以认为多维度数组的元素仍然是数组
  2. 二维数组的元素是 1 维数组
  3. 根据手写的元素和最终打印结果可以判断数组构成形式
python
arr = np.array([[1, 2], [3, 4]])

(3) 快速创建函数

  1. np.ones 可以生成元素都为 1 的数组
  2. np.zeros 生成元素都为 0 的数组
  3. np.empty 生成数组的元素不为空,为随机产生的数据
  4. np.arange 生成连续整数数组
python
# 生成元素都为1的数组  
arr = np.ones(12)  
  
# 生成元素都为0的数组  
arr = np.zeros((4, 4))  
  
# 生成数组的元素不为空,为随机产生的数据  
arr = np.empty((2, 3, 4))  
  
# 生成连续整数数组
arr = np.arange(4)                     # 一维
arr = np.arange(8, 15)                 # 一维
arr = np.arange(1, 10, 2)              # 一维
arr = np.arange(10).reshape(2, 5)      # 二维
arr = np.arange(24).reshape(2, 3, 4)   # 三维

1.2.2 属性函数

python
arr.shape             # 数组的形状
arr.ndim              # 数组的维数
arr.size              # 数组元素的个数
arr.itemsize          # 单个元素的字节数
arr.nbytes            # 所有元素的总字节数

1.2.3 数据类型大全

常用的有 bool、int、uint、float、complex

名称描述
bool_布尔型数据类型 (True 或者 False)
int_默认的整数类型 (类似于 C 语言中的 long, int32 或 int64)
intc与 C 的 int 类型一样, 一般是 int32 或 int64
intp用于索引的整数类型 (类似于 C 的 ssize_t, 一般情况下仍然是 int32 或 int64)
int8字节 (-128 to 127)
int16整数 (-32768 to 32767)
int32整数 (-2147483648 to 2147483647)
int64整数 (-9223372036854775808 to 9223372036854775807)
uint8无符号整数 (0 to 255)
uint16无符号整数 (0 to 65535)
uint32无符号整数 (0 to 4294967295)
uint64无符号整数 (0 to 18446744073709551615)
float_float64 类型的简写
float16半精度浮点数, 包括: 1 个符号位, 5 个指数位, 10 个尾数位
float32单精度浮点数, 包括: 1 个符号位, 8 个指数位, 23 个尾数位
float64双精度浮点数, 包括: 1 个符号位, 11 个指数位, 52 个尾数位
complex_complex128 类型的简写, 即 128 位复数
complex64复数, 表示双 32 位浮点数 (实数部分和虚数部分)
complex128复数, 表示双 64 位浮点数 (实数部分和虚数部分)

1.2.4 类型转化

  1. 类型转化不一定成功
  2. 有可能出现无法转化并报错的情况,例如复数(complex)无法转化成整型 (int) 和浮点型 (float)
  3. 即使成功了也要注意数据本身的变化,因为未必和预期一致
python
# 单个字符的转化  
np.float64(42)  
np.int8(127.0)  
np.int8(-128.0)  
np.int8(129.0)  
np.bool_(42)  
np.bool_(0)  
np.bool_(42.0)  
np.float_(True)  
np.float_(False)  
np.arange(7, dtype=np.uint16)  
  
# 数组的转化  
arr = np.array([5.2, 3.2, 9.96, -3.0, -1.9, 10.81])  
arr = arr.astype(np.int32)  # [5,3,9,-3,-1,10],-1.9先不看负号进行转换后再加上负号

1.2.5 字符编码

  1. 当需要指定数据类型时,可以通过 字符编码 来实现
  2. 常用的数据类型包括:整数、浮点数、字符串
数据类型字符编码
整数i
无符号整数u
单精度浮点数f
双精度浮点数d
布尔值b
复数D
字符串S
Unicode 字符串U
void(空)V
python
np.arange(7, dtype='f')  # [0. 1. 2. 3. 4. 5. 6.]
np.arange(7, dtype='D')  # [0.+0.j 1.+0.j 2.+0.j 3.+0.j 4.+0.j 5.+0.j 6.+0.j]
np.dtype(float)          # float64
np.dtype('f')  			 # float32
np.dtype('d')  			 # float64
np.dtype('D')  			 # complex128
np.dtype('f8')  		 # float64
np.dtype('float64')  	 # float64

1.3 NumPy 数组计算

1.3.1 四则运算

  1. NumPy 数组可以简单地进行四则运算
  2. NumPy 数组的幂函数运算可以通过 ** 来完成
  3. 可以通过结果和运算的对比来理解运算的处理逻辑
python
# 数组与标量的运算
arr = np.array([[1., 1., 2.], [3., 5., 8.]])  # 定义二维数组
print(arr)          # 打印数组

print(arr * arr)    # 元素逐位相乘
print('*' * 90)     # 打印分隔线

print(arr - arr)    # 元素逐位相减
print('*' * 90)     # 打印分隔线

print(1 / arr)      # 元素逐位求倒数
print('*' * 90)     # 打印分隔线

print(arr ** 0.5)   # 元素逐位开平方

1.3.2 一维数组索引

  1. 索引可以联想 list 列表的索引规则
  2. 特别说明:7:2 是选中前 7 个元素,从 0 开始每 2 个选一个
  3. 可以使用 slice 事先写好起始点与步长
  4. 如果实在理解困难,可以记住规律,以下三个参数分别为开始位置、结束为止和步长

切片格式:start : stop : step

python
# 一维数组的索引与切片 
a = np.arange(9)           # 生成包含0到8的一维数组
a                          # 打印数组内容

print(a[0])                # 访问索引0的元素
print(a[3:7])              # 获取索引3到6的元素
print(a[:7:2])             # 从头到索引6每隔2个取一个
print(a[::-1])             # 步长为负实现反转

s = slice(3, 7, 2)         # 定义切片对象起点3终点7步长2
print(a[s])                # 使用切片对象取值

s = slice(None, None, -1)  # 定义反向切片对象
print(a[s])                # 使用切片对象反转数组

1.3.3 多维数组索引

  1. 考虑多维数组索引结果,要分层理解
  2. 可参考数组的结构与索引数字来判断结果
  3. 建议在 notebook 中交互验证
python
# 选取数组元素 索引  
a = np.array([[101, 102], [103, 104]])  # 定义二维数组
print(a)  # 打印数组

print(a[0, 0])  # 取第0行第0列
print(a[0, 1])  # 取第0行第1列
print(a[1, 0])  # 取第1行第0列
print(a[1, 1])  # 取第1行第1列

# 多维数组的切片与索引 
b = np.arange(12).reshape(2, 2, 3)  # 创建一个形状为(2,2,3)的三维数组

print(b.shape)  # 打印数组形状
print(b)        # 打印数组内容

print(b[0, 0, 0])  # 取第0块 第0行 第0列
print(b[:, 0, 0])  # 取所有块中 第0行 第0列

1.3.4 数组切片

  1. 多维数组的索引是按照 , 分隔开的
  2. : 表示选择全部,::-1 表示全部选择后逆向
  3. 代表省略(省略的维度上选择全部)
python
b[0]              # 取第一层二维数组
b[0, :, :]        # 同上,完整二维切片
b[0, …]           # 等价于 b[0, :, :]

b[0, 1]           # 取第0层的第1行
b[0, 1, ::2]      # 取第0层第1行,步长为2的列

b[…, 1]           # 取所有二维数组的第1列
b[:, 1]           # 取每个二维数组的第1行
b[:, 1, :]        # 同上,完整行切片
b[0, :, 1]        # 取第0层每行的第1个元素

b[0, :, -1]       # 取第0层每行最后一个元素
b[0, ::-1, -1]    # 第0层的行反向后取最后一列

b[0, ::2, -1]     # 第0层中隔行取最后一列
b[::-1]           # 翻转第一个维度(整体上下翻转)

s = slice(None, None, -1)
b[(s, s, s)]      # 所有维度反向取值(整体翻转)

1.3.5 布尔索引

  1. 注意数组最后的结果,默认是按行筛选
  2. 如果知道了布尔数组的索引,可以写成下面的标准形式
  3. 布尔索引更简洁
python
# 布尔索引
names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])  # 姓名数组
data = np.random.randn(7, 4)  # 7 行 4 列随机数

print(names)        # 查看 names
print(data)         # 查看 data

# 布尔条件判断
print(names == 'Bob')            # 判断是否等于 'Bob' 得到布尔数组
print(data[names == 'Bob'])      # 使用布尔数组筛选对应行
print(data[(names == 'Bob'), 0]) # 布尔条件筛选行后取第 0 列

# shape 说明
print(data.shape)      # 显示 data 的形状 (7,4)
print(names.shape)     # 显示 names 的形状 (7,)

补充说明:

  • shape 的第一个值都是 7,表示有 7 行
  • 布尔索引使得数据筛选更灵活简洁

1.3.6 花式索引

  1. 行索引和列索引结合,根据结果判断筛选方式
  2. 先把布尔值判断的结果赋值,再对数组进行筛选操作
python
# 花式索引
print(data[names == 'Bob', 2])      # 行用布尔判断筛选 'Bob',列取第 2 列
print(data[names == 'Bob', 3])      # 行筛选 'Bob',列取第 3 列

print(names != 'Bob')               # 判断不等于 'Bob'
print(data[~(names == 'Bob')])      # 使用取反 ~ 选择不是 Bob 的行

mask = (names == 'Bob') | (names == 'Will')  # 组合条件:是 Bob 或 Will
print(mask)                                    # 查看布尔掩码
print(data[mask])                              # 使用组合 mask 选择行

1.3.7 布尔索引便捷操作

  1. 数组与数值的比较结果是元素级的,所以索引也是元素级别的
  2. 选中位置后可以直接进行赋值
python
# 布尔索引便捷操作
data[data < 1] = 100          # 选择所有小于 1 的元素并赋值为 100
print(data)                   # 查看结果

data[names != 'Joe'] = 7      # 所有名字不是 Joe 的行全部赋值为 7
print(data)                   # 查看结果

基于 MIT 许可发布