在data.table中使用:= with paste()

Ric*_*son 10 r data.table

我已经开始使用data.table大型人口模型.到目前为止,我印象深刻,因为使用data.table结构会使我的模拟运行时间缩短约30%.我正在尝试进一步优化我的代码并包含一个简化的示例.我的两个问题是:

  1. 是否可以使用:=此代码的运算符?
  2. 使用:=操作员会更快(但是,如果我能够回答我的第一个问题,我应该能够回答我的问题2!)?

我在运行Windows 7 data.table版本1.9.4 的计算机上使用R版本3.1.2 .

这是我可重复的例子:

library(data.table)

## Create  example table and set initial conditions
nYears = 10
exampleTable = data.table(Site = paste("Site", 1:3))
exampleTable[ , growthRate := c(1.1, 1.2, 1.3), ]
exampleTable[ , c(paste("popYears", 0:nYears, sep = "")) := 0, ]

exampleTable[ , "popYears0" := c(10, 12, 13)] # set the initial population size

for(yearIndex in 0:(nYears - 1)){
    exampleTable[[paste("popYears", yearIndex + 1, sep = "")]] <- 
    exampleTable[[paste("popYears", yearIndex, sep = "")]] * 
    exampleTable[, growthRate]
}
Run Code Online (Sandbox Code Playgroud)

我想做的事情如下:

for(yearIndex in 0:(nYears - 1)){
    exampleTable[ , paste("popYears", yearIndex + 1, sep = "") := 
    paste("popYears", yearIndex, sep = "") * growthRate, ] 
}
Run Code Online (Sandbox Code Playgroud)

但是,这不起作用,因为粘贴不起作用data.table,例如:

exampleTable[ , paste("popYears", yearIndex + 1, sep = "")]
# [1] "popYears10"
Run Code Online (Sandbox Code Playgroud)

我查看了data.table文档.FAQ的第2.9节使用cat,但这会产生空输出.

exampleTable[ , cat(paste("popYears", yearIndex + 1, sep = ""))]
# [1] popYears10NULL
Run Code Online (Sandbox Code Playgroud)

此外,我尝试搜索谷歌和rseek.org,但没有找到任何东西.如果我错过了一个明显的搜索词,我会很感激搜索提示.我总是发现搜索R运算符很难,因为搜索引擎不喜欢符号(例如," :=")和"R"可能是模糊的.

Jos*_*ien 10

## Start with 1st three columns of example data
dt <- exampleTable[,1:3,with=FALSE]

## Run for 1st five years
nYears <- 5
for(ii in seq_len(nYears)-1) {
    y0 <- as.symbol(paste0("popYears", ii))
    y1 <- paste0("popYears", ii+1)
    dt[, (y1) := eval(y0)*growthRate]
}

## Check that it worked
dt
#     Site growthRate popYears0 popYears1 popYears2 popYears3 popYears4 popYears5
#1: Site 1        1.1        10      11.0     12.10    13.310   14.6410  16.10510
#2: Site 2        1.2        12      14.4     17.28    20.736   24.8832  29.85984
#3: Site 3        1.3        13      16.9     21.97    28.561   37.1293  48.26809
Run Code Online (Sandbox Code Playgroud)

编辑:

因为set()在评论中不断提高使用速度的可能性,我会把这个额外的选项扔出去.

nYears <- 5

## Things that only need to be calculated once can be taken out of the loop
r <- dt[["growthRate"]]
yy <- paste0("popYears", seq_len(nYears+1)-1)

## A loop using set() and data.table's nice compact syntax
for(ii in seq_len(nYears)) {
    set(dt, , yy[ii+1], r*dt[[yy[ii]]])
}

## Check results
dt
#     Site growthRate popYears0 popYears1 popYears2 popYears3 popYears4 popYears5
#1: Site 1        1.1        10      11.0     12.10    13.310   14.6410  16.10510
#2: Site 2        1.2        12      14.4     17.28    20.736   24.8832  29.85984
#3: Site 3        1.3        13      16.9     21.97    28.561   37.1293  48.26809
Run Code Online (Sandbox Code Playgroud)

  • @ JoshO'Brien.别客气.再次感谢你的帮助.我查看了`set()`但决定不使用它,因为我无法弄清楚如何在其中使用`paste`.使用列号的变通方法是不可取的,因为列号很脆弱(我很难学到这一点......).此外,我正在使用`data.table`,因为我正在使用大而不是巨大的数据进行大量计算.作为`data.table`的额外奖励,一旦掌握了它,我也喜欢它的语法. (2认同)
  • @RichardErickson,你正在执行一个完整的列plonk.我真的怀疑列分配是否有帮助(因为data.table优于分配列指针,并逐列添加).我可以想到提高速度的两个地方是1)使用`set()`来避免`[.data.table`泛型方法开销(因为你似乎运行10000次左右)和2)使用` cmpFun()`关于带有for循环的函数和`set()`到字节码编译它.如果你能提供一个真实场景/数据维度的例子,我很想看看它. (2认同)
  • @Arun`set()`的*明显*缺点(或至少相对不足)是````参数中的表达式没有"直接"访问`dt`中的列.通过`dt [["var"]]`访问列然后是最有效的方法来获取它们,就像我刚刚添加的示例代码一样? (2认同)