R:如何通过ID识别多个列的第一个积极观察日期?
我想通过ID为多个列确定积极观察的第一个日期 数据帧示例:R:如何通过ID识别多个列的第一个积极观察日期?,r,R,我想通过ID为多个列确定积极观察的第一个日期 数据帧示例: ID date Observ1 Observ2 Observ3 1 1 1 0 0 1 2 0 1 0 1 3 1 0 1 2 1 1 1 0 预期结果: ID FirstObserv1 FirstObserv2 FirstObserv3
ID date Observ1 Observ2 Observ3
1 1 1 0 0
1 2 0 1 0
1 3 1 0 1
2 1 1 1 0
预期结果:
ID FirstObserv1 FirstObserv2 FirstObserv3
1 1 2 3
2 1 1 NA
对于单列观测,我可以用dplyr解决:
df %>% group_by(ID) %>% filter( Observ1 > 0) %>% summarize( FirstObserv1 = min(date) ) %>% as.data.frame()
但是,我不知道如何一次对多个列执行此操作。请尝试使用tidyverse函数对数据进行如下整形。代码id的键过滤值为1的值,然后设置过滤器以使用过滤器提取最小日期值。之后,你重塑到宽,你得到了预期的输出。代码如下:
library(tidyverse)
#Code
dfnew <- df %>% pivot_longer(-c(ID,date)) %>%
group_by(ID) %>%
filter(value==1) %>% select(-value) %>% ungroup() %>%
group_by(ID,name) %>%
filter(date==min(date)) %>%
pivot_wider(names_from = name,values_from=date)
输出:
# A tibble: 2 x 4
# Groups: ID [2]
ID Observ1 Observ2 Observ3
<int> <int> <int> <int>
1 1 1 2 3
2 2 1 1 NA
使用的一些数据:
#Data
df <- structure(list(ID = c(1L, 1L, 1L, 2L), date = c(1L, 2L, 3L, 1L
), Observ1 = c(1L, 0L, 1L, 1L), Observ2 = c(0L, 1L, 0L, 1L),
Observ3 = c(0L, 0L, 1L, 0L)), class = "data.frame", row.names = c(NA,
-4L))
尝试使用tidyverse函数像这样重塑数据。代码id的键过滤值为1的值,然后设置过滤器以使用过滤器提取最小日期值。之后,你重塑到宽,你得到了预期的输出。代码如下:
library(tidyverse)
#Code
dfnew <- df %>% pivot_longer(-c(ID,date)) %>%
group_by(ID) %>%
filter(value==1) %>% select(-value) %>% ungroup() %>%
group_by(ID,name) %>%
filter(date==min(date)) %>%
pivot_wider(names_from = name,values_from=date)
输出:
# A tibble: 2 x 4
# Groups: ID [2]
ID Observ1 Observ2 Observ3
<int> <int> <int> <int>
1 1 1 2 3
2 2 1 1 NA
使用的一些数据:
#Data
df <- structure(list(ID = c(1L, 1L, 1L, 2L), date = c(1L, 2L, 3L, 1L
), Observ1 = c(1L, 0L, 1L, 1L), Observ2 = c(0L, 1L, 0L, 1L),
Observ3 = c(0L, 0L, 1L, 0L)), class = "data.frame", row.names = c(NA,
-4L))
这里有一种方法,如果观察结果是肯定的,则用日期替换观察结果,反之亦然。获得每次观察的最小值会产生期望的结果
df %>%
mutate_at(vars(starts_with("Observ")), ~ifelse(. > 0, date, NA)) %>%
group_by(ID) %>%
summarise_at(vars(starts_with("Observ")), min, na.rm = TRUE)
#> # A tibble: 2 x 4
#> ID Observ1 Observ2 Observ3
#> <dbl> <dbl> <dbl> <dbl>
#> 1 1 1 2 3
#> 2 2 1 1 Inf
这里有一种方法,如果观察结果是肯定的,则用日期替换观察结果,反之亦然。获得每次观察的最小值会产生期望的结果
df %>%
mutate_at(vars(starts_with("Observ")), ~ifelse(. > 0, date, NA)) %>%
group_by(ID) %>%
summarise_at(vars(starts_with("Observ")), min, na.rm = TRUE)
#> # A tibble: 2 x 4
#> ID Observ1 Observ2 Observ3
#> <dbl> <dbl> <dbl> <dbl>
#> 1 1 1 2 3
#> 2 2 1 1 Inf
另一种选择:
df %>%
group_by(ID) %>%
summarise(across(
-date,
list(First = ~{x <- which(. > 0); if (length(x) > 0L) date[[x[[1L]]]] else NA_real_}),
.names = "{.fn}{.col}"
))
输出
ID FirstObserv1 FirstObserv2 FirstObserv3
<dbl> <dbl> <dbl> <dbl>
1 1 1 2 3
2 2 1 1 NA
另一种选择:
df %>%
group_by(ID) %>%
summarise(across(
-date,
list(First = ~{x <- which(. > 0); if (length(x) > 0L) date[[x[[1L]]]] else NA_real_}),
.names = "{.fn}{.col}"
))
输出
ID FirstObserv1 FirstObserv2 FirstObserv3
<dbl> <dbl> <dbl> <dbl>
1 1 1 2 3
2 2 1 1 NA
我们可以使用data.table
或者使用tidyverse
数据
我们可以使用data.table
或者使用tidyverse
数据
好的一只鸭子,同样的方法直到filtervalue==1,但是被卡住了。陡峭的学习曲线。@KarthikS肯定!!!所有的一切都是关于学习曲线:好的一只鸭子,同样的方法直到filtervalue==1,但被卡住了。陡峭的学习曲线。@KarthikS肯定!!!一切都是关于学习曲线的:这不是最后一个参数。groups='drop'默认值吗?例如:>df%>%group\U byID%>%SUMMARESEARCROSSSTARTS\U与'Obser',~哪个。>0[1],.names='First{col}%>%group\u vars使用.groups参数character0>df%>%group\u byID%>%summarySeaCrossStart\u使用'Obser',~which.>0[1],.names='First{col}',.groups='drop%>%group_vars character0>都提供相同的输出。请您帮助理解明确提到.groups='drop'参数的意义。@KarthikS'drop\u last'不是最后一个参数。groups='drop'默认值?例如:>df%>%group\U byID%>%SUMMARESEARCROSSSTARTS\U与'Obser',~哪个。>0[1],.names='First{col}%>%group\u vars使用.groups参数character0>df%>%group\u byID%>%summarySeaCrossStart\u使用'Obser',~which.>0[1],.names='First{col}',.groups='drop%>%group_vars character0>都提供相同的输出。请您帮助理解明确提到.groups='drop'参数的意义。@KarthikS它是'drop\u last'我喜欢这个解决方案,因为它看起来很干净,并且避免了多次重塑数据。我对此唯一的不满是,NAs将被min视为Inf,有没有办法防止这种情况发生?min的行为无法改变。唯一的方法是添加另一个步骤,用NA替换Inf。我喜欢这个解决方案,因为它看起来很干净,并且避免了多次重塑数据。我对此唯一的不满是,NAs将被min视为Inf,有没有办法防止这种情况发生?min的行为无法改变。唯一的方法是添加另一个步骤,用NA替换Inf。