在R中按组计算日期之间的差异

6

我正在使用逻辑曝光法计算鸟巢孵化成功率,我的数据集非常广泛,有大约2,000个巢,每个巢都有一个唯一的ID(“ClutchID”)。我需要计算给定巢穴的曝光天数(“Exposure”),或者更简单地说,就是第一天和最后一天之间的差异。我使用了以下代码:

HS_Hatch$Exposure=NA    
for(i in 2:nrow(HS_Hatch)){HS_Hatch$Exposure[i]=HS_Hatch$DateVisit[i]- HS_Hatch$DateVisit[i-1]}

HS_Hatch是我的数据集,DateVisit是实际日期。唯一的问题是R计算了第一个日期的暴露值(这是不合理的)。

我真正需要的是计算给定蛋团的第一个和最后一个日期之间的差异。我还研究了以下内容:

Exposure=ddply(HS_Hatch, "ClutchID", summarize, 
                     orderfrequency = as.numeric(diff.Date(DateVisit)))


df %>%
  mutate(Exposure =  as.Date(HS_Hatch$DateVisit, "%Y-%m-%d")) %>%
  group_by(ClutchID) %>%
  arrange(Exposure) %>%
  mutate(lag=lag(DateVisit), difference=DateVisit-lag)

我还在学习R语言,如果你能提供任何帮助将不胜感激。

编辑: 以下是我正在使用的数据样本

HS_Hatch <- structure(list(ClutchID = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 
                                        2L, 3L, 3L, 3L, 4L, 4L, 4L, 4L, 4L, 4L, 5L, 5L, 5L, 5L, 5L, 5L
), DateVisit = c("3/15/2012", "3/18/2012", "3/20/2012", "4/1/2012", 
                 "4/3/2012", "3/18/2012", "3/20/2012", "3/22/2012", "4/3/2012", 
                 "4/4/2012", "3/22/2012", "4/3/2012", "4/4/2012", "3/18/2012", 
                 "3/20/2012", "3/22/2012", "4/2/2012", "4/3/2012", "4/4/2012", 
                 "3/20/2012", "3/22/2012", "3/25/2012", "3/27/2012", "4/4/2012", 
                 "4/5/2012"), Year = c(2012L, 2012L, 2012L, 2012L, 2012L, 2012L, 
                                       2012L, 2012L, 2012L, 2012L, 2012L, 2012L, 2012L, 2012L, 2012L, 
                                       2012L, 2012L, 2012L, 2012L, 2012L, 2012L, 2012L, 2012L, 2012L, 
                                       2012L), Survive = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
                                                           1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L)), class = c("tbl_df", 
                                                                                                                               "tbl", "data.frame"), row.names = c(NA, -25L), .Names = c("ClutchID", 
                                                                                                                                                                                         "DateVisit", "Year", "Survive"), spec = structure(list(cols = structure(list(
                                                                                                                                                                                             ClutchID = structure(list(), class = c("collector_integer", 
                                                                                                                                                                                                                                    "collector")), DateVisit = structure(list(), class = c("collector_character", 
                                                                                                                                                                                                                                                                                           "collector")), Year = structure(list(), class = c("collector_integer", 
                                                                                                                                                                                                                                                                                                                                             "collector")), Survive = structure(list(), class = c("collector_integer", 
                                                                                                                                                                                                                                                                                                                                                                                                  "collector"))), .Names = c("ClutchID", "DateVisit", "Year", 
                                                                                                                                                                                                                                                                                                                                                                                                                             "Survive")), default = structure(list(), class = c("collector_guess", 
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                "collector"))), .Names = c("cols", "default"), class = "col_spec"))

