r data.table - 排除包含行中某些值的组

时间:2016-12-20 02:09:34

标签: r data.table

这是一个示例数据表:

set.seed(100)

> A <- data.table( a = sample(c('x','c','y',''),10, replace = T), b = sample(as.Date(c('2008-12-31','2012-12-31','2013-12-31','2014-12-31','2016-12-31')),10, replace = T) , c = runif(10)  )

> A
    a          b         c
 1: c 2014-12-31 0.5358112
 2: c 2016-12-31 0.7108038
 3: y 2012-12-31 0.5383487
 4: x 2012-12-31 0.7489722
 5: c 2014-12-31 0.4201015
 6: c 2014-12-31 0.1714202
 7:   2012-12-31 0.7703016
 8: c 2012-12-31 0.8819536
 9: y 2012-12-31 0.5490967
10: x 2014-12-31 0.2777238

列a包含x,y,c或空。我想按'b'分组并从数据表中排除在该组的任何行中包含至少一个X AND至少一个C的所有组。 X和C出现的顺序并不重要。

在上面的例子中,组'2014-12-31'将被删除,因为它包含c和x(第1,5,6,10行)。同组'2012-12-31'。但是,'2016-12-31'组仍将保留,因为它有一个C,它没有X.

到目前为止我的方法是:

A[ , .( a)   ,by = .(b)][ !(a %in% c('x','c') ) ]

但我相信这会删除所有包含'x'OR'c'的行。我有兴趣同时删除至少有一个X和一个C的那些。

谢谢,

3 个答案:

答案 0 :(得分:3)

逻辑:无需unique,只需提取包含b'sx的{​​{1}} y,然后删除这些条目。

library(data.table)
set.seed(100)
A <- data.table( a = sample(c('x','c','y',''),10, replace = T), 
                 b = sample(as.Date(c('2008-12-31','2012-12-31','2013-12-31','2014-12-31','2016-12-31')),10, replace = T) , 
                 c = runif(10)  )

split(A, A$b)
#$`2012-12-31`
#   a          b         c
#1: y 2012-12-31 0.5383487
#2: x 2012-12-31 0.7489722
#3:   2012-12-31 0.7703016
#4: c 2012-12-31 0.8819536
#5: y 2012-12-31 0.5490967

#$`2014-12-31`
#  a          b         c
#1: c 2014-12-31 0.5358112
#2: c 2014-12-31 0.4201015
#3: c 2014-12-31 0.1714202
#4: x 2014-12-31 0.2777238

#$`2016-12-31`
#  a          b         c
#1: c 2016-12-31 0.7108038

A[!b %in% intersect(b[a == "x"], b[a == "c"])]
#  a          b         c
#1: c 2016-12-31 0.7108038

使用group_by

func <- function(dt){
  if (sum(c("x","c") %in% dt$a) != 2)
    return(dt)
}

A[ , func(.SD), by = "b"]

答案 1 :(得分:2)

试试这个:

setkey(A, a)

A[!b %in% intersect(A['x', b], A['c', b])]

答案 2 :(得分:0)

更改了答案以显示dplyr变体

A %>%
  group_by(b) %>%
  distinct(a) %>%
  filter(a %in% c("x","c")) %>%
  filter(row_number()>1) %>%
  anti_join(A, ., by="b")

按多个b列分组,例如b1b2

A %>%
  group_by(b1,b2) %>%
  distinct(a) %>%
  filter(a %in% c("x","c")) %>%
  filter(row_number()>1) %>%
  anti_join(A, ., by=c("b1","b2"))