Некоторые предложения.
Сначала , вы не определяете, каким beta1
должно быть, если условие не выполняется, но вы все равно пытаетесь его использовать . Это плохо как в начальном случае ('beta1' not found
), так и в следующем, когда beta1
было определено в предыдущем l oop. Ваши данные будут неправильными. Я предлагаю вам использовать только beta1
, если это уместно, попробуйте следующее:
for (val in 1:length(sampledata)) {
beta1 = which(other_list == sampledata[val])
if (length(beta1)) {
add_values = dataset1[c(beta1), c("name", "gender", "age")]
rbind(dataset2, add_values)
}
}
(Это все еще неверно.)
Второй , вы вызываете rbind
, но игнорируете его возвращаемое значение. Большинство функций в R являются функциональными в том смысле, что они не имеют побочных эффектов. rbind
не изменяет никаких данных, а возвращает объединенные данные. Итак, вам нужно захватить это:
for (val in 1:length(sampledata)) {
beta1 = which(other_list == sampledata[val])
if (length(beta1)) {
add_values = dataset1[c(beta1), c("name", "gender", "age")]
dataset2 = rbind(dataset2, add_values)
}
}
(Это все еще плохо.)
Слегка- третье ... это не строго нарушено, но может быть, если вы намерены «автоматизировать» это. Предпосылка 1:length(x)
заключается в том, что он должен позволять вам перебирать индексы вектора ... но если x
пуст, тогда 1:length(x)
сокращается до 1:0
, что не не возвращает пустой вектор:
1:length(c())
# [1] 1 0
, что означает, что ваш l oop попытается найти как sampledata[1]
(которого не существует), так и sampledata[0]
(который также имеет длину 0, и нарушит многие функции ).
Лучше использовать for (i in seq_len(length(x)))
или for (i in seq_along(x))
, оба ничего не сделают, если x
пусто,
for (i in seq_along(10:11)) print(i)
# [1] 1
# [1] 2
for (i in seq_along(integer(0))) print(i)
#### nothing done
Четвертый , хотя как rbind
делает что-то функционально : он делает полную копию всего data.frame
. Это означает, что если вы начнете с (скажем) 1000 строк, а затем добавите еще 2 строки, то у вас будет эти 1000 строк в памяти дважды . В конце концов, он будет удален из памяти сборщиком мусора, но на это нужно время. Теперь на следующей итерации for
l oop вы хотите добавить еще 3 строки; на этот раз он делает полную копию текущих 1002 строк, так что теперь они появляются в памяти дважды . Сделайте это достаточно раз, и ваше время на вычисления в основном будет потрачено на копирование всех этих данных. (Это как раз проблема, обсуждаемая в главе 2: Рост объектов в R Inferno .)
Обычно исправление заключается в том, чтобы все строки добавлялись и объединить их только один раз. Я думаю, это изменит ваш код на что-то вроде:
list_of_frames = list()
for (val in 1:length(sampledata)) {
beta1 = which(other_list == sampledata[val])
if (length(beta1)) {
add_values = dataset1[c(beta1), c("name", "gender", "age")]
list_of_frames = c(list_of_frames, add_values)
}
}
dataset2 = do.call(rbind, list_of_frames)
Если вы используете другие пакеты, это может быть проще с одной из этих строк кода вместо :
dataset2 = dplyr::bind_rows(list_of_frames)
dataset2 = data.table::rbindlist(list_of_frames)
Это должно быть «достаточно хорошо».
Вы могли бы go на один шаг дальше (до пятой точки) использовать R-идиоматию c lapply
, хотя, что-то вроде:
list_of_frames = lapply(seq_along(sampledata), function(ind) {
beta1 = which(other_list == sampledata[ind])
if (length(beta1)) dataset1[beta1, c("name", "gender", "age")]
})
### or better yet
list_of_frames = lapply(sampledata, function(sampdat) {
beta1 = which(other_list == sampdat)
if (length(beta1)) dataset1[beta1, c("name", "gender", "age")]
})
### then
dataset2 = do.call(rbind, list_of_frames)
Да, вероятно, будут элементы list_of_frames
, которые являются NULL
, и часть do.call(rbind, ...)
имеет дело с этим просто отлично .