Невозможно сохранить возвращаемое значение какой функции в R - PullRequest
0 голосов
/ 16 июня 2020

Привет всем, так что я новичок в R - установил RStudio на прошлой неделе.

Я пытаюсь сохранить координаты элемента в dataframe other_list ниже в переменной beta1, но продолжаю получать ошибка: «объект 'beta1' не найден».

for (val in 1:length(sampledata)) {
  if (sampledata[val] %in% other_list)
    beta1 = which(other_list == sampledata[val])
  add_values = dataset1[c(beta1), c("name", "gender", "age")]
   rbind(dataset2, add_values)
}

У кого-нибудь есть объяснение, почему beta1 не распознается в скобках набора данных1?

Спасибо!

1 Ответ

0 голосов
/ 16 июня 2020

Некоторые предложения.

Сначала , вы не определяете, каким 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, ...) имеет дело с этим просто отлично .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...