将数据从小型data.frame复制到更大的data.frame

时间:2017-04-07 23:21:06

标签: r performance dataframe

d成为预先分配的大矩阵

d = as.data.frame(matrix(NA,ncol=3,nrow=5e7))
names(d) = c("x","y","z")

dsub是一个小矩阵,其列数和列名相同d

dsub = data.frame(x = 1:4,y=1:4,z=1:4)

我希望在第5到第8行将数据从dsub复制到d

d[5:8,] = dsub

此操作非常慢。似乎R正在复制整个data.frame d

  • 为什么会这样?

  • 如何让这个过程更快?

1 个答案:

答案 0 :(得分:2)

this comment中提到了data.table包,以解决在仅修改几行时复制整个对象的问题。

证明效果的最佳方式是基准。因此,可以比较data.table包提供的不同方法。

设置数据

df <- as.data.frame(matrix(NA_integer_, ncol = 3, nrow = 5e7))
names(df) = c("x", "y", "z")
dt <- setDT(copy(df))
dsub <- data.frame(x = 1:4, y = 1:4, z = 1:4)

请注意,目标对象初始化为NA_integer_,而不是NA,类型为logical。这避免了由左侧强制整数引起的开销(以及data.table发出的相应警告)。

基准

mb <- microbenchmark::microbenchmark(
  df = d[5:8,] <- dsub,
  dt1 = dt[5:8] <- dsub,
  dt2 = dt[5:8, (c("x","y","z")) := .SD],
  dt3 = set(dt, 5:8, 1:3, dsub),
  times = 10,
  unit = "ms"
)

print(mb, unit = "relative")
#Unit: relative
# expr        min          lq        mean      median          uq         max neval cld
#   df 56458.1921 27397.98069 27932.40685 29796.52860 34413.21160 29487.64751    10   b
#  dt1 49142.9608 24959.42180 22909.58526 20687.62826 30129.96416 21349.51295    10   b
#  dt2   111.9582    86.57717    54.36988    70.89935    69.36287    31.89704    10  a 
#  dt3     1.0000     1.00000     1.00000     1.00000     1.00000     1.00000    10  a 

请注意,基准测试结果是相对于data.table set()函数的最快方法打印的。但是,使用常规data.table systax(案例dt2)通过引用进行更新的速度比data.frame方式快。