在 R 中,如何使用列条件按 ID 获取子集

In R, how to get subset by id with column condition

我有以下数据框。

id <- c(1,1,1,2,2,2,3,3,3,4,4,4)
time <- c(1,2,3,1,2,3,1,2,3,1,2,3)
event1 <- c(0,0,1,0,0,1,0,0,0,1,0,0)
event2 <- c(0,1,0,0,0,0,0,1,0,1,0,0)   
event3 <- c(0,0,0,0,0,0,0,1,0,1,0,0)

temp<-data.frame(id,time,event1,event2,event3)


    id time event1 event2 event3
1   1    1      0      0      0
2   1    2      0      1      0
3   1    3      1      0      0
4   2    1      0      0      0
5   2    2      0      0      0
6   2    3      1      0      0
7   3    1      0      0      0
8   3    2      0      1      1
9   3    3      0      0      0
10  4    1      1      1      1
11  4    2      0      0      0
12  4    3      0      0      0

如果该事件发生(事件 = 1),我希望获得每个唯一 ID 和 event1、event2、event3 列的子集

所以输出会是这样的:

    id event1 event2 event3
1   1    1      1      0
2   2    1      0      0
3   3    0      1      1
4   4    1      1      1

我试图删除重复项并保留唯一 ID,但这给了我错误的输出,因为事件 1 到事件 3 可能不会在时间 = 1 内发生。时间无关紧要。只要该事件发生在三个时间之一内。

如果该事件的 id 中存在 1,我试图通过 id 将 0 替换为 1,但这没有用。

temp %>% group_by(id) %>% mutate(id, event1=ifelse(event1==1,1,event1),
                                 event2 = ifelse(event2==1,1,event2),
                                 event3 =ifelse(event3 ==1,1,event3))

如有任何帮助,我们将不胜感激。

library(tidyverse)
id <- c(1,1,1,2,2,2,3,3,3,4,4,4)
time <- c(1,2,3,1,2,3,1,2,3,1,2,3)
event1 <- as.factor(c(0,0,1,0,0,1,0,0,0,1,0,0))

event2 <-as.factor(c(0,1,0,0,0,0,0,1,0,1,0,0))

event3 <- as.factor(c(0,0,0,0,0,0,0,1,0,1,0,0))

temp<-data.frame(id,time,event1,event2,event3)

temp[,3:5][temp[,3:5]==0] <-NA
temp2 <- as.data.frame(temp%>% group_by(id)%>% 
                         fill(event1,event2,event3,.direction ="downup")
                       )
temp3 <- temp2[!duplicated(temp2[,'id']),]

temp3[is.na(temp3)] <-0
temp3

这给出了我想要的结果,但我觉得它过于复杂了。

您可以在 dplyr 中使用 summarise() + across():

library(dplyr)

temp %>%
  group_by(id) %>%
  summarise(across(contains("event"), sum))

上面的方法计算了每个事件的计数。如果你只想知道事件是否发生,你可以将 sum 部分替换为 max:

temp %>%
  group_by(id) %>%
  summarise(across(contains("event"), max))

# A tibble: 4 x 4
     id event1 event2 event3
  <dbl>  <dbl>  <dbl>  <dbl>
1     1      1      1      0
2     2      1      0      0
3     3      0      1      1
4     4      1      1      1

其他选择

# 1
across(contains("event"), ~ +any(.x == 1))
# 2
across(contains("event"), ~ +(sum(.x) > 0))

(提示: +将逻辑整数转换为二进制整数)

这是一个可能的 data.table 选项:

library(data.table)
dt <- as.data.table(temp)

dt[, lapply(.SD, max, na.rm = TRUE), by=.(id), .SDcols=patterns("event")]

或者可以使用来自基数 R 的 aggregate

aggregate(cbind(event1, event2, event3) ~ id, data = temp, max, na.rm = TRUE)

collapse 包:

library(collapse)

collap(temp, event1 + event2 + event3 ~ id, fmax)

输出

   id event1 event2 event3
1:  1      1      1      0
2:  2      1      0      0
3:  3      0      1      1
4:  4      1      1      1