在 R 中重复过滤数据框的快速方法
Quick way to repeatedly filter a data frame in R
我有一个数据框,由一系列 100K+ 观察值组成,每个观察值都有一个 POSIXt 时间戳。观察结果按 date/time 顺序排列。观察之间的时间间隔不同。我需要在数据框中创建一个新向量,每个观察的值是观察次数,在该观察后的 5 分钟内,满足一些标准(在下面的示例中,目标向量的值需要为正确。在实际问题中,条件更为复杂,并且取决于数据框中多个向量的值)。
目前,以下示例的性能非常糟糕:
library(plyr)
set.seed(1)
observations = 1000
startTime = Sys.time()
data <- as.data.frame(matrix(0, ncol = 3, nrow = observations))
colnames(data) <- c("timeStamp", "goal", "derived")
data$goal <- (runif(observations,0,1.1) > 1.0)
data$timeStamp <- runif(observations,1,90*60) + startTime
data <- arrange(data, timeStamp)
for(i in 1:nrow(data))
{
data[i,"derived"] <- filter(data, goal == TRUE, timeStamp > data[[i,"timeStamp"]], timeStamp < (data[[i,"timeStamp"]] + (5 * 60))) %>% nrow
}
summary(data)
是否可以在不在循环内创建新数据帧的情况下执行数据过滤操作?
有没有更好的方法来优化流程?
理想情况下,有没有办法消除数据框行的循环?
一种方法是使用 非相等连接:
library(data.table)
setorder(setDT(dat), timeStamp)
dat[, derived := dat[.(goal = TRUE, ts1 = timeStamp, ts2 = timeStamp + 5 * 60),
on = .(goal, timeStamp >= ts1, timeStamp <= ts2), .N, by = .EACHI]$N][]
dat
timeStamp goal derived
1: 2017-11-24 07:19:47 TRUE 3
2: 2017-11-24 07:19:48 FALSE 2
3: 2017-11-24 07:19:51 FALSE 2
4: 2017-11-24 07:20:04 FALSE 2
5: 2017-11-24 07:20:06 FALSE 2
---
996: 2017-11-24 08:49:06 TRUE 2
997: 2017-11-24 08:49:13 FALSE 1
998: 2017-11-24 08:49:16 TRUE 1
999: 2017-11-24 08:49:25 FALSE 0
1000: 2017-11-24 08:49:40 FALSE 0
可重现的数据
observations <- 1000
startTime <- as.POSIXct("2017-11-24 07:19:44")
set.seed(123L)
dat <- data.frame(
timeStamp = runif(observations, 1, 90*60) + startTime,
goal = runif(observations, 0, 1.1) > 1.0
)
我有一个数据框,由一系列 100K+ 观察值组成,每个观察值都有一个 POSIXt 时间戳。观察结果按 date/time 顺序排列。观察之间的时间间隔不同。我需要在数据框中创建一个新向量,每个观察的值是观察次数,在该观察后的 5 分钟内,满足一些标准(在下面的示例中,目标向量的值需要为正确。在实际问题中,条件更为复杂,并且取决于数据框中多个向量的值)。
目前,以下示例的性能非常糟糕:
library(plyr)
set.seed(1)
observations = 1000
startTime = Sys.time()
data <- as.data.frame(matrix(0, ncol = 3, nrow = observations))
colnames(data) <- c("timeStamp", "goal", "derived")
data$goal <- (runif(observations,0,1.1) > 1.0)
data$timeStamp <- runif(observations,1,90*60) + startTime
data <- arrange(data, timeStamp)
for(i in 1:nrow(data))
{
data[i,"derived"] <- filter(data, goal == TRUE, timeStamp > data[[i,"timeStamp"]], timeStamp < (data[[i,"timeStamp"]] + (5 * 60))) %>% nrow
}
summary(data)
是否可以在不在循环内创建新数据帧的情况下执行数据过滤操作?
有没有更好的方法来优化流程?
理想情况下,有没有办法消除数据框行的循环?
一种方法是使用 非相等连接:
library(data.table)
setorder(setDT(dat), timeStamp)
dat[, derived := dat[.(goal = TRUE, ts1 = timeStamp, ts2 = timeStamp + 5 * 60),
on = .(goal, timeStamp >= ts1, timeStamp <= ts2), .N, by = .EACHI]$N][]
dat
timeStamp goal derived 1: 2017-11-24 07:19:47 TRUE 3 2: 2017-11-24 07:19:48 FALSE 2 3: 2017-11-24 07:19:51 FALSE 2 4: 2017-11-24 07:20:04 FALSE 2 5: 2017-11-24 07:20:06 FALSE 2 --- 996: 2017-11-24 08:49:06 TRUE 2 997: 2017-11-24 08:49:13 FALSE 1 998: 2017-11-24 08:49:16 TRUE 1 999: 2017-11-24 08:49:25 FALSE 0 1000: 2017-11-24 08:49:40 FALSE 0
可重现的数据
observations <- 1000
startTime <- as.POSIXct("2017-11-24 07:19:44")
set.seed(123L)
dat <- data.frame(
timeStamp = runif(observations, 1, 90*60) + startTime,
goal = runif(observations, 0, 1.1) > 1.0
)