3
欢迎来到 Stack Overflow!请您提供一些数据,以便我们能够制作一个可重现的样例。请注意不要改变原文意思,尽量让翻译通俗易懂。 - Ben Bolker
3
也许可以将曝光情况总结为 diff(range(DateVisit)) - Ben Bolker
1
只是补充一下@BenBolker所说的,他的summarise行应该放在你的group_by行之后。根据DateVisit的类别,您可以省略第一行mutate,或更改summarise行以引用Exposure而不是DateVisit - rosscova
请编辑您的问题并将数据以正确格式添加到问题中,不要作为评论或链接。最好使用dput命令。谢谢。 - Uwe
@rosscova 1) 对不起,我不明白如何使用dput正确格式化数据。我可以在哪里找到更多相关信息呢? 2) 你指的是哪几行代码? - birdnerd
显示剩余4条评论
2个回答

8

收集一些评论...

加载 dplyr

我们只需要使用 dplyr 包来解决这个问题。如果我们加载了其他包,比如 plyr,它可能会与 dplyr 产生冲突,因为两个包中可能有相同名称的函数。让我们只加载 dplyr

library(dplyr)

未来你可能希望加载 tidyverse -- 它包括 dplyr 和其他相关的包,用于图形等。

日期转换

让我们将 DateVisit 变量从字符串类型转换为 R 可以解释为日期的格式。一旦这样做,R 就可以计算两个日期之间的天数差异。

HS_Hatch <- HS_Hatch %>%
 mutate(date_visit = as.Date(DateVisit, "%m/%d/%Y"))

日期格式%m/%d/%Y与您的原始代码不同。此日期格式需要与数据中的日期格式相匹配。DateVisit具有月/日/年的日期格式,因此我们使用%m/%d/%Y

此外,在mutate中不需要指定DateVisit的数据集,例如HS_Hatch$DateVisit,因为它已经在HS_Hatch中查找了。代码HS_Hatch %>% ...表示“使用HS_Hatch进行以下步骤”。

计算暴露时间

要计算暴露时间,我们需要按ClutchID的每一组行找到第一个日期、最后一个日期,然后计算两者之间的差异。我们使用summarize,将数据缩减为每个ClutchID的一行。

exposure <- HS_Hatch %>% 
    group_by(ClutchID) %>%
    summarize(first_visit = min(date_visit), 
              last_visit = max(date_visit), 
              exposure = last_visit - first_visit)

first_visit = min(date_visit)将会针对每个ClutchID分别找到最小的date_visit,因为我们使用了group_by(ClutchID)

exposure = last_visit - first_visit利用新计算出的first_visitlast_visit来计算天数上的差异。

这将产生以下结果:

  ClutchID first_visit last_visit exposure
     <int>      <date>     <date>    <dbl>
1        1  2012-03-15 2012-04-03       19
2        2  2012-03-18 2012-04-04       17
3        3  2012-03-22 2012-04-04       13
4        4  2012-03-18 2012-04-04       17
5        5  2012-03-20 2012-04-05       16

如果您想保留所有原始行,您可以使用mutate代替summarize

非常感谢!我一直在努力想弄清楚这个问题,现在终于解决了。作为一个正在学习R编程的人,我很感激你逐步解释代码。我能够理解并跟着做了。 - birdnerd
如果答案解决了您的问题,请点击“接受”。这将有助于向回答者表示感谢,并帮助其他人在未来找到解决方案。 - rosscova
我遇到了类似的问题。在复制此示例以进行曝光时,我只返回了一行。分组因素被忽略了。您是否遇到了相同的问题?或者是因为我使用的是更新版本? - FlyingDutch
我不确定。我能够使用 R 3.4.3 和 dplyr 0.7.4 复制它。你的一行结果是什么样子? - David Kretch

1
如果您正在寻找一个将向量date中的difftime结果以天为单位显示并且不会在新列中产生NA值的类似解决方案,同时期望按照几个条件/组进行分组,请使用以下方案。请确保您的日期向量已经按照先前说明的正确格式进行转换。
dat2 <- dat %>% 
select(group1, group2, date) %>% 
arrange(group1, group2, date) %>% 
group_by(group1, group2) %>% 
mutate(diff_date = c(0,diff(date)))

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接