2. Python数据分析基础回顾:NumPy数组操作、Pandas DataFrame基础、数据清洗与缺失值处理
在构建异常检测与实时监控大屏之前,必须夯实Python数据分析的核心基础。本章将系统回顾NumPy数组操作、Pandas DataFrame基础以及数据清洗与缺失值处理三大模块,为后续的时序数据处理、统计建模与可视化输出奠定坚实的技术底座。
2.1 NumPy数组操作
NumPy是Python科学计算的基石,其核心数据结构ndarray提供了高效的向量化运算能力。在异常检测场景中,NumPy常用于滑动窗口计算、统计特征提取与矩阵运算。
2.1.1 数组创建与基本属性
| 方法 | 说明 | 示例 |
|---|---|---|
np.array() |
从列表或元组创建数组 | np.array([1,2,3]) |
np.zeros() |
创建全零数组 | np.zeros((3,4)) |
np.ones() |
创建全一数组 | np.ones((2,3)) |
np.arange() |
创建等差序列 | np.arange(0,10,2) |
np.random.randn() |
标准正态分布随机数 | np.random.randn(100) |
关键属性:ndim(维度)、shape(形状)、dtype(数据类型)、size(元素总数)。
2.1.2 向量化运算与广播机制
向量化运算是NumPy性能的核心优势,避免使用Python原生循环。广播机制允许不同形状的数组进行算术运算。
import numpy as np
# 向量化运算
data = np.array([10, 20, 30, 40, 50])
normalized = (data - data.mean()) / data.std()
# 广播机制
matrix = np.ones((4, 3))
row_mean = np.array([1, 2, 3])
result = matrix * row_mean # 每行乘以row_mean
# 条件筛选(异常检测常用)
threshold = 35
outliers = data[data > threshold]
print(outliers) # [40 50]
2.1.3 统计函数与聚合操作
异常检测中频繁使用NumPy的统计函数计算数据的分布特征。
| 函数 | 说明 | 异常检测用途 |
|---|---|---|
np.mean() |
均值 | 中心趋势度量 |
np.std() |
标准差 | 离散程度度量 |
np.percentile() |
百分位数 | 箱线图异常阈值 |
np.median() |
中位数 | 稳健中心估计 |
np.diff() |
差分 | 突变检测 |
实战提示:在实时监控场景中,使用np.lib.stride_tricks.sliding_window_view()可以高效生成滑动窗口数据,用于计算滚动统计量。
2.2 Pandas DataFrame基础
Pandas是数据分析的核心工具,DataFrame作为二维表格数据结构,天然适配时间序列监控数据的存储与操作。在异常检测大屏中,DataFrame负责数据加载、切片、聚合与可视化准备。
2.2.1 DataFrame创建与基本操作
import pandas as pd
import numpy as np
# 从字典创建DataFrame
df = pd.DataFrame({
'timestamp': pd.date_range('2024-01-01', periods=5, freq='H'),
'cpu_usage': [45.2, 67.8, 92.1, 55.3, 78.9],
'memory_usage': [60.1, 72.5, 88.3, 65.4, 81.2],
'disk_io': [120, 340, 560, 210, 430]
})
# 查看基本信息
print(df.info())
print(df.describe())
# 列选择与过滤
high_cpu = df[df['cpu_usage'] > 80]
print(high_cpu)
2.2.2 索引操作与时间序列
时间序列索引是监控数据的核心特征,Pandas提供了强大的时间索引操作能力。
| 操作 | 方法 | 示例 |
|---|---|---|
| 设置时间索引 | set_index() |
df.set_index('timestamp') |
| 时间范围切片 | loc[] |
df.loc['2024-01-01 02:00':'2024-01-01 04:00'] |
| 重采样 | resample() |
df.resample('10min').mean() |
| 滚动窗口 | rolling() |
df['cpu_usage'].rolling(3).mean() |
注意:时间索引必须为DatetimeIndex类型,否则切片和重采样会失败。使用pd.to_datetime()进行类型转换。
2.2.3 分组聚合与多维度分析
在监控大屏中,经常需要按主机、服务或地域进行分组统计。
# 模拟多主机数据
df_multi = pd.DataFrame({
'host': ['server-A']*3 + ['server-B']*3 + ['server-C']*3,
'cpu': np.random.uniform(30, 95, 9),
'mem': np.random.uniform(40, 90, 9)
})
# 分组聚合
grouped = df_multi.groupby('host').agg({
'cpu': ['mean', 'max', 'std'],
'mem': ['mean', 'max', 'std']
})
print(grouped)
2.3 数据清洗与缺失值处理
真实监控数据往往存在缺失值、异常值和重复记录。数据清洗是异常检测的前置步骤,直接影响模型准确性与大屏展示效果。
2.3.1 缺失值检测与统计
# 创建含缺失值的示例数据
df_raw = pd.DataFrame({
'time': pd.date_range('2024-01-01', periods=10, freq='5min'),
'cpu': [45.2, np.nan, 67.8, 92.1, np.nan, 55.3, 78.9, 88.2, np.nan, 62.4],
'mem': [60.1, 72.5, np.nan, 88.3, 65.4, np.nan, 81.2, 75.6, 90.1, 68.7]
})
# 缺失值检测
print(df_raw.isnull().sum())
print(df_raw.isnull().mean() * 100) # 缺失比例
2.3.2 缺失值处理策略
| 策略 | 方法 | 适用场景 | 代码示例 |
|---|---|---|---|
| 删除缺失行 | dropna() |
缺失比例低(<5%) | df.dropna() |
| 固定值填充 | fillna() |
已知默认值 | df.fillna(0) |
| 均值/中位数填充 | fillna() |
数值型数据 | df.fillna(df.mean()) |
| 前向填充 | ffill() |
时间序列 | df.ffill() |
| 后向填充 | bfill() |
时间序列 | df.bfill() |
| 插值法 | interpolate() |
平滑趋势数据 | df.interpolate() |
最佳实践:在实时监控场景中,优先使用前向填充(ffill())处理短暂缺失,因为监控数据通常具有时间连续性;对于长时间缺失,建议标记为异常而非填充。
2.3.3 异常值检测与处理
异常值检测是数据清洗的重要环节,常用方法包括Z-score和IQR(四分位距)法。
# Z-score方法
from scipy import stats
z_scores = np.abs(stats.zscore(df_raw['cpu'].dropna()))
threshold = 3
outliers_z = df_raw['cpu'][z_scores > threshold]
# IQR方法
Q1 = df_raw['cpu'].quantile(0.25)
Q3 = df_raw['cpu'].quantile(0.75)
IQR = Q3 - Q1
lower_bound = Q1 - 1.5 * IQR
upper_bound = Q3 + 1.5 * IQR
outliers_iqr = df_raw['cpu'][(df_raw['cpu'] < lower_bound) | (df_raw['cpu'] > upper_bound)]
print(f"Z-score异常值: {outliers_z.tolist()}")
print(f"IQR异常值: {outliers_iqr.tolist()}")
2.3.4 重复数据处理
# 检测与删除重复行
df_dup = df_raw.append(df_raw.iloc[0]) # 模拟重复
print(f"重复行数: {df_dup.duplicated().sum()}")
df_clean = df_dup.drop_duplicates()
# 基于特定列去重
df_clean_col = df_dup.drop_duplicates(subset=['time'])
实战案例:在CPU监控数据中,若某时间点缺失值超过连续3个采样点,建议标记为“数据中断”异常,而非简单填充。这有助于区分传感器故障与真实负载波动。
2.4 综合实战:监控数据预处理流水线
将上述知识点整合为一条完整的监控数据预处理流水线,为后续异常检测模型提供干净、规范的数据输入。
def preprocess_monitor_data(df, time_col='timestamp', value_cols=None):
"""
监控数据预处理流水线
参数:
df: 原始DataFrame
time_col: 时间列名
value_cols: 需要处理的数值列列表
返回:
清洗后的DataFrame
"""
if value_cols is None:
value_cols = df.select_dtypes(include=[np.number]).columns.tolist()
# 1. 时间列处理
df[time_col] = pd.to_datetime(df[time_col])
df = df.set_index(time_col).sort_index()
# 2. 缺失值处理(前向填充,限制连续填充3个)
for col in value_cols:
df[col] = df[col].ffill(limit=3)
# 3. 异常值处理(IQR方法)
for col in value_cols:
Q1 = df[col].quantile(0.25)
Q3 = df[col].quantile(0.75)
IQR = Q3 - Q1
lower = Q1 - 1.5 * IQR
upper = Q3 + 1.5 * IQR
df[col] = df[col].clip(lower, upper)
# 4. 重复索引处理
df = df[~df.index.duplicated(keep='first')]
return df.reset_index()
# 使用示例
df_clean = preprocess_monitor_data(df_raw)
print(df_clean.head())
生产环境注意:上述流水线适用于离线批处理场景。在实时监控大屏中,建议使用流式处理框架(如Kafka + Flink)配合Pandas进行微批次清洗,避免全量数据重算。