У меня есть цикл, который будет выдавать кучу фреймов данных, и я хочу назвать фреймы данных на основе текущей итерации цикла, например. df1 для первой итерации, df2 для второй итерации и так далее.

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

counter <- 1
as.name(paste("df",counter,sep="")) <- data.frame(x = (1:10), y = (10:1))

Я получаю ошибку

Error in as.name(paste("df", counter, sep = "")) <- data.frame(x = (1:10),  : 
  target of assignment expands to non-language object

Кто-нибудь знает, как я могу использовать информацию счетчика для создания имен фреймов данных?

r
0
Thomas 18 Сен 2014 в 23:37

4 ответа

Лучший ответ

Используйте assign:

assign(paste0("df", counter), data.frame(x = (1:10), y = (10:1))
1
Sven Hohenstein 19 Сен 2014 в 10:34
Спасибо, мне удалось заставить его работать с assign(paste0("df", counter), data.frame(x = (1:10), y = (10:1)))
 – 
Thomas
18 Сен 2014 в 23:46
Верно. Извините за ошибку.
 – 
Sven Hohenstein
19 Сен 2014 в 10:34

Это сделано для того, чтобы дополнить книгу Ричарда, поскольку она казалась слишком существенной, чтобы просто отредактировать его.

Типичный образец кода для такого рода вещей:

#Initialize an empty list of the desired length
dfs <- vector("list",3)

#Fill the list with data frames, naming as we go
for (i in seq_along(dfs)){
    dfs[[i]] <- data.frame(x = runif(5),y = runif(5))
    names(dfs)[[i]] <- paste0("df",i)
}

Где использование assign обычно не одобряется как плохое (стилистически). Если именование фреймов данных очень регулярное, вам даже не нужно делать это в цикле:

names(dfs) <- paste0("df",seq_along(dfs))

Вы можете сделать это в векторизованном виде, как указано выше. И, как я уже упоминал ниже, ответ Ричарда, хотя наличие их всех в списке никогда не бывает хуже и, как правило, лучше, чем иметь их как отдельные объекты, вы можете преобразовать список в отдельные объекты с помощью:

list2env(dfs,envir = .GlobalEnv)
3
joran 19 Сен 2014 в 00:06
Спасибо, Джоран, я смог последовать вашему предложению, чтобы сохранить все мои кадры данных в списке. Это делает все намного чище, так как в конце я просто обобщу эти многочисленные фреймы данных в один фрейм данных!
 – 
Thomas
19 Сен 2014 в 00:58

Вместо того, чтобы загромождать глобальную среду фреймами данных, было бы лучше собрать их в list, а затем вы можете использовать paste0, чтобы назвать их в setNames, например,

> dfList <- setNames(list(data.frame(x = 1:10, y = 10:1)), paste0("df", 1)) 

После этого вы можете обратиться к фрейму данных с помощью

> dfList$df1
    x  y
1   1 10
2   2  9
3   3  8
4   4  7
5   5  6
6   6  5
7   7  4
8   8  3
9   9  2
10 10  1

Как отмечает Джоран, если вы настаиваете на заполнении глобальной среды этими фреймами данных, вы можете использовать

list2Env(dfList, envir = .GlobalEnv)

И фреймы данных будут назначены как объекты в глобальной среде.

3
Rich Scriven 19 Сен 2014 в 01:11
... и поскольку люди, занимающиеся подобными вещами, часто настаивают на том, что им действительно нужны фреймы данных, существующие как отдельные объекты, вы всегда можете добиться этого с помощью list2env(dfList,envir = .GlobalEnv), если это необходимо.
 – 
joran
18 Сен 2014 в 23:55
Спасибо, Ричард. Я попробую это дальше - в настоящее время я запускаю свой цикл (создавая 22 кадра данных), но для его завершения требуется некоторое время. Следующим попробую ваше предложение!
 – 
Thomas
18 Сен 2014 в 23:55

Я думаю ты ищешь

assign("name", dataframe)
1
cory 18 Сен 2014 в 23:41