计算 R 中的连续日期以确定事件的长度
Counting sequential dates in R to determine the length of an event
我有一个包含给定事件发生日期的数据框。有些活动会持续好几天,我想根据开始日期和总长度(以天为单位)总结每个活动。
我想从这里开始:
Date
2020-01-01
2020-01-02
2020-01-03
2020-01-15
2020-01-20
2020-01-21
为此:
StartDate
EventLength
2020-01-01
3
2020-01-15
1
2020-01-20
2
我尝试了各种方法 aggregate、ave、seq_along 和 lag,但我还没有设法获得在日期不连续时重置的事件长度计数。
示例数据框的代码,以防有帮助:
Date <- c("2020-01-01", "2020-01-02", "2020-01-03", "2020-01-15", "2020-01-20", "2020-01-21")
df <- data.frame(Date)
df$Date <- as.Date(df$Date, origin = "1970-01-01")
您可以 split
cumsum(c(0, diff(df$Date) != 1)
,然后取第一个日期并将其与 length
合并,假设 日期已排序 。
do.call(rbind, lapply(split(df$Date, cumsum(c(0, diff(df$Date) != 1))),
function(x) data.frame(StartDate=x[1], EventLength=length(x))))
# StartDate EventLength
#0 2020-01-01 3
#1 2020-01-15 1
#2 2020-01-20 2
或使用 rle
的其他选项:
i <- cumsum(c(0, diff(df$Date) != 1))
data.frame(StartDate = df$Date[c(1, diff(i)) == 1], EventLength=rle(i)$lengths)
# StartDate EventLength
#1 2020-01-01 3
#2 2020-01-15 1
#3 2020-01-20 2
这是一个基本的 R 解决方案,其中包含一个 cumsum
技巧,然后是 ave/table
。
d <- c(0, diff(df$Date) != 1)
res <- ave(df$Date, cumsum(d), FUN = function(x) x[1])
res <- as.data.frame(table(a))
names(res) <- c("Date", "EventLength")
res
# Date EventLength
#1 2020-01-01 3
#2 2020-01-15 1
#3 2020-01-20 2
我提出 dplyr
方法,顺便说一下,它与@Rui 的方法非常相似
df %>% mutate(dummy = c(0, diff(Date))) %>%
group_by(grp = cumsum(dummy != 1)) %>%
summarise(Date = first(Date),
event_count = n(), .groups = 'drop')
# A tibble: 3 x 3
grp Date event_count
<int> <date> <int>
1 1 2020-01-01 3
2 2 2020-01-15 1
3 3 2020-01-20 2
我有一个包含给定事件发生日期的数据框。有些活动会持续好几天,我想根据开始日期和总长度(以天为单位)总结每个活动。
我想从这里开始:
Date |
---|
2020-01-01 |
2020-01-02 |
2020-01-03 |
2020-01-15 |
2020-01-20 |
2020-01-21 |
为此:
StartDate | EventLength |
---|---|
2020-01-01 | 3 |
2020-01-15 | 1 |
2020-01-20 | 2 |
我尝试了各种方法 aggregate、ave、seq_along 和 lag,但我还没有设法获得在日期不连续时重置的事件长度计数。
示例数据框的代码,以防有帮助:
Date <- c("2020-01-01", "2020-01-02", "2020-01-03", "2020-01-15", "2020-01-20", "2020-01-21")
df <- data.frame(Date)
df$Date <- as.Date(df$Date, origin = "1970-01-01")
您可以 split
cumsum(c(0, diff(df$Date) != 1)
,然后取第一个日期并将其与 length
合并,假设 日期已排序 。
do.call(rbind, lapply(split(df$Date, cumsum(c(0, diff(df$Date) != 1))),
function(x) data.frame(StartDate=x[1], EventLength=length(x))))
# StartDate EventLength
#0 2020-01-01 3
#1 2020-01-15 1
#2 2020-01-20 2
或使用 rle
的其他选项:
i <- cumsum(c(0, diff(df$Date) != 1))
data.frame(StartDate = df$Date[c(1, diff(i)) == 1], EventLength=rle(i)$lengths)
# StartDate EventLength
#1 2020-01-01 3
#2 2020-01-15 1
#3 2020-01-20 2
这是一个基本的 R 解决方案,其中包含一个 cumsum
技巧,然后是 ave/table
。
d <- c(0, diff(df$Date) != 1)
res <- ave(df$Date, cumsum(d), FUN = function(x) x[1])
res <- as.data.frame(table(a))
names(res) <- c("Date", "EventLength")
res
# Date EventLength
#1 2020-01-01 3
#2 2020-01-15 1
#3 2020-01-20 2
我提出 dplyr
方法,顺便说一下,它与@Rui 的方法非常相似
df %>% mutate(dummy = c(0, diff(Date))) %>%
group_by(grp = cumsum(dummy != 1)) %>%
summarise(Date = first(Date),
event_count = n(), .groups = 'drop')
# A tibble: 3 x 3
grp Date event_count
<int> <date> <int>
1 1 2020-01-01 3
2 2 2020-01-15 1
3 3 2020-01-20 2