我有以下数据:
height = 1:10000000
length = -(1:10000000)
body_dim = data.frame(height,length)
body_dim_mat = as.matrix(body_dim)
为什么which()
与矩阵相比,数据框的工作速度更快?
> microbenchmark(body_dim[which(body_dim$height==50000),"length"])
Unit: milliseconds
expr min lq median uq max neval
body_dim[which(body_dim$height == 50000), "length"] 124.4586 125.1625 125.9281 127.9496 284.9824 100
> microbenchmark(body_dim_mat[which(body_dim_mat[,1] == 50000),2])
Unit: milliseconds
expr min lq median uq max neval
body_dim_mat[which(body_dim_mat[, 1] == 50000), 2] 251.1282 252.4457 389.7251 400.313 1004.25 100
答案 0 :(得分:5)
data.frame是一个列表,列是一个简单的向量,很容易从列表中提取。矩阵是具有维度属性的向量。必须从维度计算属于一列的哪些值。这会影响子集,您将其纳入基准:
library(microbenchmark)
set.seed(42)
m <- matrix(rnorm(1e5), ncol=10)
DF <- as.data.frame(m)
microbenchmark(m[,1], DF[,1], DF$V1)
#Unit: microseconds
# expr min lq median uq max neval
# m[, 1] 80.997 82.536 84.230 87.1560 1147.795 100
#DF[, 1] 15.399 16.939 20.789 22.6365 100.090 100
# DF$V1 1.849 2.772 3.389 4.3130 90.235 100
但是,带回家的消息不是你应该总是使用data.frame。因为如果你进行子集化,结果不是向量:
microbenchmark(m[1:10, 1:10], DF[1:10, 1:10])
# Unit: microseconds
# expr min lq median uq max neval
# m[1:10, 1:10] 1.233 1.8490 3.2345 3.697 11.087 100
# DF[1:10, 1:10] 211.267 219.7355 228.2050 252.226 1265.131 100
答案 1 :(得分:1)
似乎问题出现在which()
之前,如果与整个矩阵的子集相比,data.frame
列的子集化速度更快:
microbenchmark(body_dim$height==50000)
# Unit: milliseconds
# expr min lq median uq max neval
# body_dim$height == 50000 138.2619 148.5132 170.1895 170.8909 249.4592 100
microbenchmark(body_dim_mat[,1]==50000)
# Unit: milliseconds
# expr min lq median uq max neval
# body_dim_mat[, 1] == 50000 299.599 308.6066 310.9036 354.4641 432.7833 100
顺便说一句,这种情况是data.table
可以发光的地方:
require(data.table)
dt <- data.table(body_dim, key="height")
microbenchmark(dt[J(50000)]$length, unit="ms")
# Unit: milliseconds
# expr min lq median uq max neval
# dt[J(50000)]$length 0.96637 0.97908 0.989772 1.025257 2.588402 100