有效的dplyr基于另一个数据帧中的间隔在一个数据帧中进行汇总

时间:2016-10-07 20:10:44

标签: r dplyr

我经常需要根据定义为"事件"的时间间隔来计算时间序列数据集中许多参数的均值。在第二个数据集中。

下面的示例代码说明了我当前的方法,它可以很好地工作。

虽然我的数据集会增加,但我想知道是否有更有效的方法(例如在我的电脑上运行约30秒)。

保持在dplyr / tidyverse内是很重要的(数据表格方式很受欢迎,但是真的很有帮助)。

  library(tidyverse)

  #generate time series data
  data <- bind_cols(
    data_frame(td=seq(from = as.POSIXct("2010-01-01 00:00"), 
                                 to = as.POSIXct("2010-12-31 23:59"), 
                                 by = 60)),
  as_data_frame(replicate(20,runif(525600))))

  #generate events
  events <- data_frame(
  event = as.character(1:669),
  start_cet = seq(from = as.POSIXct("2010-01-01 00:00"),
          to = as.POSIXct("2010-12-01 00:00"),
          by = 43200),
  stop_cet = seq(from = as.POSIXct("2010-01-01 02:00"),
           to = as.POSIXct("2010-12-01 02:00"),
           by = 43200)
  )

  #calculate means of data columns within event intervals
  system.time(
  means <- events %>%
  rowwise() %>%
  mutate(s = list(data %>% select(td) %>% filter(td >= start_cet & td < stop_cet))) %>%
  unnest() %>%
  select(event,td) %>%
  left_join(.,data) %>%
  group_by(event) %>%
  summarise_at(vars(V1:V20),funs(mean=mean)) %>%
  ungroup()
  )

2 个答案:

答案 0 :(得分:1)

这是一种使用data.table(1.9.7+)版library(data.table) setDT(data); setDT(events) data[events, on = .(td >= start_cet, td <= stop_cet), lapply(.SD, mean), by = .EACHI] 执行此操作的有效方法,运行OP示例大约需要10毫秒:

const router      = require('express').Router(),
form    = require('../api/form');

router.post('/api/submit', (req, res) => {
    form.submit(req, res);
});

module.exports = router;

答案 1 :(得分:0)

大约3年后对自己的答案...

上述dplyr解决方案中的mutate步骤不必要地复杂,正如JDLong的评论中所述。我现在使用

means2 <- events %>%
  rowwise() %>%
  mutate(td = list(seq(start_cet, stop_cet - 60, "min"))) %>%
  unnest() %>%
  select(event,td) %>%
  left_join(.,data) %>%
  group_by(event) %>%
  summarise_at(vars(V1:V20),funs(mean=mean)) %>%
  ungroup()

,比上面的旧dplyr解决方案快25倍。

dt解决方案仍然比此dplyr链快约5倍。但是,输出有点混乱。而不是包含事件的列,我得到了两列td,分别是事件的开始和结束时间。一些dt专家知道如何解决此问题?