我有一些带有开始时间和结束时间的事件记录的数据框。 我想将记录扩展为多个固定时间间隔的记录,比如说一个小时的间隔。 例如,假设数据框包含两个记录:
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函数时,它就可以工作。
有什么建议吗?
谢谢
答案 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