【问题标题】:Optimize comparison in R优化 R 中的比较
【发布时间】:2016-02-03 13:36:43
【问题描述】:

我还是 R 编程新手,我需要优化我的部分代码。我将在下面解释它是如何工作的。

我当前的代码太慢了

myfunc <- function(dt){
    indexes = which(dt$time == CURRENT)

    for(i in indexes){
        # columns foo, bar & baz are used to build rowname
        # and colnames
        linename = paste(dt$foo[i], "_", dt$bar[i], sep="")
        colname  = dt$baz[i]

        # related_var is the name of an other global var
        # and value is the corresponding value in
        # related_var[linename, colname]
        dt$value[i] = get(dt$related_var[i])[[linename, colname]]
    }
    return(dt)
}

如何使用它?

这不是我的代码部分,所以我只是简化了它

CURRENT = 0
MAX     = 1000
for(i in 1:MAX){
    doSomeStuffOnGlobalVars()
    # get datas from global var for this CURRENT
    dt = myfunc(dt)
    CURRENT = CURRENT + 1
}

一些解释

CURRENT (like 1,2,3,4,5,... 1000) 的所有值调用此函数,我们希望为匹配dt$time == CURRENT 的每一行更新dt 中的$value,问题是变量“varname”每CURRENT 修改一次

dt : a data.table ordered by time in the form of
    foo   bar   baz   time   related_var   value
    1     1   "toto"  1      "varname"      NA
    1     2   "toto"  1      "varname"      NA
    2     1   "tata"  1      "varname"      NA
    2     8   "toto"  1      "varname"      NA
    ...

related_var : contain the name of a global data.frame which have its 
    colnames defined by baz in dt 
    rownames defined by a combination of foo & bar (foo_bar) in dt


example of "varname" variable:
          toto   tata
    1_1    1.6    2
    1_2    42   1337
    ...    ...    ...
    10_10    3.14   1.61

我已经进行了一些更改(我在data.tableeval(parse(...)) 之前使用了data.frame)但这仍然很慢(大约 5 秒的 dt 大约 5000 行),我想知道我该怎么做优化这个,如果你有想法(R 或纯算法)

注意告诉我它是否太神秘了

编辑:我发现较慢的部分是dt$value[i] = get(dt$related_var[i])[[linename, colname]],如果我进行像justAvar = get(dt$related_var[i])[[linename, colname]] 这样的简单分配,它会变得更快,所以我现在的问题是:“R 是如何通过索引的?如果我想go to index=15 R 会遍历所有 14 个之前的元素吗?”

【问题讨论】:

  • 乍一看,我认为您可以将这个 - linename = paste(dt$foo[i], "_", dt$bar[i], sep="") - 移到循环之外,因为 paste[ 是矢量化的。并且与优化无关,但将CURRENT 作为参数传递给myfunc 会更惯用,而不是根据范围规则在父环境中找到它。
  • 据我所知,您根本不需要函数内部的for 循环(最后一条语句可能是可能,但即使这样也可以使用向量化mgetlapply 的组合。

标签: r performance optimization comparison


【解决方案1】:

首先,我会预先计算行名,我怀疑它几乎是针对整个数据表计算的。将使用 data.table 引用魔法。二是内联化和简化功能。最后,使用 data.table [i,j,by] 方法

dt <- ...

dt[, linename := paste(foo, "_", bar, sep="")]

CURRENT <- 0
MAX     <- 1000
for(i in 1:MAX) {
    doSomeStuffOnGlobalVars()
    # get datas from global var for this CURRENT

    dt[time == CURRENT, value := get(related_var)[[linename, baz]]]
    CURRENT <- CURRENT + 1
}

更新

有用的阅读:http://www.r-bloggers.com/strategies-to-speedup-r-code/

更新二

也可以在循环之前为 dt 设置键

setkey(dt, time)

【讨论】:

  • 感谢带有 linename 的示例,它运行良好,但是当我尝试在 dt[time == CURRENT, value := get(related_var)[[tried_other_level]][[linename, baz]]] 中放置更多级别时出现错误 recursive indexing failed at level 2 有没有办法像 foo$bar$baz$toto$tata$lorem$['ipsum','dolor'] 一样深入?只是想知道
  • @user3482164 坦率地说,我不知道,好的讨论似乎在r.789695.n4.nabble.com/…。您可能想继续并通过代码/数据示例等提出另一个问题
猜你喜欢
  • 1970-01-01
  • 2021-11-28
  • 1970-01-01
  • 1970-01-01
  • 2023-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多