4. NumPy 入门:数组创建、数组运算、索引与切片、常用统计函数

NumPy(Numerical Python)是 Python 数据科学生态系统的核心库,提供了高性能的多维数组对象和丰富的数学运算工具。在实时监控大屏场景中,NumPy 负责底层数据的批量计算、统计聚合和预处理,是连接原始数据与可视化图表的桥梁。

学习目标:掌握 NumPy 数组的创建方法、矢量化运算、灵活的索引与切片操作,以及常用的统计函数,为后续 Pandas 数据处理和监控指标计算打下基础。

4.1 NumPy 数组创建

NumPy 的核心数据结构是 ndarray(N 维数组)。创建数组是使用 NumPy 的第一步,以下是几种最常用的创建方式:

创建方式 函数/语法 示例 结果
从列表转换 np.array(list) np.array([1, 2, 3]) array([1, 2, 3])
全零数组 np.zeros(shape) np.zeros((2, 3)) 2行3列全0矩阵
全一数组 np.ones(shape) np.ones((2, 2)) 2行2列全1矩阵
单位矩阵 np.eye(N) np.eye(3) 3x3 单位矩阵
等差数列 np.arange(start, stop, step) np.arange(0, 10, 2) array([0, 2, 4, 6, 8])
等间隔数列 np.linspace(start, stop, num) np.linspace(0, 1, 5) array([0., 0.25, 0.5, 0.75, 1.])
随机数组 np.random.randn(d0, d1) np.random.randn(2, 3) 2x3 标准正态分布随机数
import numpy as np

# 从列表创建一维数组
arr1 = np.array([10, 20, 30, 40, 50])
print("一维数组:", arr1)

# 创建二维数组(矩阵)
arr2 = np.array([[1, 2, 3], [4, 5, 6]])
print("二维数组:\n", arr2)

# 创建全零数组,用于初始化监控指标缓存
zero_cache = np.zeros((3, 4))
print("全零缓存矩阵:\n", zero_cache)

# 创建等差数列,用于生成时间轴
time_axis = np.arange(0, 60, 5)  # 0到55秒,步长5秒
print("时间轴(秒):", time_axis)

# 创建随机数组,模拟传感器数据
sensor_data = np.random.randn(100)  # 100个标准正态分布随机数
print("模拟传感器数据(前5个):", sensor_data[:5])
监控场景应用:在实时监控大屏中,np.zeros 常用于初始化指标缓存矩阵,np.arange 用于生成时间序列的横轴刻度,np.random.randn 可用于模拟测试数据或生成随机噪声。
NumPy 数组创建方式概览 np.array() 从列表/元组转换 zeros / ones / eye arange / linspace random.randn / rand 数组创建是 NumPy 数据处理的起点,不同场景选择不同的创建方式

4.2 数组运算

NumPy 最强大的特性之一是矢量化运算——无需编写循环,即可对整个数组执行元素级运算。这在大屏实时计算中能显著提升性能。

4.2.1 算术运算

import numpy as np

a = np.array([10, 20, 30, 40])
b = np.array([1, 2, 3, 4])

# 元素级运算
print("加法:", a + b)        # [11 22 33 44]
print("减法:", a - b)        # [9 18 27 36]
print("乘法:", a * b)        # [10 40 90 160]
print("除法:", a / b)        # [10. 10. 10. 10.]
print("幂运算:", a ** 2)     # [100 400 900 1600]

# 标量与数组运算
print("标量加法:", a + 100)  # [110 120 130 140]
print("标量乘法:", a * 2)    # [20 40 60 80]

4.2.2 广播机制

广播(Broadcasting)允许不同形状的数组进行运算,NumPy 会自动扩展较小数组的维度。这在处理监控数据时非常实用,例如将一组阈值与多维数据进行比较。

# 广播示例:二维数组与一维数组相加
matrix = np.array([[1, 2, 3],
                   [4, 5, 6],
                   [7, 8, 9]])
row_vector = np.array([10, 20, 30])

