我有一个很少列的熊猫数据帧。

现在我知道某些行是基于某个列值的异常值。

例如

列“Vol”的所有值都在12xx左右,其中一个值是4000(离群值)。

现在我想排除那些Vol列像这样的行。

所以,本质上,我需要在数据帧上放一个过滤器,这样我们就可以选择所有的行,其中某一列的值距离平均值在3个标准差之内。

实现这一点的优雅方式是什么?


当前回答

像在numpy.array中那样使用布尔索引

df = pd.DataFrame({'Data':np.random.normal(size=200)})
# example dataset of normally distributed data. 

df[np.abs(df.Data-df.Data.mean()) <= (3*df.Data.std())]
# keep only the ones that are within +3 to -3 standard deviations in the column 'Data'.

df[~(np.abs(df.Data-df.Data.mean()) > (3*df.Data.std()))]
# or if you prefer the other way around

对于一个系列,它是类似的:

S = pd.Series(np.random.normal(size=200))
S[~((S-S.mean()).abs() > 3*S.std())]

其他回答

像在numpy.array中那样使用布尔索引

df = pd.DataFrame({'Data':np.random.normal(size=200)})
# example dataset of normally distributed data. 

df[np.abs(df.Data-df.Data.mean()) <= (3*df.Data.std())]
# keep only the ones that are within +3 to -3 standard deviations in the column 'Data'.

df[~(np.abs(df.Data-df.Data.mean()) > (3*df.Data.std()))]
# or if you prefer the other way around

对于一个系列,它是类似的:

S = pd.Series(np.random.normal(size=200))
S[~((S-S.mean()).abs() > 3*S.std())]

把98和2百分位作为离群值的极限

upper_limit = np.percentile(X_train.logerror.values, 98) 
lower_limit = np.percentile(X_train.logerror.values, 2) # Filter the outliers from the dataframe
data[‘target’].loc[X_train[‘target’]>upper_limit] = upper_limit data[‘target’].loc[X_train[‘target’]<lower_limit] = lower_limit

删除至少一列中有异常值的所有行

如果你的数据框架中有多列,并且想要删除至少一列中有异常值的所有行,下面的表达式可以一次性完成:

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


df = pd.DataFrame(np.random.randn(100, 3))

df[(np.abs(stats.zscore(df)) < 3).any(axis=1)]

描述:

中的每个列,它首先计算每个值的z分数 列,相对于列的均值和标准差。 然后取绝对z分数,因为方向没有 物质,只有当它低于阈值时。 All(轴=1)确保对于每一行,所有列都满足 约束。 最后,这个条件的结果被用于索引数据帧。

基于单个列筛选其他列

为zscore指定一列,例如df[0],并删除.all(axis=1)。

df[(np.abs(stats.zscore(df[0])) < 3)]

我喜欢夹而不喜欢掉。以下将夹在第2和98分频。

df_list = list(df)
minPercentile = 0.02
maxPercentile = 0.98

for _ in range(numCols):
    df[df_list[_]] = df[df_list[_]].clip((df[df_list[_]].quantile(minPercentile)),(df[df_list[_]].quantile(maxPercentile)))

这个答案类似于@tanemaki提供的答案,但使用了lambda表达式而不是scipy stats。

df = pd.DataFrame(np.random.randn(100, 3), columns=list('ABC'))

standard_deviations = 3
df[df.apply(lambda x: np.abs(x - x.mean()) / x.std() < standard_deviations)
   .all(axis=1)]

要过滤只有一个列的数据帧(例如:B)在三个标准差之内:

df[((df['B'] - df['B'].mean()) / df['B'].std()).abs() < standard_deviations]

关于如何在滚动的基础上应用这个z-score:滚动z-score应用于pandas数据框架