Назначение и удаление объектов в цикле: eval (parse (paste ( - PullRequest
1 голос
/ 14 сентября 2010

Я ищу назначение объектов в цикле. Я читал, что для выполнения этой задачи мне нужна какая-то форма 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(? Есть ли более простой / лучший способ назначения объектов в цикле?

Ответы [ 4 ]

10 голосов
/ 14 сентября 2010

Это довольно отвратительный и разочаровывающий способ сделать это. Используйте 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 г.)

8 голосов
/ 12 октября 2011

Хотя кажется, что есть более эффективные способы справиться с этим, если вы действительно действительно хотите использовать подход "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.

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

5 голосов
/ 14 сентября 2010

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

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

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

4 голосов
/ 14 сентября 2010

Очень плохая идея; Вы никогда не должны использовать 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)
...