本文介绍了识别和计算咒语(每组中的不同事件)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我正在寻找一种有效的方法来识别时间序列中的法术/符文。在下图中,前三列是我拥有的,第四列spell
是我要计算的。我已尝试使用dplyr
的lead
和lag
,但这太复杂了。我尝试了rle
,但一无所获。
ReprEx
df <- structure(list(time = structure(c(1538876340, 1538876400,
1538876460,1538876520, 1538876580, 1538876640, 1538876700, 1538876760, 1526824800,
1526824860, 1526824920, 1526824980, 1526825040, 1526825100), class = c("POSIXct",
"POSIXt"), tzone = "UTC"), group = c("A", "A", "A", "A", "A", "A", "A", "A", "B",
"B", "B", "B", "B", "B"), is.5 = c(0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1)),
class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -14L))
我更喜欢tidyverse
解决方案。
假设
数据先按
排序group
排序,然后按time
每个组内的
time
中没有差距
更新
感谢您的贡献。我已经针对完整数据(n=2,583,360)对一些建议的方法进行了计时
- @markus的
rle
方法花费了0.53秒 - @M-M的
cumsum
方法花费了2.85秒 - @Mr Flick的函数逼近耗时0.66秒
- @tmfmnk的
rle
和dense_rank
取0.89
我最终选择了@markus的(1),因为它速度很快,而且仍然有点直观(主观)。(2)@M-M最好地满足了我对dplyr
解的渴望,尽管它的计算效率很低。
推荐答案
一个选项使用rle
library(dplyr)
df %>%
group_by(group) %>%
mutate(
spell = {
r <- rle(is.5)
r$values <- cumsum(r$values) * r$values
inverse.rle(r)
}
)
# A tibble: 14 x 4
# Groups: group [2]
# time group is.5 spell
# <dttm> <chr> <dbl> <dbl>
# 1 2018-10-07 01:39:00 A 0 0
# 2 2018-10-07 01:40:00 A 1 1
# 3 2018-10-07 01:41:00 A 1 1
# 4 2018-10-07 01:42:00 A 0 0
# 5 2018-10-07 01:43:00 A 1 2
# 6 2018-10-07 01:44:00 A 0 0
# 7 2018-10-07 01:45:00 A 0 0
# 8 2018-10-07 01:46:00 A 1 3
# 9 2018-05-20 14:00:00 B 0 0
#10 2018-05-20 14:01:00 B 0 0
#11 2018-05-20 14:02:00 B 1 1
#12 2018-05-20 14:03:00 B 1 1
#13 2018-05-20 14:04:00 B 0 0
#14 2018-05-20 14:05:00 B 1 2
您要求
tidyverse
解决方案,但是如果您关心速度,则可以使用data.table
。语法非常相似library(data.table)
setDT(df)[, spell := {
r <- rle(is.5)
r$values <- cumsum(r$values) * r$values
inverse.rle(r)
}, by = group][] # the [] at the end prints the data.table
说明
当我们调用
r <- rle(df$is.5)
我们得到的结果是
r
#Run Length Encoding
# lengths: int [1:10] 1 2 1 1 2 1 2 2 1 1
# values : num [1:10] 0 1 0 1 0 1 0 1 0 1
我们需要将values
替换为累计和,其中values == 1
应为零,否则values
应为零。
我们可以将cumsum(r$values)
与r$values
相乘,其中后者是0
和1
的向量。
r$values <- cumsum(r$values) * r$values
r$values
# [1] 0 1 0 2 0 3 0 4 0 5
最后,我们调用inverse.rle
返回与is.5
长度相同的向量。
inverse.rle(r)
# [1] 0 1 1 0 2 0 0 3 0 0 4 4 0 5
我们每隔group
都这样做。
这篇关于识别和计算咒语(每组中的不同事件)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!