Сравнение двух векторов по одному значению за раз без использования WHILE

У меня есть две таблицы: df.author и df.post, которые связаны отношением "один ко многим". Теперь я изменил первичный ключ df.author и хочу, чтобы df.post отразил это изменение. В следующем R-скрипте я использую match() в цикле while для сравнения внешнего ключа каждой строки df.post со старым первичным ключом df.author и-когда они соответствуют внешнему ключу и заменяют его новым (формируют другой столбец df.author). Пожалуйста, обратите внимание на следующее:

foreignkey <- c("old_pk1","old_pk2","old_pk3","old_pk4","old_pk5","old_pk1","old_pk7")
df.post <- data.frame(foreignkey,stringsAsFactors=FALSE)
rm(foreignkey)

primarykey_old <- c("old_pk1","old_pk2","old_pk3","old_pk4","old_pk5")
primarykey_new <- c("new_pk1","new_pk2","new_pk3","new_pk4","new_pk5")
df.author <- data.frame(primarykey_old, primarykey_new, stringsAsFactors=FALSE);
rm(primarykey_old); rm(primarykey_new) 

i <- 1; N <- length(df.post$foreignkey)
while (i <= N) {
  match <- match(df.post$foreignkey[i], df.author$primarykey_old)
  if (!is.na(match)) {
    df.post$foreignkey[i] <- df.author$primarykey_new[match]
  }
  i <- i + 1
}
rm(N); rm(i); rm(match)

Скрипт работает, но из-за while неэффективно масштабируется для большого набора данных. Я читал, что использование apply() (в моем случае путем преобразования в матрицу) обычно лучше, чем использование while. Интересно, применимо ли это и к моему случаю. Потому что, если вы посмотрите на цикл, вы увидите, что мне нужно пройти через каждую строку фрейма данных, чтобы получить внешний ключ, а затем через df.author для match(). Могу ли я сократить время вычислений, не используя while?


person CptNemo    schedule 30.09.2013    source источник
comment
Это неправильно написано: as.Character. Если это действительно проблема с одним-многими возможностями, вы можете создать набор данных, демонстрирующий эту функцию.   -  person IRTFM    schedule 30.09.2013
comment
Извините, эта строка была сделана лишней stringsAsFactors=FALSE   -  person CptNemo    schedule 30.09.2013
comment
Второй вопрос до сих пор не решен. Я подозреваю, что это обесценивает ответ, который я даю, но теперь вы несете ответственность за создание контрпримера.   -  person IRTFM    schedule 30.09.2013


Ответы (1)


Я думаю, что это может сделать все без петель:

df.post$foreignkey[
    !length(match(df.post$foreignkey, df.author$primarykey_old))==0] <- # the test
    df.author$primarykey_new[match(df.post$foreignkey, df.author$primarykey_old)]

Логика: Только если есть совпадение, замените существующее значение совпадающим значением.

person IRTFM    schedule 30.09.2013
comment
Если я правильно понимаю, match() возвращает только первое совпадение. Так что же здесь происходит, если в df.post$foreignkey есть повторяющиеся значения? (Это отношение «многие к одному» от df.post до df.author). Я могу проверить, что это действительно работает, я просто не понимаю, как... - person CptNemo; 02.10.2013
comment
Я отредактировал свой вопрос, добавив случай, когда в foreignkey есть значение, отсутствующее в primarykey_old. В этом решении несовпадающие значения в foreignkey заменяются пустыми значениями. Можно ли энергично изменить значение в foreignkey для несоответствия? - person CptNemo; 02.10.2013