Tim*_*Tim 5 r matrix dataframe
考虑以下基准测试(Windows机器上的R 3.4.1):
library(rbenchmark)
mtx <- matrix(runif(1e8), ncol = 100)
df <- as.data.frame(mtx)
colnames(mtx) <- colnames(df) <- paste0("V", 1:100)
benchmark(
mtx[5000:7000, 80],
mtx[5000:7000, "V80"],
mtx[, "V80"][5000:7000],
mtx[, "V80", drop = FALSE][5000:7000, ],
mtx[5000:7000, , drop = FALSE][, "V80"],
#mtx$V80[5000:7000], # does not apply
replications = 5000
)
## test replications elapsed relative user.self sys.self user.child sys.child
## 4 mtx[, "V80", drop = FALSE][5000:7000, ] 5000 64.71 588.273 47.44 16.61 NA NA
## 3 mtx[, "V80"][5000:7000] 5000 72.15 655.909 52.90 18.18 NA NA
## 2 mtx[5000:7000, "V80"] 5000 0.11 1.000 0.11 0.00 NA NA
## 5 mtx[5000:7000, , drop = FALSE][, "V80"] 5000 7.47 67.909 5.89 1.47 NA NA
## 1 mtx[5000:7000, 80] 5000 0.13 1.182 0.12 0.00 NA NA
benchmark(
df[5000:7000, 80],
df[5000:7000, "V80"],
df[, "V80"][5000:7000],
df[, "V80", drop = FALSE][5000:7000, ],
df[5000:7000, , drop = FALSE][, "V80"],
df$V80[5000:7000],
replications = 5000
)
## test replications elapsed relative user.self sys.self user.child sys.child
## 6 df$V80[5000:7000] 5000 0.13 1.000 0.12 0.00 NA NA
## 4 df[, "V80", drop = FALSE][5000:7000, ] 5000 0.33 2.538 0.33 0.00 NA NA
## 3 df[, "V80"][5000:7000] 5000 0.17 1.308 0.17 0.00 NA NA
## 2 df[5000:7000, "V80"] 5000 0.15 1.154 0.16 0.00 NA NA
## 5 df[5000:7000, , drop = FALSE][, "V80"] 5000 13.63 104.846 12.91 0.39 NA NA
## 1 df[5000:7000, 80] 5000 0.19 1.462 0.17 0.00 NA NA
Run Code Online (Sandbox Code Playgroud)
时差非常大.这是为什么?什么是该子集以及为什么推荐呢?鉴于基准,数据框架的mtx[i, colname]矩阵和df$colname[i](但似乎没有多大差别)的方式似乎是最节省时间的,但是我们是否应该更喜欢任何方法?
小智 1
主要原因在于矩阵和数据帧背后的 R 数据结构。矩阵基本上是一个具有行数 x 列数(主要是数字)条目(R 的默认矩阵不是稀疏矩阵)和维度属性的对象。因此,您的前 2 个命令
mtx[5000:7000, 80],
mtx[5000:7000, "V80"]
Run Code Online (Sandbox Code Playgroud)
再次提取矩阵,R 不仅为其分配值,而且为其维度创建新的矩阵对象,而不是作为 R 的默认对象的简单向量。
另一方面,R 中的 data.frame 根据定义是一种特殊类型的列表对象,其中每个列对象的长度必须相同,而列可能包含不同类型的变量(数字、字符串等)。矩阵只能包含单一类型的变量,默认情况下这是最通用的变量。因此,
df[5000:7000, 80]
Run Code Online (Sandbox Code Playgroud)
提取第 80 列的向量,然后从该列中提取位置 5000-7000 上的值。对于 R 来说,向量的处理比矩阵对象简单得多,因此速度要快得多。
但是,如果您选择 drop=FALSE,则会强制 R 在选择第 80 列时不使用简单的矢量对象,而是将其视为 data.frame/list 对象。列表是 R 对象中最通用和最灵活的类型,因为它们的大小和条目没有限制,但这是以它们处理起来最困难和最耗时为代价的,正如您在比较时可以观察到的那样
mtx[5000:7000, , drop = FALSE][, "V80"]
df[5000:7000, , drop = FALSE][, "V80"]
Run Code Online (Sandbox Code Playgroud)
从数据帧中,您获得另一个 data.frame/list,而矩阵仍然返回一个比列表处理速度更快的矩阵。