Создайте список имен переменных в цикле for, затем присвойте им значения

27

Интересно, есть ли простой способ создать список переменных, используя цикл for, и указать его значение?

for(i in 1:3)
{
  noquote(paste("a",i,sep=""))=i
}

В приведенной выше коде, я пытаюсь создать a1, a2, a3, задающие значения 1, 2, 3. Однако, R выдает сообщение об ошибке. Спасибо за вашу помощь.

Хан Лин Шан
источник
3
Я сомневаюсь, что вы должны это делать - кажется, вы делаете что-то очень неправильно.
@mbq, например, в Eviews это довольно нормальная практика кодирования. Не то, чтобы я защищал это, оценки Eviews только немного ниже, чем Excel в моем списке самых злых программ :)
mpiktas
6
@mpiktas В R более естественно составить список, установить его namesпараметр, а затем либо просто использовать его, attachлибо преобразовать его в среду внутри list2envи evalвнутри него. Без петель, разборов и прочих некрасивых вещей.
@mbq, хм, list2envэто относительно новая функция. И все же он будет генерировать переменные в некоторой среде, когда ОП хочет получить переменные в верхней среде. Таким образом, уродство все еще остается :)
mpiktas
2
Для будущих вопросов аналогичного характера я бы предположил, что этот тип вопросов действительно принадлежит StackOverflow. Вопрос не имеет ничего общего со статистикой как таковой.
Марс

Ответы:

41

Вы ищете assign().

for(i in 1:3){
  assign(paste("a", i, sep = ""), i)    
}

дает

> ls()
[1] "a1"          "a2"          "a3" 

а также

> a1
[1] 1
> a2
[1] 2
> a3
[1] 3

Обновить

Я согласен, что использование циклов (очень часто) является плохим стилем кодирования R (см. Обсуждение выше). Использование list2env()(спасибо @mbq за упоминание), это еще одно решение вопроса @Han Lin Shang:

x <- as.list(rnorm(10000))
names(x) <- paste("a", 1:length(x), sep = "")
list2env(x , envir = .GlobalEnv)
Бернд Вайс
источник
21

Если значения в векторе, цикл не нужен:

vals <- rnorm(3)
n    <- length(vals)
lhs  <- paste("a",    1:n,     sep="")
rhs  <- paste("vals[",1:n,"]", sep="")
eq   <- paste(paste(lhs, rhs, sep="<-"), collapse=";")
eval(parse(text=eq))

Как примечание, это причина, почему я люблю Р.

mpiktas
источник
4
library(fortunes) fortune(106)
Роман Луштрик
@Roman, странно, я начал использовать parseпосле прочтения страниц справки R. Я согласен, что иногда это перебор, например, в formulaуправлении, но я нашел это очень полезным. Обратите внимание, что я не могу переосмыслить вопрос, предложенный в судьбе, так как я не задавал его.
mpiktas
1
@mpiktas: это связано с тем, что лежащие в основе правила области видимости могут привести к непредсказуемым результатам при использовании внутри функции. Кроме того (как указано в файлах справки), R и S могут давать разные результаты из-за разницы в правилах области видимости. Это также медленнее, чем другие решения. Это будет иметь значение, когда вам придется делать это много раз. И последнее, но не менее важное: в большинстве случаев существует более элегантное и простое решение, чем использование eval (parse ()). В этом случае это работает со списками или с использованием assign.
Джорис Мейс
1
@mpiktas: я никогда не говорил, что это недостаточно. Я только что объяснил вам причину, по которой, в общем случае, рекомендуется использовать конструкцию eval (parse ()), например, Томаса Ламли, члена команды разработчиков ядра R. (см. ссылку @Roman Lustrik)
Джорис Мейс
1
точно, плохая практика, такая как использование assign для создания нескольких одноэлементных переменных, не должна поощряться
mdsumner