在跨多行进行比较时,使用data.table进行循环向量化

时间:2015-02-24 17:20:25

标签: r data.table

简而言之,我正在尝试对data.table代码进行矢量化并删除2个for循环。具体来说,我正在比较两个不同的行,无法弄清楚如何向量化我的代码。以下是详细信息:

我试图计算在鱼的坐标下鱼在一条线上移动的次数。我只关心单向运动(例如,从北到南但不是从南到北)。实际数据是二维的,有数十万个观测值。我创建了一个可重复的例子。

我查看了data.table FAQ并使用"vectorize data.table"搜索了SO。如果我不是"问正确的问题" (即用正确的术语搜索),我会指出我应该搜索什么来解决我的问题。

这是我的榜样以及我目前正在做的事情:

library(data.table)
dt = data.table(
    fish = rep(c("a", "b"), each = 4),
    time = rep(c(1:4),  2),
    location = c(1, 1, 2, 2, 1, 1, 1, 1))

crossLine = 1.5 # Coordinates that I care about
dt[ , Cross := 0] ## did the fish cross the line during the previous time step?

fishes = dt[ , unique(fish)]

for(fishIndex in fishes){ # loop through each fish
    sampleTime = dt[ fishIndex == fish, time]
    nObs = length(sampleTime)
    ## In the real dataset, the no. of observations varies by fish
    for(timeIndex in 1:(nObs - 1)){ #loop through each time point
      if(dt[ fishIndex     == fish  & sampleTime[timeIndex] == time, 
             location <=  crossLine] &  
         dt[ fishIndex     == fish  & sampleTime[timeIndex + 1] == time, 
             location >  crossLine]
         ){dt[ fishIndex == fish & time == sampleTime[timeIndex + 1], 
               Cross := 1] # record if the fish crossed the line
          } 
        }
}

我理想的解决方案看起来像这样:

moveCheck <- Vectorize(function(...))
dt[ , Cross := moveCheck(location, fish)] 

fish在函数内部,以确保在鱼之间转换时不会意外记录移动。

所以,我的问题是:使用data.table语法来提高此代码的性能并删除循环的方法是什么?

1 个答案:

答案 0 :(得分:4)

这对你有用吗(它适用于OP示例,但我不确定它的代表性如何)?

dt[, cross := c(0, diff(location >= crossLine) > 0), by = fish]