You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pandas DataFrame中用最近正常点均值替换z-score超阈值离群值

实现逻辑

核心思路是先标记离群值为临时NaN,再通过前后向填充获取最近非离群值计算均值,同时保留原始NaN不被修改。

  • 第一步:先记录原始数据中value列为NaN的位置,避免后续填充操作修改原始缺失值
  • 第二步:筛选出符合条件的离群值(绝对z-score≥3,且原始value不是NaN),将这些离群值的value临时设为NaN
  • 第三步:分别对临时NaN的value列做向前填充(取最近的前序非离群值)和向后填充(取最近的后序非离群值),两者取均值作为替换值
  • 第四步:把第一步记录的原始NaN位置的value恢复为NaN,保证原始缺失值不变

代码示例

import pandas as pd
import scipy.stats

# 需保证df已经按TimeStamp升序排序
# 备份原始NaN的位置
raw_na_mask = df['value'].isna()

# 计算z-score,跳过原始NaN避免影响统计结果
df['zscore'] = scipy.stats.zscore(df['value'], nan_policy='omit')

# 标记离群值:绝对zscore≥3 且 不属于原始NaN
outlier_mask = (df['zscore'].abs() >= 3) & (~raw_na_mask)

# 将离群值临时设为NaN方便后续填充
df.loc[outlier_mask, 'value'] = pd.NA

# 计算前后最近非离群值的均值
ffill_vals = df['value'].ffill()
bfill_vals = df['value'].bfill()
df['value'] = (ffill_vals + bfill_vals) / 2

# 恢复原始NaN,保证原始缺失值不被修改
df.loc[raw_na_mask, 'value'] = pd.NA

# 得到最终结果,删除辅助计算的zscore列
df_mod = df.drop(columns=['zscore'])

效果验证

你给出的示例中,离群值为2021-01-03、2021-01-04,临时设为NaN后:

  • 向前填充得到两个位置的值都是前序最近的非离群值5
  • 向后填充得到两个位置的值都是后序最近的非离群值7
  • 均值为(5+7)/2=6,和你期望的输出结果完全一致

边界场景说明

如果离群值出现在序列最开头,没有前序非离群值,此时向前填充结果为NaN,均值会自动取后向填充的结果;同理出现在序列末尾时会自动取前向填充的结果,无需额外处理。

内容的提问来源于stack exchange,提问作者kspr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 06:48:00