setDT,x [j]中的错误:作为函数的一部分执行时,下标类型“列表”无效

时间:2018-08-17 16:28:45

标签: r data.table

我有一些带有开始时间和结束时间的事件记录的数据框。 我想将记录扩展为多个固定时间间隔的记录,比如说一个小时的间隔。 例如,假设数据框包含两个记录:

EventId   Day   StartTime   EndTime
1         Mon   1           3
2         Tues  2           5

我想要的新数据框应该看起来像这样

EventId   Day    Time
1         Mon    1
1         Mon    2
2         Tues   2
2         Tues   3
2         Tues   4

我的函数使用data.table :: setDT来扩展记录,如下所示:

makeIncrementalRecords <- function(df) {
    new <- data.table::setDT(df)[,
                                 .(Time = seq(StartTime,
                                              EndTime,
                                              by = 1)),
                                 by = .(EventId, Day)]

逐行执行此操作,没有问题,并且得到了想要的结果。当我将函数作为已加载的软件包的一部分执行时,出现以下错误...

Error in x[j]: invalid subscript type 'list'

我完全困惑为什么在执行函数时此代码突然停止工作。我想这与本地功能环境有关。当我在全局环境中将数据帧创建为'df'并仅在控制台中执行setDT函数时,它就可以工作。

有什么建议吗?

谢谢

2 个答案:

答案 0 :(得分:0)

编辑

我认为这个结果就是您想要的。

structure(list(EventId = 1:2, Day = c("Mon", "Tues"), StartTime = 1:2, EndTime = c(3L, 5L)), 
          .Names = c("EventId", "Day", "StartTime", "EndTime"), 
          row.names = c(NA, -2L), class = "data.frame") -> test_df 


library(dplyr)
library(tidyr)

generate_val <- function(startT, endT){
  (seq(from = startT, to = (endT-1), by = 1))
}

test_df %>%
  rowwise() %>%
  do(new_vars = generate_val(.$StartTime, .$EndTime)) %>%
  bind_cols(test_df %>% select(-c(StartTime:EndTime))) %>%
  unnest()

# A tibble: 5 x 3
  EventId Day   new_vars
    <int> <chr>    <dbl>
1       1 Mon          1
2       1 Mon          2
3       2 Tues         2
4       2 Tues         3
5       2 Tues         4

要将其打包为一个函数,您必须遵循此处描述的NSE过程-Programming with dplyr


如果您不介意使用tidyr,则应该可以使用。对于大型数据集(行> 1百万),它可能比data.table慢一点。

library(tidyr)

test_df %>%
  gather(., key = Time_type, value = Time, -EventId, -Day)

  EventId  Day Time_type Time
1       1  Mon StartTime    1
2       2 Tues StartTime    2
3       1  Mon   EndTime    3
4       2 Tues   EndTime    5

答案 1 :(得分:0)

这里的解决方案与评论中提出的解决方案类似。

library(tidyverse)

makeIncrementalRecords <- function(data){
    data %>% 
        mutate(Time = map2(StartTime, EndTime, ~seq(.x, .y-1))) %>% 
        unnest() %>% 
        select(EventId, Day, Time)
}

makeIncrementalRecords(df)
#   EventId Day    Time
# 1       1 Mon       1
# 2       1 Mon       2
# 3       2 Tues      2
# 4       2 Tues      3
# 5       2 Tues      4

或者如果您想保留data.table

makeIncrementalRecords2 <- function(data){
    data.table::setDT(data)[, .(Time = seq(StartTime, EndTime-1, by = 1)), by = .(EventId, Day)]
}

makeIncrementalRecords2(df)
#    EventId  Day Time
# 1:       1  Mon    1
# 2:       1  Mon    2
# 3:       2 Tues    2
# 4:       2 Tues    3
# 5:       2 Tues    4