给定此数据帧:

library(tidyverse)
library(lubridate)

df <- tribble(
  ~person, ~start, ~end,
  '1', '2000-01-01', '2000-12-31',
  '1', '2001-01-01', '2002-07-31',
  '1', '2001-04-01', '2001-06-30',
  '1', '2001-08-01', '2001-12-31',
  '1', '2002-01-01', '2002-12-31',
  '2', '2000-01-01', '2000-11-30',
  '2', '2001-01-01', '2001-12-31') |> 
  mutate(start = lubridate::as_date(start),
         end   = lubridate::as_date(end))

我正在try 产生输出,以显示:

person     start         end
1          2000-01-01    2002-12-31
2          2000-01-01    2001-11-30
2          2001-01-01    2001-12-31

这些数据有重叠的日期,所以我正在try 创建一组连续的、没有错误的开始和结束日期.

我试过这个

df |> 
  distinct() |>
  arrange(person, start, end) |> 
  mutate(
    gap = start - lag(end, default = min(start))
  ) |>
  group_by(person) |> 
  summarise(
    MIN_START = min(start),
    MAX_END   = max(end)
  )

但这会取第一个最小日期和最后一个最大日期,并忽略其间的任何中断.对如何做到这一点有什么建议吗?

推荐答案

这是一个更省钱的函数,它使用了第一个函数所使用的内存的一小部分(下面,留作比较).

fun <- function(starts, ends) {
  S <- starts; E <- ends
  for (i in rev(seq_along(S))) {
    ind <- ind <- which(S[-i] <= S[i] & S[i] <= E[-i] + 1)
    if (length(ind)) {
      ind <- max(ind) + (max(ind) > i)
      S[ind] <- min(S[c(ind, i)])
      E[ind] <- max(E[c(ind, i)])
      S <- S[-i]
      E <- E[-i]
    }
  }
  data.frame(start=S, end=E)
}

reframe(df, .by=person, fun(start, end))
# # A tibble: 3 × 3
#   person start      end       
#   <chr>  <date>     <date>    
# 1 1      2000-01-01 2002-12-31
# 2 2      2000-01-01 2000-11-30
# 3 2      2001-01-01 2001-12-31

(Old answer, not needed.)

使用一个helper函数(这是公认的蛮力):

fun <- function(starts, ends) {
  x <- unique(sort(do.call(c, Map(seq, starts, ends, list(by="day")))))
  x <- split(x, cumsum(c(TRUE, diff(x) > 1))) |>
    lapply(function(z) setNames(data.frame(as.list(range(z))),
                                c("start", "end")))
  do.call(rbind, x)
}

然后我们就可以做

dplyr::reframe(df, .by=person, fun(start, end))
# # A tibble: 3 × 3
#   person start      end       
#   <chr>  <date>     <date>    
# 1 1      2000-01-01 2002-12-31
# 2 2      2000-01-01 2000-11-30
# 3 2      2001-01-01 2001-12-31

R相关问答推荐

从多个前置日期中获取最长日期

ggplot 2中的地块底图(basemaps_gglayer()不起作用)

如何在R中添加截止点到ROC曲线图?

如何写一个R函数来旋转最后n分钟?

在R中使用数据集名称

IMF IFS数据以R表示

如何根据嵌套元素的名称高效而优雅地确定它属于哪个列表?

使用外部文件分配变量名及其值

R中插入符号训练函数的中心因子和尺度因子预测

如果可能,将数字列转换为整数,否则保留为数字

使用rest从header(h2,h3,table)提取分层信息

在使用bslb和bootstrap5时,有没有办法更改特定dt行的 colored颜色 ?

如何计算增加10米(0.01公里)的行?

按组和连续id计算日期差

使用ifElse语句在ggploy中设置aes y值

如何在R中创建条形图,使条形图在y轴上围绕0.5而不是0构建条形图?

是否有一个R函数可以输出在输入的字符向量中找到的相应正则表达式模式?

以R表示的NaN值的IS.NA状态

R data.设置函数&;连接中的列值而不使用for循环的表方法?

按顺序将地块添加到列表