我已经开始相信数据框与矩阵相比没有优势,除了符号方便。但是,我在运行 unique
时注意到了这种奇怪现象。在矩阵和数据帧上:它似乎在数据帧上运行得更快。
a = matrix(sample(2,10^6,replace = TRUE), ncol = 10)
b = as.data.frame(a)
system.time({
u1 = unique(a)
})
user system elapsed
1.840 0.000 1.846
system.time({
u2 = unique(b)
})
user system elapsed
0.380 0.000 0.379
随着行数的增加,时序结果的差异甚至更大。所以,这个问题有两个部分。
unique
,然后转换回来。 unique
在 myUnique
,第 1 部分中的转换是什么? 注 1. 鉴于矩阵是原子的,似乎
unique
矩阵应该更快,而不是更慢。能够迭代固定大小的连续内存块通常应该比运行单独的链表 block 更快(我假设这就是数据帧的实现方式......)。注 2. 正如
data.table
的表现所证明的那样, 运行 unique
在数据框或矩阵上是一个相对糟糕的主意 - 请参阅 Matthew Dowle 的答案和相对时间的评论。我已经将很多对象迁移到数据表中,而这种性能是这样做的另一个原因。因此,尽管应该很好地为用户提供采用数据表的服务,但出于教学/社区的原因,我将暂时保留这个问题,即为什么矩阵对象需要更长的时间。下面的答案解决了时间都去哪儿了,以及我们如何才能获得更好的性能(即数据表)。答案近在咫尺 - 代码可通过 unique.data.frame
找到和 unique.matrix
. :) 对它在做什么的英文解释以及为什么缺少这一切。
最佳答案
unique.matrix
与 unique.array
相同> identical(unique.array, unique.matrix)
[1] TRUE
unique.array
必须处理多维数组,这需要额外的处理来“折叠”在二维情况下不需要的额外维度(对 paste()
的额外调用)。代码的关键部分是:collapse <- (ndim > 1L) && (prod(dx[-MARGIN]) > 1L)
temp <- if (collapse)
apply(x, MARGIN, function(x) paste(x, collapse = "\r"))
unique.data.frame
针对 2D 情况进行了优化,unique.matrix
不是。正如您所建议的那样,它可能不在当前的实现中。 请注意,在存在多个维度的所有情况下(unique.{array,matrix,data.table}),它是比较唯一性的字符串表示形式。对于浮点数,这意味着 15 个十进制数字,所以
NROW(unique(a <- matrix(rep(c(1, 1+4e-15), 2), nrow = 2)))
是
1
尽管NROW(unique(a <- matrix(rep(c(1, 1+5e-15), 2), nrow = 2)))
和
NROW(unique(a <- matrix(rep(c(1, 1+4e-15), 1), nrow = 2)))
都是
2
.你确定unique
是你想要的吗?
关于performance - 为什么在数据帧上运行 "unique"比 R 中的矩阵更快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7809570/