我有两个数据集:
我需要从工作时间中删除这些假期时间,如图所示
我发现 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")
这就是数据对一个人的看法
警告:这适用于您的示例数据,但可能需要对某些奇怪的情况进行进一步的测试。 具体来说,它假设所有假期时间都包含在工作时间之内,并且我还没有测试如果情况不成立会发生什么。
首先,创建
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
检查此人是否在前一天开始工作并且没有工作(作为防止虚假连续 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