【问题标题】:Pandas - Replace outliers with groupby meanPandas - 用 groupby mean 替换异常值
【发布时间】:2014-12-24 14:58:15
【问题描述】:

我有一个 pandas 数据框,我想将它分成几组,计算平均值和标准差,然后用组的平均值替换所有异常值。如果离群值与组均值相差 3 个以上标准差,则定义为异常值。

df = pandas.DataFrame({'a': ['A','A','A','B','B','B','B'], 'b': [1.1,1.2,1.1,3.3,3.4,3.3,100.0]})

我认为以下方法会起作用:

df.groupby('a')['b'].transform(lambda x: x[i] if np.abs(x[i]-x.mean())<=(3*x.std()) else x.mean() for i in range(0,len(x)))

但得到以下错误:

NameError: 名称“x”未定义

我也试过单独定义一个变换函数:

def trans_func(x):
    mean = x.mean()
    std = x.std()
    length = len(x)
    for i in range(0,length):
        if abs(x[i]-mean)<=(3*std):
            return x
        else:
            return mean

然后这样称呼它:

df.groupby('a')['b'].transform(lambda x: trans_func(x))

但我得到一个不同的错误:

密钥错误:0

最后,我完全创建了一个单独的列:

df['c'] = [df.groupby('a')['b'].transform(mean) if df.groupby('a')['b'].transform(lambda x: (x - x.mean()) / x.std()) > 3 else df['b']] 

但这也没有用:

ValueError:Series 的真值不明确。使用 a.empty、a.bool()、a.item()、a.any() 或 a.all()。

非常感谢任何建议。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    试试这个:

    def replace(group):
        mean, std = group.mean(), group.std()
        outliers = (group - mean).abs() > 3*std
        group[outliers] = mean        # or "group[~outliers].mean()"
        return group
    
    df.groupby('a').transform(replace)
    

    注意:如果您想消除最后一组中的 100,您可以将 3*std 替换为 1*std。该组的标准差为 48.33,因此将包含在结果中。

    【讨论】:

    • 但这意味着不受异常值的影响吗?
    【解决方案2】:

    先去除异常值,然后计算组均值进行替换会更合适。如果替换的平均值是用异常值计算的,则平均值会受到异常值的影响

    【讨论】:

      【解决方案3】:

      希望这会有所帮助:

      第一步,去除异常值(参考来自pandas group by remove outliers):

      def is_outlier(s):
          lower_limit = s.mean() - (s.std() * 3)
          upper_limit = s.mean() + (s.std() * 3)
          return ~s.between(lower_limit, upper_limit)
      
      df = df[~df.groupby('a')['count'].apply(is_outlier)]
      

      第 2 步,替换异常值(来自 elyase 的引用):

      def replace(group):
          mean, std = group.mean(), group.std()
          outliers = (group - mean).abs() > 3*std
          group[outliers] = mean        # or "group[~outliers].mean()"
          return group
      
      df.groupby('a').transform(replace)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-09
        • 2021-05-18
        • 2021-06-22
        • 2021-04-13
        • 2019-06-03
        • 2022-10-05
        相关资源
        最近更新 更多