基于%in%的R精确选择

时间:2019-05-31 10:19:55

标签: r

我在执行简单操作时遇到了一些麻烦。

我想要的是简单地选择按id分组的,具有所有值(-1, -2, -3, -4)的行,并根据此条件应用标签。

   id time
1   1   -4
2   1   -3
3   1   -2
4   1   -1
5   2   -1
6   2   -2
7   3   -1
8   3   -3
9   4   -1
10  4   -2
11  4   -3
12  4   -4

直觉上我要去

rb[rb$time %in% c(-1, -2, -3, -4), ]

但是,当我这样做时,所有id都被选中。因此,%in%运算符使用OR |运算符。

因此,我想我可以使用AND &运算符

rb[rb$time == -1 & 
 rb$time == -2 & 
 rb$time == -3 & 
 rb$time == -4, ]

但是它不起作用。

任何线索都可以标记或id的子集,例如

   id time tag
1   1   -4   1
2   1   -3   1
3   1   -2   1
4   1   -1   1
5   2   -1   0
6   2   -2   0
7   3   -1   0
8   3   -3   0
9   4   -1   1
10  4   -2   1
11  4   -3   1
12  4   -4   1

4 个答案:

答案 0 :(得分:7)

一种dplyr可能是:

df %>%
 group_by(id) %>%
 mutate(tag = all(c(-1, -2, -3, -4) %in% time) * 1)

      id  time   tag
   <int> <int> <dbl>
 1     1    -4     1
 2     1    -3     1
 3     1    -2     1
 4     1    -1     1
 5     2    -1     0
 6     2    -2     0
 7     3    -1     0
 8     3    -3     0
 9     4    -1     1
10     4    -2     1
11     4    -3     1
12     4    -4     1

base R相同的可能是:

with(df, ave(time, id, FUN = function(x) all(c(-1, -2, -3, -4) %in% x) * 1))

答案 1 :(得分:1)

许多基本的R选项之一是使用aggregate(我们也可以重命名并转换为整数以获得0或1,但布尔值似乎更适合此目的):

tags <- aggregate(df$time, by = df["id"], FUN = function(el) all(-1:-4 %in% el))
df <- merge(df, tags)

结果:

df
#    id time     x
# 1   1   -4  TRUE
# 2   1   -3  TRUE
# 3   1   -2  TRUE
# 4   1   -1  TRUE
# 5   2   -1 FALSE
# 6   2   -2 FALSE
# 7   2   -1 FALSE
# 8   2   -3 FALSE
# 9   3   -1  TRUE
# 10  3   -2  TRUE
# 11  3   -3  TRUE
# 12  3   -4  TRUE

答案 2 :(得分:0)

要添加更多选项,这里是一个data.table,应该具有显着的性能优势:

dt <- as.data.table(df)[, tag := all(-1:-4 %in% time), by = id]

结果:

dt
#     id time   tag
#  1:  1   -4  TRUE
#  2:  1   -3  TRUE
#  3:  1   -2  TRUE
#  4:  1   -1  TRUE
#  5:  2   -1 FALSE
#  6:  2   -2 FALSE
#  7:  2   -1 FALSE
#  8:  2   -3 FALSE
#  9:  3   -1  TRUE
# 10:  3   -2  TRUE
# 11:  3   -3  TRUE
# 12:  3   -4  TRUE

答案 3 :(得分:0)

这是使用vapply.subset2的另一种基本解决方案(可读性比$[]低,但效率更高)

rb[['tag']] <- 0L
id_col <- .subset2(rb, 1L)
vapply(unique(rb$id), 
       function (id) {
         index <- id_col == id
         test <- all(sort(.subset2(rb, 2L)[index]) == -4:-1)
         rb[['tag']][index] <<- as.integer(test)
         test
         }, 
       logical(1))
rb
#    id time tag
# 1   1   -4   1
# 2   1   -3   1
# 3   1   -2   1
# 4   1   -1   1
# 5   2   -1   0
# 6   2   -2   0
# 7   3   -1   0
# 8   3   -3   0
# 9   4   -1   1
# 10  4   -2   1
# 11  4   -3   1
# 12  4   -4   1