R中有没有办法计算分组后日期连续的行数?
Is there a way in R to count the number of rows where dates are consecutive after grouping?
我正在尝试计算客户的停留时间;这不是数据中的一个字段,但每一行都是一个单独的日子,连续的日子属于同一个“停留” - 所以如果同一客户有 5 行都是连续的日子,他们的停留时间将为 5天。然而,有很多不同的客户,每个客户可能有不止一次的停留——如果服务日期不是连续的,它们将被算作单独的停留。例如:
client id
date of service
123
1/1/22
123
1/2/22
123
1/3/22
123
1/4/22
123
1/5/22
456
1/1/22
456
1/4/22
456
1/5/22
456
1/6/22
789
1/1/22
789
1/2/22
789
1/5/22
789
1/6/22
789
1/9/22
789
1/10/22
对于这个假数据,客户“123”将有 1 次停留,停留时间为 5 天;客户“456”将有 2 次停留,一次停留时间为 1 天,另一次停留时间为 3 天;客户“789”将有 3 次入住,每次入住时间为 2 天。
我的计划是按客户 ID 对数据进行分组,然后按服务日期排序,然后可能使用某种 for 循环来检查服务日期是否晚于 1 天,如果是,则添加它到停留时间,如果不是,则开始新的“停留”;但这看起来笨拙且效率低下,而且我不完全确定它是否可以正常工作。数据有几千行,客户端有几百个。
理想情况下,我的输出将提供客户 ID 及其计算的停留时间;如果可能的话,最好让输出也提供每次住宿的开始日期。
有没有办法在 R 中完成此操作?
感谢您提供的任何帮助。谢谢!
我们可以使用
library(dplyr)
library(lubridate)
df1 %>%
mutate(dateofservice = mdy(dateofservice)) %>%
group_by(clientid) %>%
mutate(grp = cumsum(c(TRUE, diff(dateofservice) != 1))) %>%
group_by(grp, .add = TRUE) %>%
summarise(len = n(), start_date = first(dateofservice), .groups = 'drop')
-输出
# A tibble: 6 × 4
clientid grp len start_date
<int> <int> <int> <date>
1 123 1 5 2022-01-01
2 456 1 1 2022-01-01
3 456 2 3 2022-01-04
4 789 1 2 2022-01-01
5 789 2 2 2022-01-05
6 789 3 2 2022-01-09
数据
df1 <- structure(list(clientid = c(123L, 123L, 123L, 123L, 123L,
456L,
456L, 456L, 456L, 789L, 789L, 789L, 789L, 789L, 789L),
dateofservice = c("1/1/22",
"1/2/22", "1/3/22", "1/4/22", "1/5/22", "1/1/22", "1/4/22", "1/5/22",
"1/6/22", "1/1/22", "1/2/22", "1/5/22", "1/6/22", "1/9/22", "1/10/22"
)), class = "data.frame", row.names = c(NA, -15L))
我正在尝试计算客户的停留时间;这不是数据中的一个字段,但每一行都是一个单独的日子,连续的日子属于同一个“停留” - 所以如果同一客户有 5 行都是连续的日子,他们的停留时间将为 5天。然而,有很多不同的客户,每个客户可能有不止一次的停留——如果服务日期不是连续的,它们将被算作单独的停留。例如:
client id | date of service |
---|---|
123 | 1/1/22 |
123 | 1/2/22 |
123 | 1/3/22 |
123 | 1/4/22 |
123 | 1/5/22 |
456 | 1/1/22 |
456 | 1/4/22 |
456 | 1/5/22 |
456 | 1/6/22 |
789 | 1/1/22 |
789 | 1/2/22 |
789 | 1/5/22 |
789 | 1/6/22 |
789 | 1/9/22 |
789 | 1/10/22 |
对于这个假数据,客户“123”将有 1 次停留,停留时间为 5 天;客户“456”将有 2 次停留,一次停留时间为 1 天,另一次停留时间为 3 天;客户“789”将有 3 次入住,每次入住时间为 2 天。
我的计划是按客户 ID 对数据进行分组,然后按服务日期排序,然后可能使用某种 for 循环来检查服务日期是否晚于 1 天,如果是,则添加它到停留时间,如果不是,则开始新的“停留”;但这看起来笨拙且效率低下,而且我不完全确定它是否可以正常工作。数据有几千行,客户端有几百个。
理想情况下,我的输出将提供客户 ID 及其计算的停留时间;如果可能的话,最好让输出也提供每次住宿的开始日期。
有没有办法在 R 中完成此操作?
感谢您提供的任何帮助。谢谢!
我们可以使用
library(dplyr)
library(lubridate)
df1 %>%
mutate(dateofservice = mdy(dateofservice)) %>%
group_by(clientid) %>%
mutate(grp = cumsum(c(TRUE, diff(dateofservice) != 1))) %>%
group_by(grp, .add = TRUE) %>%
summarise(len = n(), start_date = first(dateofservice), .groups = 'drop')
-输出
# A tibble: 6 × 4
clientid grp len start_date
<int> <int> <int> <date>
1 123 1 5 2022-01-01
2 456 1 1 2022-01-01
3 456 2 3 2022-01-04
4 789 1 2 2022-01-01
5 789 2 2 2022-01-05
6 789 3 2 2022-01-09
数据
df1 <- structure(list(clientid = c(123L, 123L, 123L, 123L, 123L,
456L,
456L, 456L, 456L, 789L, 789L, 789L, 789L, 789L, 789L),
dateofservice = c("1/1/22",
"1/2/22", "1/3/22", "1/4/22", "1/5/22", "1/1/22", "1/4/22", "1/5/22",
"1/6/22", "1/1/22", "1/2/22", "1/5/22", "1/6/22", "1/9/22", "1/10/22"
)), class = "data.frame", row.names = c(NA, -15L))