【问题标题】:R convert nested for loop to lapply() for better performanceR 将嵌套的 for 循环转换为 lapply() 以获得更好的性能
【发布时间】:2018-02-01 22:35:11
【问题描述】:

出于速度原因,我在将嵌套的 for 循环转换为 lapply() 时遇到困难。

我有 2 个data.tables 循环遍历每一行以比较其内容,如果相等,则进行一些计算。我花了 10 多分钟来计算大约 1000 行和 360 行的数据集。

在这个最小的例子中,它不到一秒,但每行只有 3 行:

library(data.table)
library(tictoc)

name <- c(rep("apple",2), rep("banana",2), rep("citrus", 2))
stim <- c("nc","alk" ,"nc",  "lem", "haz", "nc")
vis <- c(1, 1, 1, 1, 6, 7)
f <-c(2,2,2,1,3,3)
g <-c(2,2,2,2,4,4)
h <- c(rep(2,6))
value<- c(5,10,5,10,10,5)
  
tab <- data.table(name, stim, vis, f,g,h,value)

tab1 <- tab[stim == "nc"]
tab2 <- tab[!(stim == "nc")]


tic("looping")

for(i in 1:NROW(tab1)){
  for (n in 1: NROW((tab2))){
    if(identical(tab2[n,name],tab1[i,name])
       
    & identical(tab2[n,vis],tab1[i,vis])
      & identical(tab2[n,3:(length(tab2)-1), with = FALSE],tab1[i,3:(length(tab1)-1), with = FALSE])){
       
      tab2[n,"value"] <- tab2[n, "value"] - tab1[i,"value"]
    }  
  }
  
}
toc()

我一直在关注apply 家庭,这似乎是一种方法,但我不知道如何解决它。感谢您的帮助!

编辑: 在循环之前,tab1 看起来像这样:

     name stim vis f g h value
1:  apple   nc   1 2 2 2     5
2: banana   nc   1 2 2 2     5
3: citrus   nc   7 3 4 2     5

tab2 看起来像这样:

     name stim vis f g h value
1:  apple  alk   1 2 2 2    10
2: banana  lem   1 1 2 2    10
3: citrus  haz   6 3 4 2    10

循环后(只对tab2感兴趣),预期结果:

     name stim vis f g h value
1:  apple  alk   1 2 2 2     5
2: banana  lem   1 1 2 2    10
3: citrus  haz   6 3 4 2    10

【问题讨论】:

  • 你能解释一下使用的条件吗?
  • 例如,如果我想将tab1 的每一行与整个tab2 绑定,那么我会执行以下操作:Map(function(x,y)cbind(x[rep(1,nrow(y))],y),split(tab1,1:3),list(tab2))。因此,您需要定义您需要为 tab1 和 tab2 执行的操作,其中有 cbind 函数
  • 我不想绑定任何东西。我正在检查两个不同 data.table 的每一行的某些列是否相同,如果是,则对这两行进行一些计算。
  • 我只是举一个 cbind 的例子..
  • 对不起。我误会了。我会尝试你的方法并回来

标签: r performance for-loop nested-loops


【解决方案1】:

应用循环不会加快您的计算速度。事实上它会让它变慢,因为你已经定义了你的 data.frames 并且你只是在替换值。

相反,我建议使用合并的替代方法。 (注意:您的代码有一些错误并且没有运行,所以我希望我正确地解释了您的意图。如果没有,请告诉我)。

> merge(tab1, tab2, by = c("name", "vis", "f", "g", "h"), suffixes=c("1", "2"), all.y=T) -> tab3
> tab3$value <- tab3$value2-tab3$value1
> tab3
    name vis f g h stim1 value1 stim2 value2 value
1  apple   1 2 2 2    nc      5   alk     10     5
2 banana   1 1 2 2  <NA>     NA   lem     10    NA
3 citrus   6 3 4 2  <NA>     NA   haz     10    NA

您可以从那里随意重命名或移动列。

【讨论】:

  • 错误来自缺少库。对不起,初学者的错误。我试过你的方法,效果很好。我把时间缩短到不到 1 秒!
  • 因为这是一个最小的例子,我现在正在处理需要减去的多个列,例如: col 2- col 5, col3-col6 用于多对列。我正在尝试类似:tab3[,3:5] = tab3[,3:5] - tab3[,7:9] 但由于语法错误而无法正常工作。
  • 您可以通过索引或负索引来减去列。例如:tab3 &lt;- tab3[,c(-2,-3)] 将减去第 2 列和第 3 列。
猜你喜欢
  • 1970-01-01
  • 2021-08-09
  • 1970-01-01
  • 2022-01-24
  • 1970-01-01
  • 2020-06-03
  • 2017-07-12
相关资源
最近更新 更多