【问题标题】:Optimizing search in time series data frame优化时间序列数据帧中的搜索
【发布时间】:2013-01-31 13:36:24
【问题描述】:

我在 R 中有一个 50 列 x 250 万行的数据框,代表一个时间序列。时间列属于 POSIXct 类。为了进行分析,我需要反复查找给定类在特定时间的系统状态。

我目前的方法如下(简化且可重现):

set.seed(1)
N <- 10000
.time <- sort(sample(1:(100*N),N))
class(.time) <- c("POSIXct", "POSIXt")
df <- data.frame(
  time=.time,
  distance1=sort(sample(1:(100*N),N)),
  distance2=sort(sample(1:(100*N),N)),
  letter=sample(letters,N,replace=TRUE)
)

# state search function
time.state <- function(df,searchtime,searchclass){
  # find all rows in between the searchtime and a while (here 10k seconds)
  # before that
  rows <- which(findInterval(df$time,c(searchtime-10000,searchtime))==1)
  # find the latest state of the given class within the search interval
  return(rev(rows)[match(T,rev(df[rows,"letter"]==searchclass))])
}  

# evaluate the function to retrieve the latest known state of the system
# at time 500,000.
df[time.state(df,500000,"a"),]

但是,拨打which 的成本很高。或者,我可以先按班级筛选,然后找到时间,但这并不会改变评估时间。根据 Rprof 的说法,大部分时间是 which==

有没有更有效的解决方案?时间点按弱递增排序。

【问题讨论】:

  • 我认为这已经很有效了。其中和 == 的复杂度是线性的。
  • 拥有 1M 行和 1000 个唯一的 letter 值,这仅需要在我的系统上查看 ms。为什么需要优化它?
  • 对于 250 万行(与行数成线性关系),调用 findInterval 大约需要 70 毫秒。我必须调用这个函数 100k-1M 次,这使得任何优化都非常受欢迎。如果你说没有,我会开始寻找解决方法。
  • 我设法找到了一个很好的解决方法,请参阅我的答案。

标签: r optimization dataframe posixct


【解决方案1】:

因为which==[都与数据帧的大小成线性关系,解决方法是生成子数据帧进行批量操作,如下:

# function that applies time.state to a series of time/class cominations
time.states <- function(df,times,classes,day.length=24){
  result <- vector("list",length(times))
  day.end <- 0
  for(i in 1:length(times)){
    if(times[i] > day.end){
      # create subset interval from 1h before to 24h after
      day.begin <- times[i]-60*60
      day.end <- times[i]+day.length*60*60
      df.subset <- df[findInterval(df$time,c(day.begin,day.end))==1,]
    }
    # save the resulting row from data frame
    result[[i]] <- df.subset[time.state(df.subset,times[i],classes[i]),]
  }
  return(do.call("rbind",result))
}

dT=diff(range(df$times))dT/day.length 很大,这会减少评估时间,系数为 dT/(day.length+1)

【讨论】:

    猜你喜欢
    • 2017-02-15
    • 1970-01-01
    • 2020-12-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-09
    • 1970-01-01
    相关资源
    最近更新 更多