【问题标题】:Calculate number of overlapping days between two datesets of periods according to condition and periods (partially) overlapping根据条件和时期(部分)重叠计算两个时期日期集之间的重叠天数
【发布时间】:2018-12-06 13:07:32
【问题描述】:

here 发布的问题类似,我想根据第三个变量(位置)计算两个时期之间的重叠天数。

对于主数据集 (DF) 的每次观察,我都有一个开始和结束日期,以及一个位置(字符)变量。事件数据包括关于事件地点、开始日期和结束日期的信息。允许在同一位置和(部分)重叠期间发生多个事件。

因此,对于 DF 中的每个观察,必须将周期与事件数据集(事件)中的其他周期进行比较。这意味着一个(DF)和多个时期(事件)之间的重叠天数必须扣除事件数据集中两个(或更多)时期之间的重叠天数

我的两个数据源的数据结构的示例可以很容易地在 R 中使用此代码重现(注意,为简单起见,位置变量已设置为整数):

        set.seed(1)
    DF <- data.frame(
      start = sample(seq(as.Date('2018-01-01'), as.Date('2018-04-30'), by="day"), 20),
      end = sample(seq(as.Date('2018-05-01'), as.Date('2018-10-30'), by="day"), 20),
      location = sample(seq(1:5)),20)


    Events <- data.frame(
      start = sample(seq(as.Date('2018-01-01'), as.Date('2018-04-30'), by="day"), 30),
      end = sample(seq(as.Date('2018-05-01'), as.Date('2018-10-30'), by="day"), 30),
      location = sample(seq(1:5)),  30 )

在事件数据减少到只有一个事件(我们不关心位置)的简单情况下,可以使用以下代码和 dplyr 轻松计算 DF 中每个观测的总体天数:来自 Matthew Lundberg 的回答 here,还请注意,我创建了另一个带有单个事件 (One_event) 的数据框:

library(dplyr)

One_event <- data.frame(
  start = as.Date('2018-01-01'),
  end = as.Date('2018-07-30'))

DF %>%
  mutate(overlap = pmax(pmin(One_event$end, end) - pmax(One_event$start, start) + 1,0))

导致:

   start        end       location X20  overlap
1  2018-02-01 2018-10-19        5  20 180 days
2  2018-02-14 2018-06-08        3  20 115 days
3  2018-03-09 2018-08-26        4  20 144 days
4  2018-04-17 2018-05-23        2  20  37 days
5  2018-01-24 2018-06-17        1  20 145 days
6  2018-04-14 2018-07-08        5  20  86 days
7  2018-04-18 2018-05-03        3  20  16 days
8  2018-03-16 2018-07-07        4  20 114 days
9  2018-03-12 2018-09-30        2  20 141 days
10 2018-01-07 2018-06-29        1  20 174 days
11 2018-01-23 2018-07-23        5  20 182 days
12 2018-01-20 2018-08-12        3  20 192 days
13 2018-04-23 2018-07-24        4  20  93 days
14 2018-02-11 2018-06-01        2  20 111 days
15 2018-03-23 2018-09-17        1  20 130 days
16 2018-02-22 2018-08-21        5  20 159 days
17 2018-04-24 2018-09-10        3  20  98 days
18 2018-04-13 2018-05-18        4  20  36 days
19 2018-02-08 2018-08-28        2  20 173 days
20 2018-03-20 2018-10-23        1  20 133 days

现在回到最初的问题。 为了允许根据观察和事件的位置比较数据中每个观察的周期和匹配的事件,我认为使用apply 函数是合理的,根据观察位置对事件数据集进行子集化,最后为每一行和事件数据的子集(临时)运行 mutate 函数:

    apply(DF, 1, function(x) {
  temp =  Events[Events$location %in% x["location"]
 x %>%
      mutate(overlap = pmax(pmin(temp$end, end) - pmax(temp$start, start) + 
1,0))
})

最后一部分代码存在几个问题。首先,不起作用并给出错误消息:

(Error in UseMethod("mutate_") : 
  no applicable method for 'mutate_' applied to an object of class "character")

其次,它不考虑事件数据集中的两个(或更多时间段)重叠。

【问题讨论】:

    标签: r date overlap dplyr period


    【解决方案1】:

    你在找这个吗:

    apply(DF, MARGIN = 1, function(x) {
      Events[Events$location == x["location"],] %>% mutate(overlap = pmax(pmin(.data$end,         
      x["end"]) - pmax(.data$start, x["start"])))
    })
    

    这导致我的情况是:

    [[1]]
       start        end location X30  overlap
    1 2018-02-01 2018-07-28        5  30 177 days
    2 2018-04-14 2018-08-27        5  30 135 days
    3 2018-01-23 2018-09-20        5  30 231 days
    4 2018-02-22 2018-09-10        5  30 200 days
    5 2018-04-04 2018-07-17        5  30 104 days
    6 2018-02-06 2018-05-16        5  30  99 days
    
    [[2]]
       start        end location X30  overlap
    1 2018-01-24 2018-09-26        3  30 114 days
    2 2018-01-07 2018-07-11        3  30 114 days
    3 2018-03-23 2018-10-28        3  30  77 days
    4 2018-03-20 2018-08-22        3  30  80 days
    5 2018-01-26 2018-05-12        3  30  87 days
    6 2018-01-31 2018-07-02        3  30 114 days
    
    [[3]]
       start        end location X30  overlap
    1 2018-03-09 2018-07-29        4  30 142 days
    2 2018-03-16 2018-05-19        4  30  64 days
    3 2018-04-23 2018-09-11        4  30 125 days
    4 2018-04-13 2018-07-19        4  30  97 days
    5 2018-03-05 2018-07-10        4  30 123 days
    6 2018-02-05 2018-07-20        4  30 133 days
    
    ...
    

    【讨论】:

    • 这确实很有帮助。您发布的代码会根据位置变量有条件地生成 DF 中的时段(对于每个 obs)和事件数据集中的时段之间的重叠天数。但是,我想对每个 obs 进行一次计数。在事件的最终重叠时期的 DF 网络中。
    • @Caserio 你能举个例子吗?
    • 当然。首先,我澄清一下我想要的输出是暴露于某些事件的时间。如果两个事件同时发生,我不想重复计算曝光。让我们考虑代码输出的第一部分:[[1]] start end location X30 overlap 1 2018-02-01 2018-07-28 5 30 177 days 2 2018-04-14 2018-08-27 5 30 135 days 这两个事件从 4 月 14 日到 7 月 28 日重叠。因此,如果只考虑这两个事件,那么真正的曝光时间应该是从 2 月 1 日到 8 月 27 日。
    • @Caserio 我明白,没那么容易。也许一个解决方案是作为将 EventDF 聚合到每个位置的最小重叠事件的第一步。
    猜你喜欢
    • 2019-02-12
    • 1970-01-01
    • 1970-01-01
    • 2023-01-19
    • 2021-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多