按组确定独特的服务使用天数

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

我有一个数据集,其中包含个人服务使用的开始和结束日期(每一集一行)。有时这些时期会重叠,有时则不会。我想计算一年中此人接触服务(使用 R)的唯一天数。尝试使用 IVS 包但遇到问题,因为这与开始日期和结束日期在同一天的行有关。我如何计算同一个人有单天服务以及多天服务的不同天数。

eg_data <- data.frame(
id = c(1,1,1,  2,2,  3,3,3,3,3,3,  4,4,  5,5,5,5),
start_dt = c("01/01/2016", "12/02/2016", "03/12/2017",  "02/01/2016", 
"03/04/2016",  "01/01/2016", "03/05/2016", "05/07/2016", "07/01/2016", 
"09/04/2016", "10/10/2016",  "01/01/2016", "05/28/2016",  "01/01/2016", 
"06/05/2016", "08/25/2016", "11/01/2016"),  
end_dt =   c("12/01/2016", "12/02/2016", "05/15/2017",  "05/15/2016", 
"12/29/2016",  "03/02/2016", "04/29/2016", "06/29/2016", "08/31/2016", 
"03/04/2016", "11/29/2016",  "05/31/2016", "08/19/2016",  "06/10/2016", 
"07/25/2016", "08/25/2016", "12/30/2016"))
eg_data$row_n <- 1:nrow(eg_data)

试过

ab <- a %>%
  mutate(
    start_dt = as.Date(ActivityStartDate, format = "%m/%d/%Y"),
    end_dt = as.Date(ActivityEndDate, format = "%m/%d/%Y")
  ) %>%
  mutate(
    range = iv(start_dt, end_dt),
    .keep = "unused"
  )


c <-ab %>%
  group_by(ID) %>%
  mutate(group = iv_identify_group(range)) %>%
  group_by(group, .add = TRUE)

但不适用于开始日期和结束日期在同一天的记录。还希望输出是一个带有日期变量的数据框,而不是一个向量,这样我就可以计算活动的总天数(不计算同一天不止一次)。

r date gaps-and-islands overlapping
3个回答
0
投票

一种方法是过滤每个id的数据,获取并组合每一行的日期序列,然后统计唯一日期的数量。 不确定你需要输出作为带有日期变量的数据框是什么意思,但我将结果转换为数据框,希望它接近你所追求的。 请注意,在您的数据中,第 10 行的开始日期在结束日期之后,因此需要在以下内容起作用之前进行修复。我以为他们是从后到前。

DayTotals <- sapply(seq_along(unique(eg_data$id)), function(id_index) {
  Current_id <- unique(eg_data$id)[id_index]
  Current_id_data <- eg_data %>% filter(id == Current_id)
  Current_id_dates <- apply(Current_id_data,1,function(row) {
    seq.Date(from = as.Date(row['start_dt'],format="%m/%d/%Y"),
                      to=as.Date(row['end_dt'],format="%m/%d/%Y"),
             by="day")})
  Current_id_No_Of_Days <- Current_id_dates %>% unlist %>% unique %>% length
})

DayTotalsDF <- data.frame(id=unique(eg_data$id),
                          NoOfDays=DayTotals)

> DayTotalsDF
  id NoOfDays
1  1      402
2  2      333
3  3      298
4  4      232
5  5      268

0
投票
library(lubridate)
library(dplyr)
library(purrr)

eg_data <- data.frame(
  id = c(1, 2, 3),
  start_date = c("2022-01-01", "2022-03-05", "2022-04-12"),
  end_date = c("2022-01-05", "2022-03-10", "2022-04-16")
)

eg_data$start_dt <- ymd(eg_data$start_date)
eg_data$end_dt <- ymd(eg_data$end_date)

eg_data %>%
  mutate(
    date_list = map2(start_dt, end_dt, seq, by = "day"),
    date = map(date_list, ~ paste0(format(.x, "%Y-%m-%d"), collapse = ", "))
  ) %>%
  select(id, date)

输出: www.kaavannan-perl.blogspot.com

上面的代码采用一个包含开始日期和结束日期列的数据框,并创建一个新的数据框,其中包含这些开始日期和结束日期之间的每日日期。下面是代码的详细解释:

第一行代码加载lubridate和dplyr包,程序中用到了。 lubridate 包提供了处理日期和时间的工具,而 dplyr 用于数据操作。

下一行代码创建了一个名为 eg_data 的示例数据框,其中包含两列,名为 start_dt 和 end_dt。这些列包含日期值,并代表每个期间的开始和结束日期。

dplyr 包中的 mutate() 函数用于在 eg_data 数据框中创建一个名为 date_list 的新列。此列是使用 purrr 包中的 map2() 函数创建的。 map2() 接受三个参数:开始日期、结束日期和应用于每对开始日期和结束日期的函数。在这种情况下,seq() 函数应用于每对开始日期和结束日期,以生成这两个值之间的日期序列。

seq() 函数生成开始日期和结束日期之间的日期序列,使用“天”作为步长。这将创建一个向量列表,其中每个向量包含给定开始日期和结束日期之间的每日日期。

tidyr 包中的 unnest() 函数用于解除向量列表的嵌套,以便每个每日日期值出现在 eg_data 数据框中的单独行中。

最后,dplyr 的 select() 函数用于仅选择最终输出中需要的列:start_dt、end_dt 和 date_list。 distinct() 函数用于删除输出中的任何重复行。

您可以尝试此代码,如果需要更多帮助,请关注我的博客


0
投票

使用 difftime() 计算开始日期和结束日期之间的天数,并加 1 以包括开始日期和结束日期。然后按 ID 对数据进行分组,并对有活动的天数求和。

参见:https://www.mycompiler.io/view/AAAyWCmzw0X

library(dplyr)

eg_data <- data.frame(
id = c(1,1,1,  2,2,  3,3,3,3,3,3,  4,4,  5,5,5,5),
start_dt = c("01/01/2016", "12/02/2016", "03/12/2017",  "02/01/2016", 
"03/04/2016",  "01/01/2016", "03/05/2016", "05/07/2016", "07/01/2016", 
"09/04/2016", "10/10/2016",  "01/01/2016", "05/28/2016",  "01/01/2016", 
"06/05/2016", "08/25/2016", "11/01/2016"),  
end_dt =   c("12/01/2016", "12/02/2016", "05/15/2017",  "05/15/2016", 
"12/29/2016",  "03/02/2016", "04/29/2016", "06/29/2016", "08/31/2016", 
"03/04/2016", "11/29/2016",  "05/31/2016", "08/19/2016",  "06/10/2016", 
"07/25/2016", "08/25/2016", "12/30/2016"))
eg_data$row_n <- 1:nrow(eg_data)


eg_data %>%
  mutate(
    start_dt = as.Date(start_dt, format = "%m/%d/%Y"),
    end_dt = as.Date(end_dt, format = "%m/%d/%Y"),
    min_date = pmin(start_dt, end_dt),
    max_date = pmax(start_dt, end_dt),
    n_days = as.numeric(difftime(max_date, min_date, units = "days")) + 1
  ) %>%
  group_by(id) %>%
  summarize(total_days = sum(n_days))

结果是;

 id total_days
  <dbl>      <dbl>
1     1        402
2     2        406
3     3        470
4     4        236
5     5        274

如果这不是想要的结果,请提供想要的结果,如果可能的话,请解释你是如何得到的(仅来自示例数据)

© www.soinside.com 2019 - 2024. All rights reserved.