用 dplyr 和 rle 总结连续失败
Summarize consecutive failures with dplyr and rle
我正在尝试构建一个客户流失模型,其中包含每个客户的最大连续用户体验失败次数和遇到的问题。这是我的简化数据和所需的输出:
library(dplyr)
df <- data.frame(customerId = c(1,2,2,3,3,3), date = c('2015-01-01','2015-02-01','2015-02-02', '2015-03-01','2015-03-02','2015-03-03'),isFailure = c(0,0,1,0,1,1))
> df
customerId date isFailure
1 1 2015-01-01 0
2 2 2015-02-01 0
3 2 2015-02-02 1
4 3 2015-03-01 0
5 3 2015-03-02 1
6 3 2015-03-03 1
期望的结果:
> desired.df
customerId maxConsecutiveFailures
1 1 0
2 2 1
3 3 2
我有点不知所措,搜索其他 rle 问题对我没有帮助 - 这就是我 "expecting" 类似的解决方案:
df %>%
group_by(customerId) %>%
summarise(maxConsecutiveFailures =
max(rle(isFailure[isFailure == 1])$lengths))
我们按 'customerId' 分组并使用 do
在 'isFailure' 列上执行 rle
。为 values
(lengths[values]
) 提取 'TRUE' 的 lengths
,并创建具有 if/else
条件的 'Max' 列到 return 0 对于那些没有任何 1 值的人。
df %>%
group_by(customerId) %>%
do({tmp <- with(rle(.$isFailure==1), lengths[values])
data.frame(customerId= .$customerId, Max=if(length(tmp)==0) 0
else max(tmp)) }) %>%
slice(1L)
# customerId Max
#1 1 0
#2 2 1
#3 3 2
这是我的尝试,仅使用标准 dplyr
函数:
df %>%
# grouping key(s):
group_by(customerId) %>%
# check if there is any value change
# if yes, a new sequence id is generated through cumsum
mutate(last_one = lag(isFailure, 1, default = 100),
not_eq = last_one != isFailure,
seq = cumsum(not_eq)) %>%
# the following is just to find the largest sequence
count(customerId, isFailure, seq) %>%
group_by(customerId, isFailure) %>%
summarise(max_consecutive_event = max(n))
输出:
# A tibble: 5 x 3
# Groups: customerId [3]
customerId isFailure max_consecutive_event
<dbl> <dbl> <int>
1 1 0 1
2 2 0 1
3 2 1 1
4 3 0 1
5 3 1 2
isFailure
值的最终过滤器将产生想要的结果(不过需要添加回 0
失败计数客户)。
该脚本可以采用 isFailure
列的任何值,并计算具有相同值的最大连续天数。
我正在尝试构建一个客户流失模型,其中包含每个客户的最大连续用户体验失败次数和遇到的问题。这是我的简化数据和所需的输出:
library(dplyr)
df <- data.frame(customerId = c(1,2,2,3,3,3), date = c('2015-01-01','2015-02-01','2015-02-02', '2015-03-01','2015-03-02','2015-03-03'),isFailure = c(0,0,1,0,1,1))
> df
customerId date isFailure
1 1 2015-01-01 0
2 2 2015-02-01 0
3 2 2015-02-02 1
4 3 2015-03-01 0
5 3 2015-03-02 1
6 3 2015-03-03 1
期望的结果:
> desired.df
customerId maxConsecutiveFailures
1 1 0
2 2 1
3 3 2
我有点不知所措,搜索其他 rle 问题对我没有帮助 - 这就是我 "expecting" 类似的解决方案:
df %>%
group_by(customerId) %>%
summarise(maxConsecutiveFailures =
max(rle(isFailure[isFailure == 1])$lengths))
我们按 'customerId' 分组并使用 do
在 'isFailure' 列上执行 rle
。为 values
(lengths[values]
) 提取 'TRUE' 的 lengths
,并创建具有 if/else
条件的 'Max' 列到 return 0 对于那些没有任何 1 值的人。
df %>%
group_by(customerId) %>%
do({tmp <- with(rle(.$isFailure==1), lengths[values])
data.frame(customerId= .$customerId, Max=if(length(tmp)==0) 0
else max(tmp)) }) %>%
slice(1L)
# customerId Max
#1 1 0
#2 2 1
#3 3 2
这是我的尝试,仅使用标准 dplyr
函数:
df %>%
# grouping key(s):
group_by(customerId) %>%
# check if there is any value change
# if yes, a new sequence id is generated through cumsum
mutate(last_one = lag(isFailure, 1, default = 100),
not_eq = last_one != isFailure,
seq = cumsum(not_eq)) %>%
# the following is just to find the largest sequence
count(customerId, isFailure, seq) %>%
group_by(customerId, isFailure) %>%
summarise(max_consecutive_event = max(n))
输出:
# A tibble: 5 x 3
# Groups: customerId [3]
customerId isFailure max_consecutive_event
<dbl> <dbl> <int>
1 1 0 1
2 2 0 1
3 2 1 1
4 3 0 1
5 3 1 2
isFailure
值的最终过滤器将产生想要的结果(不过需要添加回 0
失败计数客户)。
该脚本可以采用 isFailure
列的任何值,并计算具有相同值的最大连续天数。