Assigning and removing objects in a loop: eval(par

2019-01-23 21:55发布

I am looking to assign objects in a loop. I've read that some form of eval(parse( is what I need to perform this, but I'm running into errors listing invalid text or no such file or directory. Below is sample code of generally what I'm attempting to do:

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="")
}

And when I'm finished using these objects, I would like to remove them (the actual objects are very large and cause memory problems later on...)

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

Both eval(parse(paste( portions of this script return errors for invalid text or no such file or directory. Am I missing something in using eval(parse(? Is there a easier/better way to assign objects in a loop?

4条回答
Rolldiameter
2楼-- · 2019-01-23 22:37

It is best to avoid using either eval(paste( or assign in this case. Doing either creates many global variables that just cause additional headaches later on.

The best approach is to use existing data structures to store your objects, lists are the most general for these types of cases.

Then you can use the [ls]apply functions to do things with the different elements, usually much quicker than looping through global variables. If you want to save all the objects created, you have just one list to save/load. When it comes time to delete them, you just delete 1 single object and everything is gone (no looping). You can name the elements of the list to refer to them by name later on, or by index.

查看更多
三岁会撩人
3楼-- · 2019-01-23 22:47

Very bad idea; you should never use eval or parse in R, unless you perfectly know what you are doing.
Variables can be created using:

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

And removed by:

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

But in your case, it can be done with simple named vector:

apply(x,3,mean)->v;names(v)<-letters[1:length(v)]
v
v["b"]
#Some operations on v
rm(v)
查看更多
Summer. ? 凉城
4楼-- · 2019-01-23 22:48

Although it seems there are better ways to handle this, if you really did want to use the "eval(parse(paste(" approach, what you're missing is the text flag.

parse assumes that its first argument is a path to a file which it will then parse. In your case, you don't want it to go reading a file to parse, you want to directly pass it some text to parse. So, your code, rewritten (in what has been called disgusting form above) would be

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="")))
}

In addition to not specifying "text=" you're missing a few parentheses on the right side to close your parse and eval statements.

It sounds like your problem has been solved, but for people who reach this page who really do want to use eval(parse(paste, I wanted to clarify.

查看更多
家丑人穷心不美
5楼-- · 2019-01-23 22:49

That's a pretty disgusting and frustrating way to go about it. Use assign to assign and rm's list argument to remove objects.

> 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"
> 

Whenever you feel the need to use parse, remember fortune(106):

If the answer is parse() you should usually rethink the question.
-- Thomas Lumley, R-help (February 2005)

查看更多
登录 后发表回答