【问题标题】:Assigning and removing objects in a loop: eval(parse(paste(在循环中分配和删除对象: eval(parse(paste(
【发布时间】:2011-04-12 06:39:56
【问题描述】:

我希望在循环中分配对象。我已经读到某种形式的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 textno such file or directory 的错误。我在使用eval(parse( 时遗漏了什么吗?有没有更简单/更好的方法在循环中分配对象?

【问题讨论】:

    标签: r loops object eval paste


    【解决方案1】:

    这是一种非常恶心和令人沮丧的方式。使用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时,记住fortune(106):

    如果答案是 parse() 你应该 通常会重新考虑这个问题。
    -- Thomas Lumley,R-help(2005 年 2 月)

    【讨论】:

    • 我在我的简历中添加了“令人作呕和令人沮丧的代码的创造者”。
    • 我也会将其添加到我的简历中。
    【解决方案2】:

    虽然似乎有更好的方法来处理这个问题,但如果你真的确实想要使用“eval(parse(paste(”)”方法,那么你缺少的是文本标志。

    parse 假设它的第一个参数是一个文件的 path,然后它将被解析。在您的情况下,您不希望它去读取要解析的文件,而是希望直接将一些文本传递给它以进行解析。所以,你的代码,重写(上面被称为恶心的形式)将是

    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,我想澄清一下。

    【讨论】:

      【解决方案3】:

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

      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)
      

      【讨论】:

      • 呃,嗯...在某些语言中从不使用eval 是一个好主意,但是在语言上进行计算是R 的优势之一...stat.ethz.ch/R-manual/R-devel/doc/manual/… 但是在这种情况下,分配是首选。
      • @Vince 从某种意义上说,在你进阶之前永远不要使用eval ;-)
      • fortune(106):“如果答案是 parse(),你通常应该重新考虑这个问题。” -- Thomas Lumley,R-help(2005 年 2 月)
      • @Joshua 我只是在找它。
      • 我感觉你指的是那个,所以我也搜索了它。
      【解决方案4】:

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

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

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

      【讨论】:

      • 我认为 Gregs 对列表的建议是一个非常合理的解决方案。我将它用于我的工作并且效果很好,尤其是与 lapply 配合使用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-23
      • 2013-05-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多