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

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

例如

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

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

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

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


当前回答

由于我正处于我的数据科学之旅的早期阶段,我使用下面的代码来处理异常值。

#Outlier Treatment

def outlier_detect(df):
    for i in df.describe().columns:
        Q1=df.describe().at['25%',i]
        Q3=df.describe().at['75%',i]
        IQR=Q3 - Q1
        LTV=Q1 - 1.5 * IQR
        UTV=Q3 + 1.5 * IQR
        x=np.array(df[i])
        p=[]
        for j in x:
            if j < LTV or j>UTV:
                p.append(df[i].median())
            else:
                p.append(j)
        df[i]=p
    return df

其他回答

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

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

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)]

这个答案类似于@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数据框架

去掉离群值的函数

def drop_outliers(df, field_name):
    distance = 1.5 * (np.percentile(df[field_name], 75) - np.percentile(df[field_name], 25))
    df.drop(df[df[field_name] > distance + np.percentile(df[field_name], 75)].index, inplace=True)
    df.drop(df[df[field_name] < np.percentile(df[field_name], 25) - distance].index, inplace=True)

下面是一个包含数据和2组的完整示例:

进口:

from StringIO import StringIO
import pandas as pd
#pandas config
pd.set_option('display.max_rows', 20)

有2个组的数据示例:G1:Group 1。G2:第二组:

TESTDATA = StringIO("""G1;G2;Value
1;A;1.6
1;A;5.1
1;A;7.1
1;A;8.1

1;B;21.1
1;B;22.1
1;B;24.1
1;B;30.6

2;A;40.6
2;A;51.1
2;A;52.1
2;A;60.6

2;B;80.1
2;B;70.6
2;B;90.6
2;B;85.1
""")

读取文本数据到pandas数据框架:

df = pd.read_csv(TESTDATA, sep=";")

使用标准偏差定义离群值

stds = 1.0
outliers = df[['G1', 'G2', 'Value']].groupby(['G1','G2']).transform(
           lambda group: (group - group.mean()).abs().div(group.std())) > stds

定义过滤后的数据值和异常值:

dfv = df[outliers.Value == False]
dfo = df[outliers.Value == True]

打印结果:

print '\n'*5, 'All values with decimal 1 are non-outliers. In the other hand, all values with 6 in the decimal are.'
print '\nDef DATA:\n%s\n\nFiltred Values with %s stds:\n%s\n\nOutliers:\n%s' %(df, stds, dfv, dfo)

如果你的数据帧有异常值,有很多方法可以处理这些异常值:

大多数都在我的文章中提到过:读一读

在这里找到代码:Notebook