dplyr-安排、分组、计算日期差异

dplyr-安排、分组、计算日期差异,r,dplyr,R,Dplyr,我有一个大数据集,显示了从健康事件到随后的疾病事件的儿童随访情况 我试图使用dplyr来计算健康事件和第一次生病事件之间的时间 模拟数据集 模拟输出数据集 我只能使用dplyr按id和日期对数据进行排序,然后按id分组: df2 <- df1 %>% arrange(id, date_follow_up) %>% group_by(id) 在计算日期差异并将其添加到每个人的健康事件行旁边时,您需要帮助:这里有一种方法,但如果您每个ID有多个健康事件,您可能需要调整它以使其更加

我有一个大数据集,显示了从健康事件到随后的疾病事件的儿童随访情况

我试图使用dplyr来计算健康事件和第一次生病事件之间的时间

模拟数据集

模拟输出数据集

我只能使用dplyr按id和日期对数据进行排序,然后按id分组:

df2 <- df1 %>% arrange(id, date_follow_up) %>% group_by(id)

在计算日期差异并将其添加到每个人的健康事件行旁边时,您需要帮助:

这里有一种方法,但如果您每个ID有多个健康事件,您可能需要调整它以使其更加可靠:

        # turn dates into subtractable Date class
df1 %>% mutate(date_follow_up = as.Date(date_follow_up, '%m/%d/%y')) %>% 
    group_by(id) %>%
           # Add new column. If there is a "healthy" event,
    mutate(diff_time = ifelse(event == 'healthy', 
                              # subtract the date from the minimum "sick" date
                              min(date_follow_up[event == 'sick']) - date_follow_up, 
                              # else if it isn't a "healthy" event, return NA.
                              NA))

## Source: local data frame [6 x 4]
## 
##      id   event date_follow_up diff_time
##   <dbl>   <chr>         <date>     <dbl>
## 1     1 healthy     2015-04-01         3
## 2     1             2015-04-02        NA
## 3     1             2015-04-03        NA
## 4     1    sick     2015-04-04        NA
## 5     1    sick     2015-04-05        NA
## 6     1             2015-04-06        NA

这里有一种方法,但如果您每个ID有多个健康事件,您可能需要调整它以变得更健壮:

        # turn dates into subtractable Date class
df1 %>% mutate(date_follow_up = as.Date(date_follow_up, '%m/%d/%y')) %>% 
    group_by(id) %>%
           # Add new column. If there is a "healthy" event,
    mutate(diff_time = ifelse(event == 'healthy', 
                              # subtract the date from the minimum "sick" date
                              min(date_follow_up[event == 'sick']) - date_follow_up, 
                              # else if it isn't a "healthy" event, return NA.
                              NA))

## Source: local data frame [6 x 4]
## 
##      id   event date_follow_up diff_time
##   <dbl>   <chr>         <date>     <dbl>
## 1     1 healthy     2015-04-01         3
## 2     1             2015-04-02        NA
## 3     1             2015-04-03        NA
## 4     1    sick     2015-04-04        NA
## 5     1    sick     2015-04-05        NA
## 6     1             2015-04-06        NA

这里是使用dplyr的另一种方法,尽管与早期的解决方案相比它稍微长一点

library(dplyr)
df1$date_follow_up <- as.Date(df1$date_follow_up, "%m/%d/%y")

df1 %>% group_by(id, event) %>%
        filter(event %in% c("healthy", "sick")) %>%
        slice(which.min(date_follow_up)) %>% group_by(id) %>%
        mutate(diff_time = lead(date_follow_up) - date_follow_up) %>% 
        right_join(df1, by = c("id", "event" , "date_follow_up"))

# Output 

Source: local data frame [6 x 4]
Groups: id [?]

      id   event   date_follow_up       diff_time
     <dbl>   <chr>         <date>  <S3: difftime>
1     1   healthy     2015-04-01         3 days
2     1               2015-04-02        NA days
3     1               2015-04-03        NA days
4     1      sick     2015-04-04        NA days    
5     1      sick     2015-04-05        NA days
6     1               2015-04-06        NA days

这里是使用dplyr的另一种方法,尽管与早期的解决方案相比它稍微长一点

library(dplyr)
df1$date_follow_up <- as.Date(df1$date_follow_up, "%m/%d/%y")

