二、NumPy数据处理
1、Numpy基础与数组创建
1.1 Numpy基础知识
Numpy(Numerical Python)是Python编程语言里面用于数值计算的基础库,它提供了高性能的多维数组对象 narray 以及一系列用于操作这类数组的工具函数。NumPy于2005年发布,现如今已成为Python数据科学生态系统的核心组件。
💡重要提示:pandas、scipy、scikit-learn等主流数据处理库都是基于NumPy构建的。掌握NumPy就像掌握了数据分析的「内功心法」,后续学习其他库将事半功倍。
NumPy的核心特性包括:
- 向量化运算:无需编写循环即可对整个数组进行数学运算。
- 广播机制:支持不同形状数组之间的运算。
- 高效内存存储:连续内存块存储,访问速度快。
- 丰富的数学函数库:线性代数、傅里叶变换、随机数生成等。
1.2 ndarray 与 Python列表
对于Python列表与Numpy数组两者之间的关系让大多数初学者有些不解,虽然看着并无差别,但是通过特性回来看确实大不相同。
💡NumPy数组
- 元素类型:必须同质
- 运算方式:向量化运算
- 执行速度:使用C语言作为底层,速度快
- 内存占用:紧凑,连续内存块
- 维度支持:原生N维数组
- 功能丰富度:多维运算、矩阵分解、统计聚合
import numpy as np
import time
# Python列表:循环求和
py_list = list(range(1000000))
start = time.time()
py_sum = sum(py_list)
print(f"Python列表求和耗时:{time.time() – start:.4f}秒")
# NumPy数组:向量化求和
np_arr = np.arange(1000000)
start = time.time()
np_sum = np_arr.sum()
print(f"NumPy数组求和耗时:{time.time() – start:.4f}秒")
1.3 创建数组的方式
# NumPy库
import numpy as np
# 方式1:从Python列表转换(最常用)
a = np.array([1, 2, 3, 4, 5])
print(f"从列表创建:{a}") # [1 2 3 4 5]
# 方式2:全0数组
zeros_1d = np.zeros(5) # 一维:5个元素
zeros_2d = np.zeros((3, 4)) # 二维:3行4列
print(f"全0一维数组:{zeros_1d}")
# [0. 0. 0. 0. 0.]
# 方式3:全1数组
ones_1d = np.ones(5)
ones_2d = np.ones((3, 4))
print(f"全1二维数组:\\n{ones_2d}")
# [[1. 1. 1. 1.]
# [1. 1. 1. 1.]
# [1. 1. 1. 1.]]
# 方式4:指定填充值的数组
full_arr = np.full((2, 3), 7) # 2行3列,全部填充7
print(f"全7数组:\\n{full_arr}")
# [[7 7 7]
# [7 7 7]]
# 方式5:范围数组
arr1 = np.arange(0, 10, 2) # 开始0,结束10,步长2
arr2 = np.linspace(0, 1, 5) # 开始0,结束1,均匀切分5份
print(f"arange创建:{arr1}") # [0 2 4 6 8]
print(f"linspace创建:{arr2}") # [0. 0.25 0.5 0.75 1. ]
# 方式6:随机数组(最常用)
rand_uniform = np.random.rand(3, 4) # 0~1均匀分布
rand_int = np.random.randint(0, 10, (3, 4)) # 0~10整数随机
randn = np.random.randn(3, 4) # 标准正态分布(均值0方差1)
print(f"随机整数数组:\\n{rand_int}")
💡注意事项: np.arange() 的区间是左闭右开 [start, stop) ,而 np.linspace() 是左闭右闭 [st
art, stop] 。
1.4 数组的关键属性
每个NumPy数组都有以下重要属性,理解它们对于数组的操作可谓是必不可少:
a = np.array([[1, 2, 3], [4, 5, 6]])
print(f"形状 (shape):{a.shape}") # (2, 3) – 2行3列
print(f"维度数 (ndim):{a.ndim}") # 2 – 二维数组
print(f"数据类型 (dtype):{a.dtype}") # int64 – 64位整数
print(f"元素总数 (size):{a.size}") # 6 – 共6个元素
print(f"单个元素字节数 (itemsize):{a.itemsize}") # 8
print(f"数组总字节数 (nbytes):{a.nbytes}") # 48
1.5 数据类型详解
NumPy支持多种数据类型,合理选择可以节省内存:
| dtype | 说明 | 字节数 | 典型用途 |
| int32 | 32位整数 | 4 | 一般整数运算 |
| int64 | 64位整数 | 8 | 大数值统计 |
| float32 | 单精度浮点 | 4 | 内存敏感场景 |
| float | 双精度浮点 | 8 | 精度要求高 |
| bool | 布尔类型 | 1 | 条件判断 |
| boject | Python对象 | 可变 | 混合类型存储 |
# 指定数据类型
arr1 = np.array([1, 2, 3], dtype=np.float32)
arr2 = np.array([1, 2, 3], dtype=np.float64)
print(f"float32内存:{arr1.nbytes}字节") # 12
print(f"float64内存:{arr2.nbytes}字节") # 24
2、数组索引与切片
2.1 一维数组索引基础
NumPy数组的索引方式与 Python 列表类似,但功能强大。索引基础规则:
- 正向索引:从0开始,a[0] 是第一个元素
- 负向索引:从-1开始,a[-1] 是最后一个元素
- 切片:a[start:stop:step],遵循左闭右开原则
a = np.arange(10) # 创建 [0 1 2 3 4 5 6 7 8 9]
print(f"原数组:{a}")
# 正向索引
print(f"a[0] = {a[0]}") # 0
print(f"a[5] = {a[5]}") # 5
# 负向索引
print(f"a[-1] = {a[-1]}") # 9
print(f"a[-3] = {a[-3]}") # 7
# 切片操作
print(f"a[2:7] = {a[2:7]}") # [2 3 4 5 6] – 第3到第7个元素
print(f"a[:5] = {a[:5]}") # [0 1 2 3 4] – 从头到第5个
print(f"a[5:] = {a[5:]}") # [5 6 7 8 9] – 从第6个到末尾
# 步长切片
print(f"a[::2] = {a[::2]}") # [0 2 4 6 8] – 步长2
print(f"a[::3] = {a[::3]}") # [0 3 6 9] – 步长3
print(f"a[::-1] = {a[::-1]}") # [9 8 7 6 5 4 3 2 1 0] – 完全反转
2.2 二维数组索引
二维数组的索引需要同时指定行和列,语法为 array[row, col]:
b = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
print(f"原数组:\\n{b}")
# 单个元素索引
print(f"b[1, 2] = {b[1, 2]}") # 6 – 第2行第3列
# 行索引
print(f"b[0, :] = {b[0, :]}") # [1 2 3] – 第1行所有列
print(f"b[1] = {b[1]}") # [4 5 6] – 第2行(省略写法)
# 列索引
print(f"b[:, 1] = {b[:, 1]}") # [2 5 8] – 第2列所有行
# 子矩阵切片
print(f"b[0:2, 0:2] = \\n{b[0:2, 0:2]}")
# [[1 2]
# [4 5]]
# 跳行跳列
print(f"b[::2, ::2] = \\n{b[::2, ::2]}")
# [[1 3]
# [7 9]]
2.3 布尔索引
布尔索引是 NumPy 里面最强大的特征之一,它允许我们根据条件筛选数组元素:
a = np.array([10, 20, 30, 40, 50])
print(f"原数组:{a}")
# 创建布尔掩码
mask = a > 30
print(f"a > 30 的掩码:{mask}") # [False False False True True]
# 使用掩码筛选
result = a[mask]
print(f"a[a > 30] = {result}") # [40 50]
# 一行写法(最常用)
print(f"a[a > 25] = {a[a > 25]}") # [30 40 50]
💡核心应用场景:在数据分析中,布尔索引用于数据清洗、异常值检测、条件筛选等场景。
实际应用:
# 场景:筛选价格大于150的商品
prices = np.array([99, 199, 299, 399, 149])
print(f"高价商品价格:{prices[prices > 150]}") # [199 299 399]
# 场景:筛选成绩及格的学生
scores = np.array([45, 78, 92, 63, 88, 55, 76])
print(f"及格成绩:{scores[scores >= 60]}") # [78 92 63 88 76]
# 复合条件
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
# 找出大于3且小于8的数
result = a[(a > 3) & (a < 8)]
print(f"大于3且小于8:{result}") # [4 5 6 7]
💡注意:在NumPy中进行复合条件筛选时,必须使用 & (按位与)而不是 and (Python逻辑与),因为NumPy操作的是数组而不是单个值。
2.4 花式索引
花式索引(Fancy Indexing)使用整数数组作为索引,可以实现任意顺序、任意位置的元素选取:
a = np.arange(10) # [0 1 2 3 4 5 6 7 8 9]
# 使用整数数组指定索引位置
indices = [0, 2, 4, 6]
print(f"a[{indices}] = {a[indices]}") # [0 2 4 6]
# 不按顺序选取
print(f"a[[3, 0, 5]] = {a[[3, 0, 5]]}") # [3 0 5]
# 二维花式索引
b = np.arange(12).reshape(3, 4)
print(f"原数组:\\n{b}")
# 选取特定行
print(f"b[[0, 2], :] = \\n{b[[0, 2], :]}") # 选取第1行和第3行,因为下标从0开始所以是0和2
3、数组运算与聚合
3.1 逐元素运算
NumPy的核心优势之一是支持向量化运算,无需循环即可对数组的每个元素进行数学运算:
a = np.array([1, 2, 3, 4, 5])
# 基本算术运算
print(f"a + 10 = {a + 10}") # [11 12 13 14 15]
print(f"a – 5 = {a – 5}") # [-4 -3 -2 -1 0]
print(f"a * 2 = {a * 2}") # [2 4 6 8 10]
print(f"a / 2 = {a / 2}") # [0.5 1. 1.5 2. 2.5]
print(f"a ** 2 = {a ** 2}") # [1 4 9 16 25]
print(f"a % 2 = {a % 2}") # [1 0 1 0 1] – 取模
# 比较运算(布尔索引)
print(f"a > 3 = {a > 3}") # [False False False True True]
print(f"a == 3 = {a == 3}") # [False False True False False]
💡向量化优势:使用向量化运算比Python循环快10-100倍,因为NumPy在底层使用了SIMD指令集优化。
3.2 数组间运算
两个形状相同的数组可以进行逐元素运算:
a = np.array([1, 2, 3, 4])
b = np.array([10, 20, 30, 40])
print(f"a + b = {a + b}") # [11 22 33 44]
print(f"a * b = {a * b}") # [10 40 90 160]
print(f"b – a = {b – a}") # [9 18 27 36]
3.3 广播机制(Boardcasting)
广播 NumPy 最强大的特征之一,它允许不同形状的数组进行运算:
# 一维数组与二维数组广播
c = np.array([
[1, 2, 3],
[4, 5, 6]
])
d = np.array([10, 20, 30])
print(f"c + d = \\n{c + d}")
# [[11 22 33]
# [14 25 36]]
# 标量与数组广播
print(f"c * 2 = \\n{c * 2}")
# [[2 4 6]
# [8 10 12]]
💡广播规则:当两个数组的形状不同时,NumPy会从后向前比较维度,如果维度相同或其中一个为1,则可以广播。
3.4 聚合函数
NumPy 提供了丰富的聚合函数,用于统计计算:
arr = np.array([1, 2, 3, 4, 5])
# 基本统计
print(f"总和 sum = {arr.sum()}") # 15
print(f"均值 mean = {arr.mean()}") # 3.0
print(f"最大值 max = {arr.max()}") # 5
print(f"最小值 min = {arr.min()}") # 1
print(f"标准差 std = {arr.std():.4f}") # 1.4142
print(f"方差 var = {arr.var():.4f}") # 2.0000
# 累积函数
print(f"累加 cumsum = {arr.cumsum()}") # [1 3 6 10 15]
print(f"累乘 cumprod= {arr.cumprod()}") # [1 2 6 24 120]
3.5 多维数组聚合(轴向)
对于多维数组,可以通过指定 axis 参数沿特定轴进行聚合:
m = np.arange(12).reshape(3, 4)
print(f"原数组:\\n{m}")
# 按列聚合(axis=0)
print(f"每列求和 (axis=0):{m.sum(axis=0)}") #[12 15 18 21]
# 按行聚合(axis=1)
print(f"每行求和 (axis=1):{m.sum(axis=1)}") # [ 6 22 38]
# 其他轴向聚合
print(f"每列最大值:{m.max(axis=0)}") # [ 8 9 10 11]
print(f"每行平均值:{m.mean(axis=1)}") # [1.5 5.5 9.5]
💡参数提示:axis=1表示行,axis=0表示列
网硕互联帮助中心





评论前必须登录!
注册