如果为真,则在组和子集中的多个列中搜索值

Searching a value in multiple columns within group and subset if true

我的目标是在组内对组进行子集,其中 cond==1 和其他条件 ==3 三次。所以,首先,我查看 id 内的 group。接下来,我只看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 的第 1 组有资格进行子集化,因为在同一行中,cond==1,其他条件至少三次取值 3。此外,id==500 的第 2 组也有 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

这是一个基本的 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

或在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