如何高效逐行填充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
相关产品推荐
相关产品推荐

