You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效逐行填充R语言中的data.frame?

关于R中逐行填充data.frame的性能疑问

**摘要:**本问题最初基于错误的基准测试。若要对比填充data.frame不同方法的实际性能,可参考jblood94的分析。

已有多篇报道指出,预先分配data.frame后逐行赋值的速度极慢——即使仅修改单个单元格,整个data.frame也会被复制。示例代码如下:

# preallocation
df.pre <- function(x) {
  df <- data.frame(x=numeric(length(x)), y=logical(length(x)))
  for (i in 1:length(x)) {
    df[i,] <- data.frame(x=x[i], y=(x[i]>0.5))  # <<<--- entire df is copied
  }
  return(df)
}

有趣的是,当为不存在的索引赋值、让data.frame自动扩展时,似乎不会出现上述复制问题:

# automatic extension
df.auto <- function(x) {
  df <- data.frame(x=numeric(0), y=logical(0))
  for (i in 1:length(x)) {
    df[i,] <- data.frame(x=x[i], y=(x[i]>0.5))
  }
  return(df)
}

x <- runif(100)
library(microbenchmark)
microbenchmark(df.pre(x), df.auto) # <<<--- WRONG

测试得到的运行时长如下:

Unit: nanoseconds
      expr     min      lq       mean  median        uq      max neval cld
 df.pre(x) 5400053 5447409 5889698.24 5827590 5876605.5 18726678   100   b
   df.auto       9      11      75.94      82     109.5     1071   100  a 

基于这个错误的测试结果,作者发现这种自动扩展的填充方法速度几乎与预先分配矩阵相当,且比先填充列表再转为data.frame快得多,由此提出两个问题:

  • 这种无复制的行为是否有保障?
  • 这是否是逐行填充data.frame的推荐方式?

**编辑:**正如jblood94指出,上述基准测试存在错误——正确调用后,自动扩展赋值与预先分配data.frame赋值的速度几乎无差异,二者都很慢。目前已知最快的方法是:若所有值类型相同,可先使用预先分配的矩阵,再转为data.frame;或先填充列表,再转为data.frame。示例代码如下:

df.pre <- function(x) {
  df <- data.frame(x=numeric(length(x)), y=logical(length(x)))
  for (i in 1:length(x)) {
      df[i,] <- data.frame(x=x[i], y=(x[i]>0.5))
  }
  return(df)
}
ls.pre <- function(x) {
  ls <- list(x=numeric(length(x)), y=logical(length(x)))
  for (i in 1:length(x)) {
    ls$x[i] <- x[i]; ls$y[i] <- (x[i]>0.5)
  }
  return(as.data.frame(ls))
}
matrix.pre <- function(x) {
  mt <- matrix(c(numeric(length(x)*2)), ncol=2)
  for (i in 1:length(x)) {
    mt[i,] <- c(x[i], as.numeric(x[i]>0.5))
  }
  return(as.data.frame(mt))
}

x <- runif(100)
library(microbenchmark)
microbenchmark(df.pre(x), ls.pre(x), matrix.pre(x))

测试得到的运行时长如下:

Unit: microseconds
          expr      min        lq       mean    median        uq      max neval
     df.pre(x) 5745.687 5789.6780 6073.79760 5812.7450 5888.2840 8714.556   100
     ls.pre(x)   61.209   65.9720  100.35568   70.9705   74.6935 2981.260   100
 matrix.pre(x)   29.641   33.1215   59.85807   38.6615   40.7255 2237.502   100

内容的提问来源于stack exchange,提问作者cdalitz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 11:45:16