df1 %>% group_by(id, event) %>%
        filter(event %in% c("healthy", "sick")) %>%
        slice(which.min(date_follow_up)) %>% group_by(id) %>%
        mutate(diff_time = lead(date_follow_up) - date_follow_up) %>% 
        right_join(df1, by = c("id", "event" , "date_follow_up"))

# Output 

Source: local data frame [6 x 4]
Groups: id [?]

      id   event   date_follow_up       diff_time
     <dbl>   <chr>         <date>  <S3: difftime>
1     1   healthy     2015-04-01         3 days
2     1               2015-04-02        NA days
3     1               2015-04-03        NA days
4     1      sick     2015-04-04        NA days    
5     1      sick     2015-04-05        NA days
6     1               2015-04-06        NA days

我对你的数据做了更多的修改,以便彻底检查这个案例。我的建议与阿利斯泰尔的建议相似。我的建议可以为mydf中的id 2生成NA,而alistaire建议创建Inf。首先,我将字符中的日期转换为日期对象。然后,我按id对数据进行分组,并通过从生病的第一天(即日期跟进)减去健康的第一天(即日期跟进)[event==health][1]来计算时间差[event==sick][1]。最后,我用NA替换了不相关行的时差

   id   event date_follow_up
1   1 healthy         4/1/15
2   1                 4/2/15
3   1                 4/3/15
4   1    sick         4/4/15
5   1    sick         4/5/15
6   2                 4/1/15
7   2 healthy         4/2/15
8   2                 4/3/15
9   2                 4/4/15
10  2                 4/5/15
11  3                 4/1/15
12  3 healthy         4/2/15
13  3    sick         4/3/15
14  3                 4/4/15
15  3                 4/5/15

library(dplyr)
mutate(mydf, date_follow_up = as.Date(date_follow_up, format = "%m/%d/%y")) %>%
group_by(id) %>%
mutate(foo = date_follow_up[event == "sick"][1] - date_follow_up[event == "healthy"][1],        
       foo = replace(foo, which(event != "healthy"), NA))


Source: local data frame [15 x 4]
Groups: id [3]

      id   event date_follow_up            foo
   <int>   <chr>         <date> <S3: difftime>
1      1 healthy     2015-04-01         3 days
2      1             2015-04-02        NA days
3      1             2015-04-03        NA days
4      1    sick     2015-04-04        NA days
5      1    sick     2015-04-05        NA days
6      2             2015-04-01        NA days
7      2 healthy     2015-04-02        NA days
8      2             2015-04-03        NA days
9      2             2015-04-04        NA days
10     2             2015-04-05        NA days
11     3             2015-04-01        NA days
12     3 healthy     2015-04-02         1 days
13     3    sick     2015-04-03        NA days
14     3             2015-04-04        NA days
15     3             2015-04-05        NA days
资料


我对您的数据进行了更多的修改,以彻底检查这个案例。我的建议与alistaire的建议类似。我的建议可以在mydf中为id 2生成NA,而alistaire的建议创建Inf。首先,我将字符中的日期转换为日期对象。然后,我按id对数据进行分组,并通过减去t来计算时差健康的第一天,即从生病的第一天开始的日期跟进[event==Health][1],即日期跟进[event==sick][1]。最后,我用NA替换了不相关行的时差

   id   event date_follow_up
1   1 healthy         4/1/15
2   1                 4/2/15
3   1                 4/3/15
4   1    sick         4/4/15
5   1    sick         4/5/15
6   2                 4/1/15
7   2 healthy         4/2/15
8   2                 4/3/15
9   2                 4/4/15
10  2                 4/5/15
11  3                 4/1/15
12  3 healthy         4/2/15
13  3    sick         4/3/15
14  3                 4/4/15
15  3                 4/5/15

library(dplyr)
mutate(mydf, date_follow_up = as.Date(date_follow_up, format = "%m/%d/%y")) %>%
group_by(id) %>%
mutate(foo = date_follow_up[event == "sick"][1] - date_follow_up[event == "healthy"][1],        
       foo = replace(foo, which(event != "healthy"), NA))


Source: local data frame [15 x 4]
Groups: id [3]

      id   event date_follow_up            foo
   <int>   <chr>         <date> <S3: difftime>
