1

我正在寻找循环分配对象。我已经读过某种形式eval(parse(是我需要执行此操作,但我遇到了错误列表invalid textno 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

4 回答 4

11

这是一种非常恶心和令人沮丧的方式。用于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() 你通常应该重新考虑这个问题。
——Thomas Lumley,R-help(2005 年 2 月)

于 2010-09-14T16:48:22.807 回答
8

尽管似乎有更好的方法来处理这个问题,但如果您确实使用“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=" 之外,您还缺少右侧的一些括号来关闭您的 parse 和 eval 语句。

听起来你的问题已经解决了,但是对于那些真正想要使用 eval(parse(paste,我想澄清一下。

于 2011-10-12T19:54:51.393 回答
5

在这种情况下,最好避免使用 eval(paste( 或 assign 。这样做会创建许多全局变量,这些变量只会在以后引起额外的麻烦。

最好的方法是使用现有的数据结构来存储您的对象,对于这些类型的情况,列表是最通用的。

然后你可以使用 [ls]apply 函数来处理不同的元素,通常比循环遍历全局变量要快得多。如果您想保存所有创建的对象,您只需保存/加载一个列表。当需要删除它们时,您只需删除 1 个单个对象,一切都消失了(没有循环)。您可以命名列表的元素,以便稍后通过名称或索引来引用它们。

于 2010-09-14T17:23:48.307 回答
5

非常糟糕的主意;你不应该在 R 中使用evalor parse,除非你完全知道你在做什么。
可以使用以下方法创建变量:

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)
于 2010-09-14T16:47:47.613 回答