【问题标题】:efficiency of rbindrbind 的效率
【发布时间】:2013-04-07 06:58:19
【问题描述】:

我正在编写一个必须构建一个大型矩阵的脚本。我想为每个名称取一个名称向量从不同的数据框中获取数据对其进行一些操作,然后返回该名称的数据向量。 例如:

allNew=matrix(ncol=ncol(X)-1);
for(name in list)
    {
    tmpdata=all[grep(names,list$Names),];
    data=(as.data.frame(apply(tmpdata[,2:(ncol(tmpdata)-1)],2,sum))==nrow(tmpdata))*1
    colnames(data)=name;
        data=t(data);
        allNew=rbind(allNew,data);
    }

名称列表的长度在 10000 范围内,每个名称 tmpdata 有 1-5 行。我在我的实验室 linux 服务器上运行我的代码,内存大约 8 GB,
不知何故,我觉得这比它应该花费的时间要长得多,需要几分钟。我怎样才能更有效地做到这一点?

【问题讨论】:

  • 这里有一个类似的问题:stackoverflow.com/questions/5980240/…
  • 不要在循环内增长矩阵。在开始时将其设置为最终大小,然后如果您必须使用循环,只需随时分配到其列中。
  • 另外,您的apply 可以替换为更快的colSums,如果您使用预分配矩阵as.data.framecolnames<-,则不需要转置。

标签: r performance rbind


【解决方案1】:

正如 cmets 所指出的,一次增长一个对象比覆盖部分预分配对象要慢。这样的事情应该可以工作——尽管没有任何测试数据很难确定。

allNew=matrix(NA, ncol=ncol(X)-1, nrow = length(list));
for(i in 1:length(list))
    {
    name <- names(list)[i]
    tmpdata=all[grep(names,list$Names), ]
    data=(as.data.frame(apply(tmpdata[, 2:(ncol(tmpdata)-1)], 2, sum))==nrow(tmpdata))*1
    colnames(data)=name
    allNew[i, ] = t(data)
    }

【讨论】:

  • 感谢您的快速回复!写完问题大约一个小时后,我意识到预先分配矩阵并逐行覆盖会更快
  • @user2253904 搜索 Patrick Burns 的“The R Inferno”。大开眼界。
  • @user2253904,如果您满意,请投票并接受该答案。
猜你喜欢
  • 2011-10-28
  • 1970-01-01
  • 2013-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多