1      1 healthy     2015-04-01         3 days
2      1             2015-04-02        NA days
3      1             2015-04-03        NA days
4      1    sick     2015-04-04        NA days
5      1    sick     2015-04-05        NA days
6      2             2015-04-01        NA days
7      2 healthy     2015-04-02        NA days
8      2             2015-04-03        NA days
9      2             2015-04-04        NA days
10     2             2015-04-05        NA days
11     3             2015-04-01        NA days
12     3 healthy     2015-04-02         1 days
13     3    sick     2015-04-03        NA days
14     3             2015-04-04        NA days
15     3             2015-04-05        NA days
资料

我们还可以使用data.table。将“data.frame”转换为“data.table”setDTmydf,使用as.date更改“date\u follow\u up to date”的类,按“id”分组,并通过获取逻辑向量事件==health的累积和创建分组变量,我们得到第一个生病“事件”的“date\u follow\u”与第一个“date\u fo”的差值如果某一特定群体中有任何生病的“事件”或其他返回NA,则允许健康的“事件”

library(data.table)
setDT(mydf)[, date_follow_up := as.Date(date_follow_up, "%m/%d/%y")
    ][, foo := if(any(event == "sick"))  
                  as.integer(date_follow_up[which(event=="sick")[1]] - 
                         date_follow_up[1] )
                else NA_integer_ , 
     by = .(grp= cumsum(event == "healthy"), id)]
然后,对于所有不健康的事件,我们可以将foo更改为NA

mydf[event!= "healthy", foo := NA_integer_]
mydf
#    id   event date_follow_up foo
# 1:  1 healthy     2015-04-01   3
# 2:  1             2015-04-02  NA
# 3:  1             2015-04-03  NA
# 4:  1    sick     2015-04-04  NA
# 5:  1    sick     2015-04-05  NA
# 6:  2             2015-04-01  NA
# 7:  2 healthy     2015-04-02  NA
# 8:  2             2015-04-03  NA
# 9:  2             2015-04-04  NA
#10:  2             2015-04-05  NA
#11:  3             2015-04-01  NA
#12:  3 healthy     2015-04-02   1
#13:  3    sick     2015-04-03  NA
#14:  3             2015-04-04  NA
#15:  3             2015-04-05  NA
#16:  4             2015-04-01  NA
#17:  4 healthy     2015-04-02   3
#18:  4             2015-04-03  NA
#19:  4             2015-04-04  NA
#20:  4    sick     2015-04-05  NA
#21:  4    sick     2015-04-06  NA
#22:  4             2015-04-07  NA
#23:  4 healthy     2015-04-08   2
#24:  4             2015-04-09  NA
#25:  4    sick     2015-04-10  NA
注意:在这里,我准备了一个特定id可能存在多个健康/疾病“事件”的数据

数据 我们还可以使用data.table。将“data.frame”转换为“data.table”setDTmydf,使用as.date更改“date\u follow\u up to date”的类,按“id”分组,并通过获取逻辑向量事件==health的累积和创建分组变量,我们得到第一个生病“事件”的“date\u follow\u”与第一个“date\u fo”的差值如果某一特定群体中有任何生病的“事件”或其他返回NA,则允许健康的“事件”

library(data.table)
setDT(mydf)[, date_follow_up := as.Date(date_follow_up, "%m/%d/%y")
    ][, foo := if(any(event == "sick"))  
                  as.integer(date_follow_up[which(event=="sick")[1]] - 
                         date_follow_up[1] )
                else NA_integer_ , 
     by = .(grp= cumsum(event == "healthy"), id)]
然后,对于所有不健康的事件,我们可以将foo更改为NA

mydf[event!= "healthy", foo := NA_integer_]
mydf
#    id   event date_follow_up foo
# 1:  1 healthy     2015-04-01   3
# 2:  1             2015-04-02  NA
# 3:  1             2015-04-03  NA
# 4:  1    sick     2015-04-04  NA
# 5:  1    sick     2015-04-05  NA
# 6:  2             2015-04-01  NA
# 7:  2 healthy     2015-04-02  NA
# 8:  2             2015-04-03  NA
# 9:  2             2015-04-04  NA
#10:  2             2015-04-05  NA
#11:  3             2015-04-01  NA
#12:  3 healthy     2015-04-02   1
#13:  3    sick     2015-04-03  NA
#14:  3             2015-04-04  NA
#15:  3             2015-04-05  NA
#16:  4             2015-04-01  NA
#17:  4 healthy     2015-04-02   3
#18:  4             2015-04-03  NA
#19:  4             2015-04-04  NA
#20:  4    sick     2015-04-05  NA
#21:  4    sick     2015-04-06  NA
#22:  4             2015-04-07  NA
#23:  4 healthy     2015-04-08   2
#24:  4             2015-04-09  NA
#25:  4    sick     2015-04-10  NA
注意:在这里,我准备了一个特定id可能存在多个健康/疾病“事件”的数据

