我在执行简单操作时遇到了一些麻烦。
我想要的是简单地选择按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
答案 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