С этими данными:
A <- data.frame( date_A = c('2010-01-01', '2010-01-02', '2010-01-03', '2010-01-02',
'2010-02-03', '2010-01-01', '2010-01-02') )
B <- data.frame(
date_B = c('2010-01-01','2010-01-02','2010-01-03'),
X_B = c(7.9,8.5,2.1))
Вы можете использовать match()
для индексации X_B
значений в правильном порядке:
A$X_A <- B$X_B[match(A$date_A,B$date_B)]
match()
возвращает индексы местоположений B$date_B
в A$date_A
. Другой прием, который нужно использовать, - это использовать уровни фактора в качестве индекса:
A$X_A <- B$X_B[A$date_A]
, который работает, потому что каждый фактор имеет уровни в отсортированном порядке и соответствует числовым значениям (1,2,3 ...). Таким образом, если B
отсортировано в соответствии с этими уровнями, это возвращает правильные индексы. (вы можете отсортировать B
, чтобы убедиться: B <- B[order(B$date_B),]
)
Что касается того, почему цикл не работает. Во-первых, я думаю, что вы действительно не хотите использовать ;
в R-скриптах. Это делает код намного сложнее для чтения. Лучше всего, если вы научитесь писать понятный код. В вашем коде вы можете использовать присваиватели более согласованно и использовать правильные отступы. Например:
i <- 1
j <- 1
while (i <= nrow(A))
{
while (j <= nrow(B))
{
if (A$date_A[i]==B$date_B[j]) A$X_A[i] <- B$X_B[j]
j <- j+1
if (j == nrow(B)) i <- i+1
j <- 1
}
}
Это ваш код, но его гораздо понятнее читать. Для меня это не работает, потому что уровни не сопоставимы (из-за опечатки), поэтому я вставил вызов as.character()
. Это, вероятно, не требуется в реальном наборе данных.
Индексация сразу показывает самую большую проблему здесь: вы потеряли j <- 1
за пределами if (j == nrow(B))
части. Использование ;
завершает строку и, следовательно, условную часть. Из-за этого j
устанавливается в 1 в каждом цикле.
Изменение этого параметра улучшает его работу, но вы по-прежнему получаете ошибку, поскольку цикл while
для j
может не завершиться до того, как i
будет больше, чем число строк в A
. Это можно изменить, установив оператор AND
и сворачивая оба цикла while
в один. Наконец, вам нужно установить для оператора if
большее количество строк в B
, либо вы пропустите одну строку. Это должно работать:
i <- 1
j <- 1
while (j <= nrow(B) & i <= nrow(A))
{
if (as.character(A$date_A[i])==as.character(B$date_B[j])) A$X_A[i] <- B$X_B[j]
j <- j+1
if (j > nrow(B))
{
i <- i+1
j <- 1
}
}
Но это только для того, чтобы показать, что пошло не так, я никогда не рекомендовал делать что-то подобное таким образом. Даже если вы действительно хотите использовать циклы, вам, вероятно, лучше использовать циклы for
.