如何消除间隔中的重叠?

问题描述 投票:0回答:1

我有两个数据集:

  1. 由人们工作的时间段组成
  2. 第二个包括人们度假的时间段

我需要从工作时间中删除这些假期时间,如图所示

enter image description here

我发现 ivs 包很有前途,我能够合并间隔,但无法删除重叠。怎么办?

library(tidyverse)
library(ivs)

worked = read.csv("https://www.dropbox.com/scl/fi/ctu6d8nb193ub0t5wawdf/worked.csv?rlkey=3zsbe8gh483hb0daazrrwl9ko&dl=1")
vacation = read.csv("https://www.dropbox.com/scl/fi/xn76ojwmewpcz71tcivgs/vacation.csv?rlkey=kmllrgvgr6ix0z2wq6roxin8f&dl=1")

这就是数据对一个人的看法

enter image description here

r datetime intervals period
1个回答
0
投票

警告:这适用于您的示例数据,但可能需要对某些奇怪的情况进行进一步的测试。 具体来说,它假设所有假期时间都包含在工作时间之内,并且我还没有测试如果情况不成立会发生什么。

首先,创建

data.frame
,因为我们没有您的 CSV 文件。 请注意,您需要将日期列从
character
转换为
Date

worked <- data.frame(
  ID = c("ID100045", "ID100045"),
  start = as.Date(c("2019-06-04", "2020-12-29")),
  end = as.Date(c("2020-11-30", "9999-10-31")))

vacation <- data.frame(
  ID = c("ID100045", "ID100045", "ID100045"),
  start = as.Date(c("2020-07-08", "2021-02-03", "2022-04-10")),
  end = as.Date(c("2020-11-23", "2021-04-25", "2022-05-10")))

建立一个“时间表”,其中所有日期都按顺序排列。 我们将添加一个名为

at_work
的列,指示该人在该日期开始或停止工作的时间:

library(tidyr)
library(dplyr)

timeline <-
  bind_rows(
    pivot_longer(worked, -ID) %>%
    mutate(at_work = name == "start"),
    pivot_longer(vacation, -ID) %>%
    mutate(at_work = name == "end")
  ) %>%
arrange(ID, value)
> timeline
# A tibble: 10 × 4
   ID       name  value      at_work
   <chr>    <chr> <date>     <lgl>
 1 ID100045 start 2019-06-04 TRUE
 2 ID100045 start 2020-07-08 FALSE
 3 ID100045 end   2020-11-23 TRUE
 4 ID100045 end   2020-11-30 FALSE
 5 ID100045 start 2020-12-29 TRUE
 6 ID100045 start 2021-02-03 FALSE
 7 ID100045 end   2021-04-25 TRUE
 8 ID100045 start 2022-04-10 FALSE
 9 ID100045 end   2022-05-10 TRUE
10 ID100045 end   2024-10-16 FALSE

方法1

检查此人是否在前一天开始工作并且没有工作(作为防止虚假连续 at_work == TRUE

 行的保障),并计算其累积总和。  这将生成一个列,指示每个单独的“工作周期”,并按顺序对其进行编号。
然后,获取每个周期并获取每个周期的开始和结束。

timeline %>% group_by(ID) %>% mutate(period = cumsum(at_work & !lead(at_work))) %>% group_by(ID, period) %>% summarise(start = min(value), end = max(value))
# A tibble: 5 × 4
# Groups:   ID [1]
  ID       period start      end
  <chr>     <int> <date>     <date>
1 ID100045      1 2019-06-04 2020-07-08
2 ID100045      2 2020-11-23 2020-11-30
3 ID100045      3 2020-12-29 2021-02-03
4 ID100045      4 2021-04-25 2022-04-10
5 ID100045      5 2022-05-10 2024-10-16
方法2(不安全)

如果您完全确定所有假期期都在工作期内开始和结束,则只需使用

pivot_wider

unnest
 即可完成:

timeline %>% select(-name) %>% pivot_wider(names_from = at_work, values_from = value) %>% unnest(cols = c(`TRUE`, `FALSE`))
# A tibble: 5 × 3
  ID       `TRUE`     `FALSE`
  <chr>    <date>     <date>
1 ID100045 2019-06-04 2020-07-08
2 ID100045 2020-11-23 2020-11-30
3 ID100045 2020-12-29 2021-02-03
4 ID100045 2021-04-25 2022-04-10
5 ID100045 2022-05-10 2024-10-16
    
© www.soinside.com 2019 - 2024. All rights reserved.