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

使用Z-Score移除pandas数据框异常值,处理百分比变化后得空数据框?

问题根源和解决方案

先给你说清楚为啥用pct_change()后跑z-score会得到空数据框:

  • pct_change()生成的第一行是NaN(因为没有前一行数据计算变化率),stats.zscore()碰到NaN会返回NaN,而NaN < 1.5的结果是False,这行直接被过滤。
  • 如果原始数据里有0或者极小值,计算百分比变化时会出现极大值甚至无穷大(比如从0涨到0.1,变化率是无穷大),这些值的z-score会大到离谱,远超过你设置的任何阈值,导致所有行的条件np.abs(stats.zscore(df[0])) < 1.5都不满足,最后就得到空数据框。

解决步骤

1. 先清理NaN和无穷值

先把pct_change()产生的无效值处理掉:

import pandas as pd
import numpy as np
from scipy import stats

# 模拟你的原始数据
df = pd.DataFrame(np.random.randn(100, 3))
# 计算百分比变化
df_pct = df.pct_change()
# 替换无穷大值为NaN,再删掉所有包含NaN的行
df_pct_clean = df_pct.replace([np.inf, -np.inf], np.nan).dropna()

2. 用更稳健的方法过滤异常值(替代z-score)

z-score基于均值和标准差,对极端值特别敏感,而百分比变化数据本身就容易出极端值,建议用中位数绝对偏差(MAD),它对异常值的耐受力更强:

def mad_based_outlier(data, threshold=3.5):
    median = np.median(data)
    mad = np.median(np.abs(data - median))
    modified_z_score = 0.6745 * (data - median) / mad
    return np.abs(modified_z_score) > threshold

# 对第一列过滤异常值(~表示取反,保留非异常值)
df_filtered = df_pct_clean[~mad_based_outlier(df_pct_clean[0])]

如果非要用z-score,得先把极端的超大值提前过滤,再调整阈值(效果不如MAD稳定):

# 先去掉变化率绝对值超过合理范围的行(比如>10,根据你的数据调整)
df_pct_clean = df_pct_clean[np.abs(df_pct_clean[0]) < 10]
# 再用z-score过滤
df_filtered = df_pct_clean[np.abs(stats.zscore(df_pct_clean[0])) < 3]

3. 验证结果

跑代码后可以查看过滤后的数据规模:

print(df_filtered.shape)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 16:55:11