Назначение и удаление объектов в цикле: eval(parse(paste(

Я ищу, чтобы назначать объекты в цикле. Я читал, что для этого мне нужна какая-то форма eval(parse(, но я сталкиваюсь с ошибками, перечисляющими invalid text или no such file or directory.. Ниже приведен пример кода того, что я пытаюсь сделать:

x <- array(seq(1,18,by=1),dim=c(3,2,3))
for (i in 1:length(x[1,1,])) {
  eval(parse(paste(letters[i],"<-mean(x[,,",i,"])",sep="")
}

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

for (i in 1:length(x[1,1,])) eval(parse(paste("rm(",letters[i],")",sep="")))

Обе части eval(parse(paste( этого скрипта возвращают ошибки для invalid text или no such file or directory. Я что-то упустил при использовании eval(parse(? Есть ли более простой/лучший способ назначать объекты в цикле?


person Community    schedule 14.09.2010    source источник


Ответы (4)


Это довольно отвратительный и разочаровывающий способ сделать это. Используйте assign для назначения и аргумент списка rm для удаления объектов.

> for (i in 1:length(x[1,1,])) {
+   assign(letters[i],mean(x[,,i]))
+ }
> ls()
[1] "a" "b" "c" "i" "x"
> a
[1] 3.5
> b
[1] 9.5
> c
[1] 15.5
> for (i in 1:length(x[1,1,])) {
+   rm(list=letters[i])
+ }
> ls()
[1] "i" "x"
> 

Всякий раз, когда вы чувствуете необходимость использовать parse, помните удачу (106):

Если ответом является parse(), вам обычно следует переосмыслить вопрос.
-- Томас Ламли, R-help (февраль 2005 г.)

person Joshua Ulrich    schedule 14.09.2010
comment
Я добавляю создателя отвратительного и разочаровывающего кода в свою биографию. - person JD Long; 14.09.2010
comment
Я также добавлю это в свою биографию. - person ; 15.09.2010

Хотя кажется, что есть лучшие способы справиться с этим, если вы действительно действительно хотите использовать подход "eval(parse(paste("), вам не хватает текстового флага.

parse предполагает, что его первый аргумент — это путь к файлу, который затем будет проанализирован. В вашем случае вы не хотите, чтобы он читал файл для анализа, вы хотите напрямую передать ему какой-то текст для анализа. Итак, ваш код, переписанный (в том, что выше было названо отвратительной формой), будет

letters=c('a','b','c')
x <- array(seq(1,18,by=1),dim=c(3,2,3))
for (i in 1:length(x[1,1,])) {
  eval(parse(text=paste(letters[i],"<-mean(x[,,",i,"])",sep="")))
}

В дополнение к тому, что вы не указали "text=", вам не хватает нескольких круглых скобок с правой стороны, чтобы закрыть ваши операторы синтаксического анализа и оценки.

Похоже, ваша проблема решена, но для людей, которые попадают на эту страницу и действительно хотят использовать eval(parse(paste, я хотел уточнить.

person Daniel Kessler    schedule 12.10.2011

Очень плохая идея; вы никогда не должны использовать eval или parse в R, если только вы не знаете точно, что делаете.
Переменные можно создавать, используя:

name<-"x"
assign(name,3) #Eqiv to x<-3

И удалено:

name<-"x"
rm(list=name)

Но в вашем случае это можно сделать с помощью простого именованного вектора:

apply(x,3,mean)->v;names(v)<-letters[1:length(v)]
v
v["b"]
#Some operations on v
rm(v)
person mbq    schedule 14.09.2010
comment
Э-э, гм... никогда не использовать eval — хорошая идея для некоторых языков, но вычисления на этом языке — одна из сильных сторон R... stat.ethz.ch/R-manual/R-devel/doc/manual/ Но да, в этом контексте assign предпочтительнее. - person Vince; 14.09.2010
comment
@Vince В каком-то смысле никогда не используйте eval, пока не станете продвинутым ;-) - person mbq; 14.09.2010
comment
удача (106): Если ответом является parse(), вам обычно следует переосмыслить вопрос. -- Томас Ламли, R-help (февраль 2005 г.) - person Joshua Ulrich; 14.09.2010
comment
@ Джошуа, я просто искал это. - person mbq; 14.09.2010
comment
У меня было ощущение, что вы имеете в виду это, поэтому я тоже искал это. - person Joshua Ulrich; 14.09.2010

В этом случае лучше избегать использования eval(paste( или assign ). Выполнение любого из них создает много глобальных переменных, которые позже вызывают дополнительные головные боли.

Наилучший подход — использовать существующие структуры данных для хранения ваших объектов, списки являются наиболее общими для таких случаев.

Затем вы можете использовать функции [ls]apply для работы с различными элементами, что обычно намного быстрее, чем перебор глобальных переменных. Если вы хотите сохранить все созданные объекты, у вас есть только один список для сохранения/загрузки. Когда приходит время их удалить, вы просто удаляете 1 отдельный объект, и все исчезает (без циклов). Вы можете назвать элементы списка, чтобы обращаться к ним позже по имени или по индексу.

person Greg Snow    schedule 14.09.2010
comment
Я думаю, что предложение Грега со списками - довольно разумное решение. Я использую его для своей работы, и он хорошо работает, особенно в связке с lapply. - person Roman Luštrik; 14.09.2010