result = matrix + row_vector
print("广播加法结果:\n", result)
# [[11 22 33]
#  [14 25 36]
#  [17 28 39]]
广播规则要点:从尾部维度开始比较,维度大小相同或其中一个为 1 时才能广播。如果维度不匹配且都不为 1,则会抛出 ValueError。
NumPy 广播机制示意图 矩阵 (3x3) [[1, 2, 3], [4, 5, 6], [7, 8, 9]] + 行向量 [10,20,30] = 广播结果 (3x3) [[11, 22, 33], [14, 25, 36], [17, 28, 39]] 行向量沿行方向广播 广播规则:从尾部维度比较,维度为1或相等时可自动扩展 避免显式循环,提升监控数据批量处理性能

4.3 索引与切片

NumPy 的索引与切片语法与 Python 列表类似,但功能更强大,支持多维索引和布尔索引。在监控大屏中,切片用于提取特定时间窗口的数据,布尔索引用于条件过滤。

4.3.1 基本索引与切片

import numpy as np

arr = np.array([10, 20, 30, 40, 50, 60])

# 基本索引
print("索引第3个元素:", arr[2])       # 30

# 切片 [start:stop:step]
print("切片 1~4:", arr[1:4])          # [20 30 40]
print("步长为2:", arr[::2])           # [10 30 50]
print("反向切片:", arr[::-1])         # [60 50 40 30 20 10]

# 二维数组切片
matrix = np.array([[1, 2, 3, 4],
                   [5, 6, 7, 8],
                   [9, 10, 11, 12]])

print("第2行:", matrix[1, :])         # [5 6 7 8]
print("第3列:", matrix[:, 2])         # [3 7 11]
print("子矩阵(前2行, 第2~3列):\n", matrix[:2, 1:3])
# [[2 3]
#  [6 7]]

4.3.2 布尔索引

布尔索引是 NumPy 最灵活的筛选方式,通过条件表达式生成布尔数组,再作为索引使用。

# 布尔索引示例
data = np.array([12, 25, 8, 35, 18, 42, 30])

# 筛选大于20的元素
mask = data > 20
print("布尔掩码:", mask)              # [False  True False  True False  True  True]
print("大于20的数据:", data[mask])    # [25 35 42 30]

# 组合条件:大于15且小于35
filtered = data[(data > 15) & (data < 35)]
print("15~35之间的数据:", filtered)   # [25 18 30]

# 将满足条件的元素替换为0
data[data < 20] = 0
print("替换后:", data)               # [ 0 25  0 35  0 42 30]
监控场景应用:布尔索引可用于实时过滤异常数据。例如,筛选 CPU 使用率超过 90% 的节点,或找出响应时间超过阈值的请求记录。
NumPy 索引与切片操作流程 原始数组 [10, 20, 30, 40, 50] 索引: 0 1 2 3 4 基本索引 arr[2] → 30 arr[1:4] → [20,30,40] 布尔索引 mask = arr > 25 arr[mask] → [30,40,50] 筛选结果 切片使用 [start:stop:step] 语法,支持多维切片 布尔索引通过条件表达式生成掩码,实现灵活的数据筛选 监控场景:时间窗口切片提取、异常数据布尔过滤、多维指标子集选取 例如:data[last_5_minutes] 或 data[data > threshold]

4.4 常用统计函数

NumPy 提供了丰富的统计函数,用于描述数据的集中趋势、离散程度和分布特征。这些函数是监控指标计算的核心工具。

函数 说明 示例 监控场景
np.mean() 计算平均值 np.mean(data) 平均响应时间
np.median() 计算中位数 np.median(data) 请求延迟中位数
np.std() 计算标准差 np.std(data) 性能波动程度
np.var() 计算方差 np.var(data) 数据离散度
np.min() 最小值 np.min(data) 最低延迟
np.max() 最大值 np.max(data) 峰值负载
np.percentile() 计算百分位数 np.percentile(data, 95) P95 延迟监控
np.sum() 求和 np.sum(data) 总请求数
np.cumsum() 累积和 np.cumsum(data) 累计流量曲线
import numpy as np

