2017-02-16 72 views
-2

我試圖用幾個名字清理一個數據庫,確切地說,1895971,其中許多是空白和NAs。如何優化和加快R中的循環函數

這樣做,我編寫,似乎工作的解決方案:

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)和姓氏(MATERNO.x),只要全名不是NA,空格或空白,具有3個或更少的單詞,並且目標向量未被有效數據佔據(某些名字正確地分佈和分開)。

當我運行10000循環大約需要14秒,因此,整個矢量應該在不到45分鐘的時間內進行分析(在非常粗糙和鬆散的計算中)。在這45分鐘足夠長的時間裏,事實證明我已經將R運行了近2個小時而沒有完成循環(儘管我知道它提前了)。

你有什麼建議加快這種操作嗎?

謝謝!

+1

在R中優化循環性能的最佳方法是消除它,以支持完全向量化的代碼。 –

+0

這是我第一次嘗試@JohnColeman,但是,'strsplit'沒有像我應該那樣操作。我會考慮這個功能。謝謝。 –

+0

另外,函數'word()'是什麼?它不是基R的一部分。 –

回答

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) 
+0

'word'函數是完全向量化的。您可以測試'is.na(word(final.cons.nom $ N_COMPLETO.x,4))'來查看全名是否爲3個字或更少。 –

+0

太棒了!非常感謝,@JohnColeman。 –