在R中循环之前初始化列表的内存效率最高的方法是什么?

在R中循环之前初始化列表的内存效率最高的方法是什么?,r,list,for-loop,initialization,memory-efficient,R,List,For Loop,Initialization,Memory Efficient,我想知道,如果在循环中使用列表来存储结果,那么在R中初始化列表的内存效率最高的方法是什么。我知道在循环中增加一个对象会导致计算效率的严重下降,所以我尽量避免这种情况 我的问题如下。我有几组数据要单独处理。我的代码的要点是,我有一个循环,一次遍历每个组,进行一些t检验,然后只返回统计上显著的结果(因此每个组的长度可变)。到目前为止,我正在初始化一个length(groups)列表,以存储每次迭代的结果 我的主要问题是我应该如何初始化列表,以便对象不会在循环中增长 初始化时执行list=vecto

我想知道,如果在循环中使用列表来存储结果,那么在R中初始化列表的内存效率最高的方法是什么。我知道在循环中增加一个对象会导致计算效率的严重下降,所以我尽量避免这种情况

我的问题如下。我有几组数据要单独处理。我的代码的要点是,我有一个循环,一次遍历每个组,进行一些t检验,然后只返回统计上显著的结果(因此每个组的长度可变)。到目前为止,我正在初始化一个
length(groups)
列表,以存储每次迭代的结果

我的主要问题是我应该如何初始化列表,以便对象不会在循环中增长

  • 初始化时执行
    list=vector(mode=“list”,length=length(groups))
    是否足够好?
    • 我对此表示怀疑,因为它只是创建了一个
      长度(组)
      列表,但每个条目都等于
      NULL
      。我关心的是,在循环的每次迭代过程中,当我将数据存储到列表中时,每次当条目从
      NULL
      变为我的结果向量时,它都会重新复制对象,在这种情况下,初始化列表实际上没有多大用处。但是,我不知道
      列表的内部是如何工作的,因此它可能只存储对存储在列表中的向量的引用,这意味着不需要重新复制
  • 另一个选项是将列表的每个元素初始化为结果可能具有的最大长度的向量。
    • 这不是一个大问题,因为已知可能的最大有效结果数。如果我采用这种方法,我会用循环中的结果向量覆盖每个向量。由于已经保留了最大内存量,希望不会发生重新复制/增长。但是,如果没有必要,并且上面的第一个选项足够好,我不想采用这种方法
下面是一些描述我的问题的psuedo代码

#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
}   
#初始化变量
结果=向量(mode=“list”,length=长度(组))#有问题的代码行
y=1
t测试=向量(长度=长度(单组))
#分组对每组进行分析
for(分组中的组)
{
#返回p值的向量,组中每个元素有一个条目
tTests=tTestFunction(组)

结果[[y]=tTest你的代码不起作用,所以这是一个坏的例子。考虑一下:

x <- vector("list", length = 4)
tracemem(x)  ## trace memory copies of "x"
for (i in 1:4) x[[i]] <- rnorm(4)

x我想绝大多数人会说是的,
vector(“list”,length(groups))
是初始化结果列表的方式。问题有点宽泛。用一个玩具示例来测试你的两个想法很容易。正如我的问题中所述,代码不起作用,因为它是psuedo代码。我包含它是为了展示我试图完成的工作的逻辑框架,而不是给出一个工作示例(因为这只是一个复杂代码块的一小部分。)谢谢你的回答,
traceem
似乎非常方便。
traceem()
没有报告内存重新分配,我不知道为什么;使用
.Internal(inspect(x))
查看外部向量在每个赋值上是否重新分配(输出的第一行中的
@…
是列表的内存地址;不知何故,它“必须”是,因为原始分配不够大)。虽然单个元素没有被复制,但它们被复制到列表中,i=2时有1个副本,i=3时有2个副本,…大约n(n-1)/2个副本(二次缩放)总的来说。
inspect()
是一个C级函数,用于汇总每个符号的信息;StackOverflow中以及其他地方有更多信息。