如何在R中优化和加速循环函数

时间:2017-02-16 15:12:24

标签: r performance loops optimization

我正在努力用几个名称来清理整理数据库,确切地说,1895971,其中许多都有空白和NA。

在这样做的过程中,我编写了一个似乎有效的解决方案:

for(j in 1:length(final.cons.nom$N_COMPLETO.x)) {

if((!is.na(final.cons.nom$N_COMPLETO.x[j]) & (final.cons.nom$N_COMPLETO.x[j] != "") & (final.cons.nom$N_COMPLETO.x[j] != " ") & length(strsplit(final.cons.nom$N_COMPLETO.x[j],' ')[[1]]) <= 3) & (length(strsplit(final.cons.nom$N_COMPLETO.x[j],' ')[[1]]) > 0)) {

   if((is.na(final.cons.nom$NOMBRE.x[j]) | (final.cons.nom$NOMBRE.x[j] == "") | (final.cons.nom$NOMBRE.x[j] == " "))) {
       final.cons.nom$NOMBRE.x[j] <- word(final.cons.nom$N_COMPLETO.x[j], 1)    
   }

   if((is.na(final.cons.nom$PATERNO.x[j]) | (final.cons.nom$PATERNO.x[j] == "") | (final.cons.nom$PATERNO.x[j] == " "))) {
       final.cons.nom$PATERNO.x[j] <- word(final.cons.nom$N_COMPLETO.x[j], 2)    
   }

   if((is.na(final.cons.nom$MATERNO.x[j]) | (final.cons.nom$MATERNO.x[j] == "") | (final.cons.nom$MATERNO.x[j] == " "))) {
       final.cons.nom$MATERNO.x[j] <- word(final.cons.nom$N_COMPLETO.x[j], 3)    
   }

}

}

代码查看具有全名N_COMPLETO.x的向量,并尝试将该名称分为名字(NOMBRE.x),姓氏(PATERNO.x)和姓氏({{1只要全名不是NA,空格或空格,有3个或更少的单词,并且目标向量不被有效数据占用(某些名称正确分布和分离) )。

当我运行10000循环时,大约需要14秒,因此,应该在不到45分钟内分析整个矢量(在非常粗略和松散的计算中)。

在这45分钟足够长的情况下,事实证明我已经离开了R跑了将近2个小时没有完成循环(即使我知道它确实前进了)。

你有什么建议加快这种行动吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

我最终回到代码的矢量化版本,改变了如何使用strsplit的方法。

矢量化解决方案,如果相当长,但是,对于尝试这种技术的人来说,它是一个很好的例子:

final.cons.nom$NOMBRE.x[!is.na(final.cons.nom$N_COMPLETO.x) & 
(final.cons.nom$N_COMPLETO.x != "") & (final.cons.nom$N_COMPLETO.x != " ") & 
(sapply(strsplit(final.cons.nom$N_COMPLETO.x,' '), length) <= 3) & 
(sapply(strsplit(final.cons.nom$N_COMPLETO.x,' '), length) > 0) & 
(is.na(final.cons.nom$NOMBRE.x) | (final.cons.nom$NOMBRE.x == "") | 
(final.cons.nom$NOMBRE.x == " "))] <- 
word(final.cons.nom$N_COMPLETO.x[!is.na(final.cons.nom$N_COMPLETO.x) & 
(final.cons.nom$N_COMPLETO.x != "") & (final.cons.nom$N_COMPLETO.x != " ") & 
(sapply(strsplit(final.cons.nom$N_COMPLETO.x,' '), length) <= 3) & 
(sapply(strsplit(final.cons.nom$N_COMPLETO.x,' '), length) > 0) & 
(is.na(final.cons.nom$NOMBRE.x) | (final.cons.nom$NOMBRE.x == "") | 
(final.cons.nom$NOMBRE.x == " "))], 1)

特别是,我想指出使用strsplit的结果作为逻辑评估的向量:

sapply(strsplit(final.cons.nom$N_COMPLETO.x,' '), length) <= 3)