我正在努力提高我必须经常运行的基本任务的性能。我有一个数据框'测试'看起来像这样:
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的新手,我对这套功能没有多少经验。有关提高绩效的替代方案的任何提示吗?
答案 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"))))