# 模拟监控数据:100个请求的响应时间(毫秒)
response_times = np.random.exponential(scale=50, size=100)

# 核心统计指标
mean_rt = np.mean(response_times)
median_rt = np.median(response_times)
std_rt = np.std(response_times)
min_rt = np.min(response_times)
max_rt = np.max(response_times)
p95_rt = np.percentile(response_times, 95)
p99_rt = np.percentile(response_times, 99)

print(f"平均响应时间: {mean_rt:.2f} ms")
print(f"中位数响应时间: {median_rt:.2f} ms")
print(f"标准差: {std_rt:.2f} ms")
print(f"最小值: {min_rt:.2f} ms")
print(f"最大值: {max_rt:.2f} ms")
print(f"P95 延迟: {p95_rt:.2f} ms")
print(f"P99 延迟: {p99_rt:.2f} ms")

# 沿指定轴统计(适用于多维数据)
# 假设有3个服务节点,每个节点有10个采样点
node_data = np.random.randn(3, 10)  # 3行10列
node_means = np.mean(node_data, axis=1)  # 每个节点的均值
node_stds = np.std(node_data, axis=1)    # 每个节点的标准差
print("各节点均值:", node_means)
print("各节点标准差:", node_stds)
性能提示:NumPy 的统计函数都是经过 C 语言优化的,比 Python 原生循环快 10~100 倍。在实时监控大屏中,应尽量使用 NumPy 函数进行批量计算,避免逐元素循环。
NumPy 常用统计函数分类 原始数据 集中趋势 mean / median / percentile 离散程度 std / var / min / max 累积统计 sum / cumsum / cumprod 统计函数支持 axis 参数,可沿指定维度计算 监控大屏中常用 mean/std/percentile 描述系统性能特征

4.5 综合案例:监控指标计算

将本章知识点串联起来,实现一个简单的监控指标计算模块:

import numpy as np

class MonitorMetrics:
    """监控指标计算器"""

    def __init__(self, window_size=60):
        self.window_size = window_size
        self.data_buffer = np.zeros(window_size)

    def update(self, new_value):
        """更新数据缓冲区(滑动窗口)"""
        self.data_buffer = np.roll(self.data_buffer, -1)
        self.data_buffer[-1] = new_value

    def compute_metrics(self):
        """计算当前窗口的统计指标"""
        return {
            'mean': np.mean(self.data_buffer),
            'median': np.median(self.data_buffer),
            'std': np.std(self.data_buffer),
            'min': np.min(self.data_buffer),
            'max': np.max(self.data_buffer),
            'p95': np.percentile(self.data_buffer, 95),
            'p99': np.percentile(self.data_buffer, 99),
            'sum': np.sum(self.data_buffer)
        }

    def detect_anomaly(self, threshold=2.0):
        """基于标准差检测异常值"""
        mean = np.mean(self.data_buffer)
        std = np.std(self.data_buffer)
        z_scores = (self.data_buffer - mean) / std
        anomalies = np.abs(z_scores) > threshold
        return anomalies, self.data_buffer[anomalies]

# 模拟实时数据流
metrics = MonitorMetrics(window_size=30)
for i in range(50):
    # 模拟传感器读数,偶尔出现异常值
    if i % 10 == 5:
        value = 100.0  # 异常值
    else:
        value = np.random.normal(50, 10)
    metrics.update(value)

# 计算并输出指标
result = metrics.compute_metrics()
print("当前窗口统计指标:")
for key, val in result.items():
    print(f"  {key}: {val:.2f}")

# 检测异常
anomaly_mask, anomaly_values = metrics.detect_anomaly(threshold=2.0)
print(f"\n检测到 {len(anomaly_values)} 个异常值:")
print(anomaly_values)
案例要点:
  • 数组创建:使用 np.zeros 初始化固定大小的滑动窗口缓冲区
  • 数组运算:使用 np.roll 实现数据移位,z_scores 计算使用矢量化运算
  • 索引与切片:通过布尔索引筛选异常值
  • 统计函数:综合使用 mean、std、percentile 等函数计算监控指标