本文介绍了识别和计算咒语(每组中的不同事件)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一种有效的方法来识别时间序列中的法术/符文。在下图中,前三列是我拥有的,第四列spell是我要计算的。我已尝试使用dplyrleadlag,但这太复杂了。我尝试了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解决方案。

假设

  1. 数据先按group排序,然后按time

    排序
  2. 每个组内的time中没有差距


更新

感谢您的贡献。我已经针对完整数据(n=2,583,360)对一些建议的方法进行了计时

  1. @markus的rle方法花费了0.53秒
  2. @M-M的cumsum方法花费了2.85秒
  3. @Mr Flick的函数逼近耗时0.66秒
  4. @tmfmnk的rledense_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相乘,其中后者是01的向量。

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都这样做。

这篇关于识别和计算咒语(每组中的不同事件)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-30 21:10