我想知道初始化列表的最有效的内存方式是在R中,如果该列表将在循环中用于存储结果。我知道在循环中增长对象会严重影响计算效率,所以我尽量避免这种情况。
我的问题如下。我有几组数据,我想单独处理。我的代码的要点是,我有一个循环,每次运行一个组,进行一些t测试,然后只返回统计上显著的结果(因此每个组的结果长度可变)。到目前为止,我正在初始化一个length(groups)
列表来存储每次迭代的结果。
我的主要问题是我应该如何初始化列表,使对象不会在循环中增长。
- 初始化
list = vector(mode = "list", length=length(groups))
是否足够好?- 我对此持怀疑态度,因为它只是创建了一个
length(groups)
列表,但每个条目都等于NULL
。我担心的是,在循环的每次迭代中,当我将数据存储到列表中时,每次当条目从NULL
到我的结果向量时,它都会重新复制对象,在这种情况下,初始化列表并没有多大好处。我不知道list
的内部是如何工作的,但是,所以它有可能只是存储对存储在列表中的矢量的引用,这意味着不需要重新复制。
- 我对此持怀疑态度,因为它只是创建了一个
- 另一种方法是将list中的每个元素初始化为结果可能具有的最大长度的vector。
- 这不是一个大问题,因为可能有效结果的最大数量是已知的。如果我采用这种方法,我会用循环中的结果向量覆盖每个向量。由于已经预留了最大内存量,希望不会发生重复制/增长。但是,如果没有必要,并且上面的第一个选项足够好,我不想采用这种方法。
下面是一些描述我的问题的伪代码
#initialize variables
results = vector(mode="list", length=length(groups)) #the line of code in question
y=1
tTests = vector(length = length(singleGroup))
#perform analysis on each group in groups
for(group in groups)
{
#returns a vector of p values with one entry per element in group
tTests = tTestFunction(group)
results[[y]] = tTests<=0.05
y=y+1
}
你的代码不工作,所以它是一个坏的例子。想想看:
x <- vector("list", length = 4)
tracemem(x) ## trace memory copies of "x"
for (i in 1:4) x[[i]] <- rnorm(4)
在更新期间没有额外的x
副本。所以没什么好担心的。
正如@lmo所建议的,即使您使用x <- list()
来初始化这个列表,也不会产生内存复制。
我的回答的目的,是指你使用tracemem
,当你想要跟踪(可能的)内存副本在代码执行期间。如果你知道这个功能,你就不会来找我们了。
这是我的另一个答案,与使用tracemem
有关。不过,这是在一个不同的背景下。在这里,您可以看到创建内存副本时tracemem
将返回什么。