我正在运行仿真,我需要从矩阵中重复提取1列,并根据某种条件(例如<10)检查其每个值。但是,使用矩阵执行此操作的速度比使用data.frame执行相同操作的速度慢3倍。为什么会这样?
我想使用矩阵存储模拟数据,因为对于其他一些操作(例如,通过添加/减去值来更新列),它们会更快。如何以更快的方式提取列/矩阵的子集?
df <- data.frame(a = 1:1e4)
m <- as.matrix(df)
library(microbenchmark)
microbenchmark(
df$a,
m[ , "a"])
# Results; Unit: microseconds
# expr min lq mean median uq max neval cld
# df$a 5.463 5.8315 8.03997 6.612 8.0275 57.637 100 a
# m[ , "a"] 64.699 66.6265 72.43631 73.759 75.5595 117.922 100 b
microbenchmark(
df[1, 1],
df$a[1],
m[1, 1],
m[ , "a"][1])
# Results; Unit: nanoseconds
# expr min lq mean median uq max neval cld
# df[1, 1] 8248 8753.0 10198.56 9818.5 10689.5 48159 100 c
# df$a[1] 4072 4416.0 5247.67 5057.5 5754.5 17993 100 b
# m[1, 1] 517 708.5 828.04 810.0 920.5 2732 100 a
# m[ , "a"][1] 45745 47884.0 51861.90 49100.5 54831.5 105323 100 d
我希望基质柱的提取速度更快,但速度较慢。但是,从矩阵(即m[1, 1]
)中提取单个值比使用data.frame的两种方法都快。我不知道为什么会这样。
以上内容仅适用于选择列。选择行时,矩阵比data.frames快得多。还是不知道为什么。
microbenchmark(
df[1, ],
m[1, ],
df[ , 1],
m[ , 1])
# Result: Unit: nanoseconds
# expr min lq mean median uq max neval cld
# df[1, ] 16359 17243.5 18766.93 17860.5 19849.5 42973 100 c
# m[1, ] 718 999.5 1175.95 1181.0 1327.0 3595 100 a
# df[ , 1] 7664 8687.5 9888.57 9301.0 10535.5 42312 100 b
# m[ , 1] 64874 66218.5 72074.93 73717.5 74084.5 97827 100 d
答案 0 :(得分:3)
请考虑内置数据框BOD
。数据帧存储为列列表,下面显示的inspect
输出显示BOD
两列中每一列的地址。然后,将其第二列分配给BOD2
。请注意,BOD2
的地址与inspect
的{{1}}输出中显示的第二列的存储位置相同。也就是说,R所做的全部工作是BOD
指向BOD2
内的内存,以便创建BOD
。根本没有数据移动。另一种查看方式是比较BOD2
,BOD
和两者的大小,我们发现两者占用的内存量与BOD2
相同,因此肯定没有复制。 (接在代码之后。)
BOD
矩阵存储为一个带有维的长向量,而不是列的列表,因此提取列的策略有所不同。如果我们查看矩阵library(pryr)
BOD2 <- BOD[[2]]
inspect(BOD)
## <VECSXP 0x507c278>
## <REALSXP 0x4f81f48>
## <REALSXP 0x4f81ed8> <--- compare this address to address shown below
## ...snip...
BOD2 <- BOD[,2]
address(BOD2)
## [1] "0x4f81ed8"
object_size(BOD)
## 1.18 kB
object_size(BOD2)
## 96 B
object_size(BOD, BOD2) # same as object_size(BOD) above
## 1.18 kB
,提取的列m
所使用的内存,以及两者一起,我们将在下面看到,两者共同使用了单个对象的内存总和,表明存在数据复制。
m2
如果您的程序只能使用列提取功能,则可以对该部分使用数据框,然后一次转换为矩阵,然后像其余部分一样对其进行处理。
答案 1 :(得分:1)
我想这与内存中R的数据结构有关。 R中的矩阵是2维数组,与1维数组相同。变量是直接指向内存的点,因此提取单个值会非常快。要提取矩阵中的一列,需要进行一些计算,然后请求新的内存地址并将其保存。至于数据框,它实际上是列的列表,因此返回列会更快。 我猜就是那样,希望得到证明。