【问题标题】:remove outliers by group in R在R中按组删除异常值
【发布时间】:2018-10-03 14:24:17
【问题描述】:

在我的数据集中,我必须分别删除每个组的异常值。 这是我的数据集

vpg=structure(list(customer = c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 
1L, 1L, 1L, 2L, 2L, 2L, 2L), code = c(2L, 2L, 3L, 3L, 4L, 4L, 
5L, 5L, 2L, 2L, 3L, 3L, 4L, 4L, 5L, 5L), year = c(2017L, 2017L, 
2017L, 2017L, 2017L, 2017L, 2017L, 2017L, 2018L, 2018L, 2018L, 
2018L, 2018L, 2018L, 2018L, 2018L), stuff = c(10L, 20L, 30L, 
40L, 50L, 60L, 70L, 80L, 10L, 20L, 30L, 40L, 50L, 60L, 70L, 80L
), action = c(0L, 1L, 0L, 1L, 0L, 1L, 0L, 1L, 0L, 1L, 0L, 1L, 
0L, 1L, 0L, 1L)), .Names = c("customer", "code", "year", "stuff", 
"action"), class = "data.frame", row.names = c(NA, -16L))

我必须从 stuff 变量中删除异常值,但按组 customer+code+year 分开

我发现了这个漂亮的功能

remove_outliers <- function(x, na.rm = TRUE, ...) {
  qnt <- quantile(x, probs=c(.25, .75), na.rm = na.rm, ...)
  H <- 1.5 * IQR(x, na.rm = na.rm)
  y <- x
  y[x < (qnt[1] - H)] <- NA
  y[x > (qnt[2] + H)] <- NA
  y
}

new <- remove_outliers(vpg$stuff)
vpg=cbind(new,vpg)
View(vpg)

但它适用于所有群体。 如何使用此功能删除每个组的异常值并为下一步工作获得清晰的数据集? 注意,在这个数据集中,有可变的动作(它的值是 0 和 1)。不是组变量,但只能删除ZERO(0)动作变量类别的异常值。

【问题讨论】:

  • 在您的示例中:是否有异常值要删除?
  • @jogo ,不,因为它是简单的例子,很少

标签: r dataframe dplyr


【解决方案1】:

这是data.table的解决方案:

library("data.table")
setDT(vpg)
vpg[, new:=stuff][action==0, new:=remove_outliers(stuff), by=.(customer, code, year)]

【讨论】:

    【解决方案2】:

    试试这个解决方案:

    构建一个包含函数remove_outliers按客户+代码+年份工作的函数

    f<-function(x,vpg)
    {
      select<-paste0(vpg$customer,vpg$code,vpg$year)==x
      out<-suppressWarnings(cbind(vpg[select,c("customer","code","year")][1,],remove_outliers(vpg[select,"stuff"])))
      return(out)
    }
    

    遍历所有三元组 customer+code+year

    uniq<-as.character(unique(paste0(vpg$customer,vpg$code,vpg$year)))
    bind_rows(lapply(uniq,f,vpg=vpg))
    

    【讨论】:

    • 不使用bind_rows 可以做到吗?像一个基本函数?
    • rbind 是另一种选择
    • 你能不能试试,因为我得到一个尺寸错误...
    【解决方案3】:

    这是一个使用tidyverse的选项

    library(dplyr)
    vpg %>%
      group_by_at(names(.)[1:3]) %>% 
      mutate(new = case_when(action == 0 ~ remove_outliers(stuff), TRUE ~ stuff))
    

    【讨论】:

      【解决方案4】:

      使用library(tidyverse),可以定义函数

      add_new_column <- function(df) {
        new <- remove_outliers(df$stuff)
        return(cbind(new,df))
      }
      

      然后在整个数据框上按组应用它:

      vpg %>%
        group_by(customer, code, year) %>%
        nest() %>%
        mutate(data = map(data, my_function)) %>%
        unnest()
      

      【讨论】:

        猜你喜欢
        • 2020-11-17
        • 2018-10-10
        • 2012-08-11
        • 2020-08-19
        • 2017-11-28
        • 2017-09-25
        • 1970-01-01
        • 2019-04-11
        相关资源
        最近更新 更多