使用数据框中的apply替换for循环

时间:2016-03-31 16:14:24

标签: r performance for-loop apply

我正在努力提高我必须经常运行的基本任务的性能。我有一个数据框'测试'看起来像这样:

        pair_id rr  im  db
    1   A0A0B5JQ66_A0A0B5JFG2   NA  yes NA
    2   A0A024RA76_A0A024RA76   NA  yes NA
    3   A0A068F1B9_A0A068F1B9   NA  yes NA
    4   A0A098_A0A098   NA  yes NA
    5   A0A0B5JJY8_A0A0B5JFB4   yes NA  NA
    6   A0A0B5JK11_A0A0B5JK11   yes NA  NA
    7   A0A0B5JK74_A0A0B5JFG2   yes NA  NA
    8   A0A0B5JK74_A0A0B5JK74   yes NA  NA
    9   A0A0B5JKA2_A0A0B5JF96   NA  yes NA
    10  A0A0B5JKA2_A0A0B5JK74   NA  yes NA
    11  A0A0B5JPZ7_A0A0B5JFG2   yes yes NA
    12  A0A0B5JPZ7_A0A0B5JK74   NA  yes NA
    13  A0A0B5JPZ7_A0A0B5JKA2   NA  yes NA
    14  A0A0B5JPZ7_A0A0B5JPZ7   NA  yes NA
    15  A0A0B5JQ10_A0A0B5JK95   yes yes NA
    16  A0A0B5JQ14_A0A0B5JFB4   NA  yes NA
    17  A0A0B5JQ25_A0A0B5JFB4   NA  yes NA
    18  A0A0B5JQ25_A0A0B5JFB8   NA  yes NA
    19  A0A0B5JQ25_A0A0B5JK29   NA  yes NA
    20  A0A0B5JQ29_A0A0B5JQ14   yes NA  NA

我需要比较第2列和第3列(' rr'以及' im')然后根据此比较设置第4列的值。为此,我创建了以下函数,名为' compare':

compare <- function(v){
  if (v[1]=="yes" & is.na(v[2])){
    db <- "rr"
  }
  else if (v[2]=="yes" & is.na(v[1])){
    db <- "im"
  }
  else if (v[1]=="yes" & v[2]=="yes"){
    db <- "both"
  }
  else {
    db <- "check"
  }
  db
}

它只需要两个元素的向量作为输入,检查哪一个具有&#34;是&#34;哪一个是空的(如果有的话)并返回一个可以分配给第三列的值。

现在我一直在使用这个&#39;测试&#39;使用for循环:

for (i in 1:nrow(test)){
        test[i,]$db <- compare(test[i,2:3])
} 

然而,当我的数据框变得很大(我必须管理一些超过700000行)并且需要花费大量时间来计算时,这个解决方案非常低效。我一直试图在“应用”的不同变体下使用我的功能。家庭,但无法使它工作,因为我是R的新手,我对这套功能没有多少经验。有关提高绩效的替代方案的任何提示吗?

3 个答案:

答案 0 :(得分:2)

您可以使用应用功能

test$db <- apply(test[, 2:3], compare)

但这不会快得多

更快的解决方案是使用矢量化

test$db <- "check" #make column of default values
test$db[test$rr == "yes" & is.na(test$im)] <- "rr"
test$db[test$im == "yes" & is.na(test$rr)] <- "im"
test$db[test$rr == "yes" & test$im == "yes"] <- "both"

答案 1 :(得分:1)

感谢所有给出答案的人。我实际上尝试并使用10000行长的测试数据帧比较了使用原始for循环建议的不同方法。这就是我得到的:

                   user   system elapsed
    ptm_loop      4.831    0.551   5.390
    ptm_apply     0.055    0.002   0.056
    ptm_vect      0.046    0.001   0.046
    ptm_dplyr     0.009    0.000   0.009

ptm当然是处理时间的缩写,并且每个提议的解决方案都以描述性缩写列出。所有这些都显着提升了性能,但似乎到目前为止最快的解决方案是Psidom提出的基于dplyr的建议。

答案 2 :(得分:0)

您可能想尝试一下。它应该会提升你的性能。

library(dplyr) test <- mutate(test, db = ifelse(rr == "yes" & is.na(im), "rr", ifelse(is.na(rr) & im == "yes", "im", ifelse(rr == "yes" & im == "yes", "both", "check"))))