在R中按组移除异常值

时间:2018-04-23 13:47:33

标签: r dataframe dplyr

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

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变量中删除异常值,但必须按组客户+代码+年份

分别删除

我找到了这个漂亮的功能

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)类动作变量删除异常值。

4 个答案:

答案 0 :(得分:2)

以下是data.table的解决方案:

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

答案 1 :(得分: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)
}

迭代所有三胞胎客户+代码+年

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

答案 2 :(得分:2)

使用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()

答案 3 :(得分:1)

以下是使用tidyverse

的选项
library(dplyr)
vpg %>%
  group_by_at(names(.)[1:3]) %>% 
  mutate(new = case_when(action == 0 ~ remove_outliers(stuff), TRUE ~ stuff))
相关问题