2017-02-16 22 views
-2

Я пытаюсь очистить базу данных с несколькими именами, если быть точным, 1895971, многие из них имеют пробелы и NA.Как оптимизировать и ускорить функцию цикла в 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 в течение почти двух часов без его завершения цикла (хотя я знаю, что он продвигается).

Есть ли у вас рекомендации по ускорению такого рода операций?

Спасибо!

+1

Лучший способ оптимизации производительности цикла в R - исключить его в пользу полностью векторизованного кода. –

+0

Это была моя первая попытка @JohnColeman, однако, 'strsplit' не работал, как мне кажется. Вместо этого я рассмотрю эту функцию. Благодарю. –

+0

Кроме того, что такое функция 'word()'? Он не является частью базы R. –

ответ

1

В конце концов я вернулся к векторизованной версии кода, изменив подход к использованию strsplit.

vectorised решение, если достаточно долго, однако, он служит хорошим примером для тех, кто пытается такими методами:

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 «s как вектор для логической оценки:

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

Функция 'word' полностью векторизована. Вы можете проверить 'is.na (word (final.cons.nom $ N_COMPLETO.x, 4))', чтобы увидеть, если полное имя составляет 3 слова или меньше. –

+0

Отлично! Большое спасибо, @ Джон Колеман. –