Подтвердить что ты не робот

Заполнение кадра данных в R в цикле

Я пытаюсь заполнить фрейм данных из цикла for в R. Названия столбцов генерируются динамически в цикле, а значение некоторых из переменных цикла используется как значения при заполнении кадра данных. Например, имя текущего столбца может быть некоторым именем переменной в виде строки в цикле, а столбец может принимать значение текущего итератора как его значение в кадре данных.

Я попытался создать пустой цикл данных за пределами цикла, как этот

d = data.frame()

Но я не могу ничего с этим поделать, как только я попытаюсь заполнить его, я столкнулся с ошибкой

 d[1] = c(1,2)
Error in `[<-.data.frame`(`*tmp*`, 1, value = c(1, 2)) : 
  replacement has 2 rows, data has 0

Что может быть хорошим способом добиться того, что я ищу. Пожалуйста, дайте мне знать, если я не поняла.

4b9b3361

Ответ 1

Вы можете сделать это следующим образом:

 iterations = 10
 variables = 2

 output <- matrix(ncol=variables, nrow=iterations)

 for(i in 1:iterations){
  output[i,] <- runif(2)

 }

 output

а затем превратите его в data.frame

 output <- data.frame(output)
 class(output)

что это делает:

  • создать матрицу со строками и столбцами в соответствии с ожидаемым ростом
  • вставить 2 случайных числа в матрицу
  • преобразуйте это в кадр данных после завершения цикла.

Ответ 2

Часто предпочтительнее избегать циклов и использовать векторизованные функции. Если это невозможно, существует два подхода:

  • Предоставить выделение data.frame. Это не рекомендуется, поскольку индексирование выполняется медленно для data.frames.
  • Используйте другую структуру данных в цикле и затем преобразуйте ее в data.frame. A list здесь очень полезен.

Пример, иллюстрирующий общий подход:

mylist <- list() #create an empty list

for (i in 1:5) {
  vec <- numeric(5) #preallocate a numeric vector
  for (j in 1:5) { #fill the vector
    vec[j] <- i^j 
  }
  mylist[[i]] <- vec #put all vectors in the list
}
df <- do.call("rbind",mylist) #combine all vectors into a matrix

В этом примере нет необходимости использовать list, вы можете предварительно выделить matrix. Однако, если вы не знаете, сколько итераций потребуется вашему циклу, вы должны использовать list.

Наконец, это векторная альтернатива примеру цикла:

outer(1:5,1:5,function(i,j) i^j)

Как вы видите, это проще и эффективнее.

Ответ 3

У меня был случай, когда мне нужно было использовать фрейм данных внутри функции цикла. В этом случае это был "эффективный", однако имейте в виду, что база данных была небольшой, и итерации в цикле были очень простыми. Но, возможно, код может быть полезен для кого-то с аналогичными условиями.

Целью цикла было использование функции извлечения растра вдоль пяти местоположений (т.е. 5 Токио, Нью-Йорк, Сау-Паулу, Сеул и Мехико), и каждое место имело свои растровые решетки. У меня была база данных пространственных точек с более чем 1000 наблюдениями, выделенными в 5 разных местах, и мне нужно было извлечь информацию из 10 различных растровых сеток (две сетки на каждое место). Кроме того, для последующего анализа мне требовались не только значения растра, но и уникальный идентификатор для каждого наблюдения.

После подготовки пространственных данных, которые включали следующие задачи:

  • Импорт точек шейп файла с помощью функции readOGR (пакет rgdap)
  • Импортировать растровые файлы с помощью растровой функции (растровый пакет)
  • Решетки стека из одного и того же местоположения в один файл с помощью стека функций (растровый пакет)

Здесь код цикла цикла с использованием кадра данных:

1. Добавьте штабелированные растры на каждое место в список

raslist <- list(LOC1,LOC2,LOC3,LOC4,LOC5)

2. Создайте пустой фреймворк данных, это будет выходной файл

TB <- data.frame(VAR1=double(),VAR2=double(),ID=character())

3. Настройка для функции цикла

L1 <- seq(1,5,1) # the location ID is a numeric variable with values from 1 to 5 

for (i in 1:length(L1)) {
  dat=subset(points,LOCATION==i) # select corresponding points for location [i] 
  t=data.frame(extract(raslist[[i]],dat),dat$ID) # run extract function with points & raster stack for location [i]
  names(t)=c("VAR1","VAR2","ID") 
  TB=rbind(TB,t)
}