让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
!
为什么会这样?
如何让这个过程更快?
答案 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
方式快。