数据
使用@akrun的示例数据,这里有一种使用data.table中的滚动联接的方法:

其思想是:对于dt1中的每个健康日期,获取dt2中第一个生病日期的索引>=健康日期

然后直接减去这两个日期得到最终结果

dt[event == "healthy", 
     diff := as.integer(dt2$date_follow_up[idx] - dt1$date_follow_up)]

使用@akrun的示例数据,这里有一种使用data.table中的滚动联接的方法:

其思想是:对于dt1中的每个健康日期,获取dt2中第一个生病日期的索引>=健康日期

然后直接减去这两个日期得到最终结果

dt[event == "healthy", 
     diff := as.integer(dt2$date_follow_up[idx] - dt1$date_follow_up)]

你还考虑了可能的情况。再加上一个反馈给你。“JasZurro谢谢,是的,我有点好奇我的第一个解决方案是否适用于它。”AkRun我相信OP有足够的事情来考虑他/她如何解决这个难题。嗨,Akrun,谢谢,考虑到多个健康/生病的事件。非常感谢。现在看看如何真实数据回应:hi@akrun,我在更大的数据集上试用过,效果很好。但是,我需要做一些调整。到目前为止,脚本为每个人寻找每个健康事件之后的第一个生病事件。请帮助我调整:对于每个人,按日期对条目进行排序,如果第一个条目是健康的,然后发现第一个生病的事件,并在日期上有所不同。它不应该考虑更多的健康事件跟随你进一步考虑可能的情况。再加上一个回到你。:“JasZurro谢谢,是的,我有点好奇我的第一个解决方案是否适用于我。”
我相信OP有足够的事情来考虑他/她如何解决这个难题。嗨,Akrun,谢谢你,并且考虑到多重健康/病态的事件。非常感谢。现在看看真实数据是如何反应的:hi@akrun,我已经在更大的数据集上试用过了,效果非常好。但是,我需要做一些调整。到目前为止,脚本将查找每个个体的每个健康事件之后的第一个生病事件。请帮助我调整:对于每个人,按日期对条目进行排序,如果第一个条目是健康的,那么找到接下来的第一个生病事件并获得日期差异。它不应该考虑后续的健康事件,感谢反馈,在运行最后一行代码时,我得到了错误:[.DAT.TabDelt2,Dt1,Loop--INF,其中=true,on = .id::找不到函数.HI,谢谢反馈,运行最后一行代码时,我得到了错误:[.data.tabledt2,dt1,roll=-Inf,which=TRUE,on=.id,:找不到函数。嗨,Jazzurro,就像Akrun一样,我很感谢您考虑到多个健康/疾病事件以及您如何满足其他id。让我看看真正的数据如何响应。Cheers@K.Kariuki很高兴能帮助你。嗨,爵士音乐,就像Akrun的一样,我很感激考虑多个健康/疾病事件,以及您如何满足其他id。让我看看真实数据如何响应。Cheers@K.Kariuki很高兴能为您提供帮助。嗨,Alistare。感谢您的反馈。Akrun和Jazzurro承办了多项健康活动。不过,非常感谢:嗨,Alistare。谢谢您的反馈。Akrun和Jazzurro承办了r多个健康事件。不过,非常感谢:嗨,Sumedh,谢谢。我在我发布的原始数据集上测试了它,效果很好。然后我在Akrun的数据集上进行了测试,该数据集与真实数据类似,我有多个健康/疾病事件,但失败了,出现以下错误:警告消息:在右侧\u join\u implx,y,by$x,by$y:join character vect或者和因子,强制转换为字符向量。仍然非常感谢..嗨,Sumedh,谢谢。我在我发布的原始数据集上测试了它,效果很好。然后我在Akrun的数据集上进行了测试,该数据集与真实数据类似,我有多个健康/疾病事件,但失败了,错误如下:警告消息:在右侧加入\u implx,y,by$x,by$y:joining字符向量和因子,强制转换为字符向量。仍然非常感谢。。