我的目标是在组内进行分组,其中包括 cond==1
和其他条件 ==3
三次。所以,首先,我看 group
内 id
. 接下来,我看一下 cond1==1
只有。如果 cond1==1
,我数了一下有多少条件取值 3
. 如果我看到三个条件取值 3
然后我把整个 group
但在 id
.
这里是 df
:
df = data.frame(id = c(rep(450, 4),rep(500, 4)),
group = c(rep(1, 2), rep(2,2)),
cond1 = c(1,2,1,2,1,2,2,1),
cond2 = c(1,3,3,1,3,2,3,1),
cond3 = c(3,3,1,2,3,1,2,3),
cond4 = c(3,2,2,3,3,1,2,3),
cond5 = c(3,2,3,3,3,1,2,3))
这里是如何 df
的样子。
id group cond1 cond2 cond3 cond4 cond5
1 450 1 1 1 3 3 3
2 450 1 2 3 3 2 2
3 450 2 1 3 1 2 3
4 450 2 2 1 2 3 3
5 500 1 1 3 3 3 3
6 500 1 2 2 1 1 1
7 500 2 2 3 2 2 2
8 500 2 1 1 3 3 3
比如说,从这个数据框来看,第一组为: id==450
有资格进行子集,因为在同一行中,其中的 cond==1
,其他条件至少取值3三次。另外,第2组为 id==500
也有 cond==1
和至少三个数值 3
在行。顺序并不重要。
这里的结果应该是怎样的。
id group cond1 cond2 cond3 cond4 cond5
1 450 1 1 1 3 3 3
2 450 1 2 3 3 2 2
7 500 2 2 3 2 2 2
8 500 2 1 1 3 3 3
或者在 dplyr
library(dplyr)
df %>%
mutate(ind = rowSums(select(., cond2:cond5) == 3) == 3) %>%
group_by(id, group) %>%
filter(if(any(ind & cond1 == 1)) all(ind[cond1==1]) else FALSE)%>%
ungroup %>%
select(-ind)
# A tibble: 4 x 7
# id group cond1 cond2 cond3 cond4 cond5
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 450 1 1 1 3 3 3
#2 450 1 2 3 3 2 2
#3 500 2 2 3 2 2 2
#4 500 2 1 1 3 3 3
下面是一个基本的R选项
r <- do.call(
rbind,
lapply(
split(df, df[c("id", "group")]),
function(v) subset(v, rowSums(v[-c(1:3)] == 3) >= 3)
)
)
dfout <- `row.names<-`(r[order(r$id,r$group),],NULL)
以致于
> df
id group cond1 cond2 cond3 cond4 cond5
1 450 1 1 1 3 3 3
2 450 1 2 3 3 2 2
3 450 2 1 3 1 2 3
4 450 2 2 1 2 3 3
5 500 1 1 3 3 3 3
6 500 1 2 2 1 1 1
7 500 2 2 3 2 2 2
8 500 2 1 1 3 3 3
如果你想保留原始数据框中的行号,你可以尝试使用
r <- Reduce(
rbind,
lapply(
split(df, df[c("id", "group")]),
function(v) subset(v, rowSums(v[-c(1:3)] == 3) >= 3)
)
)
dfout <- r[order(as.integer(rownames(r))), ]
由此可见
> dfout
id group cond1 cond2 cond3 cond4 cond5
1 450 1 1 1 3 3 3
3 450 2 1 3 3 2 3
5 500 1 1 3 3 3 3
8 500 2 1 1 3 3 3