【问题标题】:Why does R store the loop variable/index/dummy in memory?为什么 R 将循环变量/索引/虚拟变量存储在内存中?
【发布时间】:2015-06-20 18:09:42
【问题描述】:

我注意到R 将索引从存储在全局环境中的for 循环中保留下来,例如:

for (ii in 1:5){ }

print(ii)
# [1] 5

运行循环后人们对这个索引有任何需求吗?

我从不使用它,并且不得不记住在我运行的每个循环之后添加rm(ii)(首先,因为我很想保持我的命名空间干净,其次是为了记忆,因为我有时会遍历 @ 列表987654325@--在我的代码中,我有 357MB 的虚拟变量在浪费空间)。

有没有一种简单的方法来解决这个烦恼? Perfect 将是一个全局选项来设置(a la options(keep_for_index = FALSE);类似 for(ii in 1:5, keep_index = FALSE) 的东西也可以接受。

【问题讨论】:

  • 这根本不是一个愚蠢的问题——我最初的反应是考虑使用lapply 或类似的家庭函数。这并不总是可行的,但对于很多任务来说通常更可取。
  • 当然;但是,例如,我的一个 for 循环运行 200 行。定义一个函数来执行循环所做的事情只是为了避免 for 循环似乎有点古怪
  • 350 兆只来自循环的索引变量?你怎么解释?你是用 r 语言用 r 编程还是用 c 语言用 r 编程?
  • 我不知道第二个问题是什么意思。但我基本上是在运行稳健性检查——对不同的子样本进行相同的统计分析——循环不同的数据集对我来说似乎很自然。
  • @MichaelChirico - 如果您正在处理 dt1 dt2 dt3 命名为 data.tables,我不禁觉得您应该使用 data.tables 的列表和lapply将您的函数添加到列表的每个部分。据我所知,:= 将通过引用更新列表中的data.tables。

标签: r for-loop


【解决方案1】:

为了执行您的建议,R 必须更改 for 循环的范围规则。这可能永远不会发生,因为我确信依赖它的包中有代码。您可能不会在 for 循环之后使用索引,但考虑到循环可以随时break(),最终迭代值并不总是提前知道。再次将其作为全局选项会导致工作包中现有代码出现问题。

正如所指出的,在 R 中使用 sapply 或 lapply 循环更为常见。类似

for(i in 1:4) {
   lm(data[, 1] ~ data[, i])
}

变成

sapply(1:4, function(i) {
   lm(data[, 1] ~ data[, i])
})

您不应该害怕 R 中的函数。毕竟,R 是一种函数式语言。

使用for 循环进行更多控制很好,但正如您所指出的,您必须注意使用rm() 删除索引变量。除非您在每个循环中使用不同的索引变量,否则我对它们堆积如山感到惊讶。我也很惊讶在您的情况下,如果它们是 data.tables,它们会添加额外的内存,因为据我所知,data.tables 默认情况下不会进行深层复制。您需要支付的唯一内存“价格”是一个简单的指针。

【讨论】:

  • 嗯,公平点。我的内存消耗基于tables();不确定该输出是否给出重叠或不同的内存使用情况。
  • 另外,我想你已经接近回答我的主要问题了,但你能澄清一下吗?你是说R存储索引变量的原因是for循环不像普通函数那样创建自己的环境,所以索引被初始化并存储在主环境中?
  • 基本上。范围仅在您定义函数时创建,而不是在您调用它们时创建。所以for 循环与任何“正常”函数没有什么不同。如果我做了mean(i<-1:10),则i 变量将在调用mean() 之后存在,即使它在调用之前不存在。
  • 所以for 函数通过in 隐式分配索引。明白了!
【解决方案2】:

我同意上面的 cmets。即使您必须使用for 循环(仅使用副作用,而不是函数的返回值),构建结构也是一个好主意 您的代码在多个函数中,并将您的数据存储在列表中。

但是,有一种方法可以“隐藏”循环内的索引和所有临时变量 - 通过在单独的环境中调用 for 函数:

do.call(`for`, alist(i, 1:3, {
  # ...
  print(i)
  # ... 
}), envir = new.env())

但是......如果你可以把你的代码放在一个函数中,那么解决方案会更优雅:

for_each <- function(x, FUN) {
  for(i in x) {
    FUN(i)
  }
}

for_each(1:3, print)

请注意,使用类似“for_each”的构造时,您甚至看不到索引变量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-21
    • 1970-01-01
    • 2017-02-24
    • 1970-01-01
    相关资源
    最近更新 更多