gpt4 book ai didi

r - 为什么在 R 的这个例子中 data.table 这么慢

转载 作者:行者123 更新时间:2023-12-03 22:52:18 25 4
gpt4 key购买 nike

这与 R- view all the columns names with any NA 有关

我比较了 data.frame 和 data.table 版本,发现 data.table 慢了 10 倍。这与大多数带有 data.table 的代码相反,后者确实比 data.frame 版本快得多。

set.seed(49)
df1 <- as.data.frame(matrix(sample(c(NA,1:200), 1e4*5000, replace=TRUE), ncol=5000))

library(microbenchmark)
f1 <- function() {names(df1)[sapply(df1, function(x) any(is.na(x)))]}
f2 <- function() { setDT(df1); names(df1)[df1[,sapply(.SD, function(x) any(is.na(x))),]] }
microbenchmark(f1(), f2(), unit="relative")
Unit: relative
expr min lq median uq max neval
f1() 1.00000 1.00000 1.000000 1.000000 1.000000 100
f2() 10.56342 10.20919 9.996129 9.967001 7.199539 100

预先设置DT:

set.seed(49)
df1 <- as.data.frame(matrix(sample(c(NA,1:200), 1e4*5000, replace=TRUE), ncol=5000))
setDT(df1)

library(microbenchmark)
f1 <- function() {names(df1)[sapply(df1, function(x) any(is.na(x)))]}
f2 <- function() {names(df1)[df1[,sapply(.SD, function(x) any(is.na(x))),]] }
microbenchmark(f1(), f2(), unit="relative")
Unit: relative
expr min lq median uq max neval
f1() 1.00000 1.00000 1.00000 1.00000 1.000000 100
f2() 10.64642 10.77769 10.79191 10.77536 7.716308 100

可能是什么原因?

最佳答案

data.table 在这种情况下不会提供任何神奇的加速。

# Unit: relative
# expr min lq median uq max neval
# f1() 1.000000 1.000000 1.000000 1.000000 1.000000 10
# f2() 8.350364 8.146091 6.966839 5.766292 4.595742 10

为了比较,在我的机器上,时间在上面。

在“data.frame”方法中,您实际上只是使用 data.frame 是一个列表并遍历该列表这一事实。

data.table 方法中,您正在做同样的事情,但是通过使用 .SD,您将强制复制整个 data.table(使可用的数据)。这是 data.table 巧妙地将您需要的数据复制到 j 表达式的结果。通过使用 .SD,您将复制所有内容。

提高性能的最佳方法是使用 anyNA 这是一种更快的(原始)方法来查找任何 NA 值(一旦找到第一个值就会停止,而不是创建整个is.na 向量,然后扫描任何 TRUE 值)

对于更定制的测试,您可能需要编写(Rcpp 糖样式)函数

您还会发现 unlist(lapply(...)) 通常会比 sapply 更快。​​

f3 <- function() names(df1)[unlist(lapply(df1, anyNA))]
f4 <- function() names(df1)[sapply(df1, anyNA)]
microbenchmark(f1(), f2(),f3() ,f4(),unit="relative",times=10)

# Unit: relative
# expr min lq median uq max neval
# f1() 10.988322 11.200684 11.048738 10.697663 13.110318 10
# f2() 92.915256 92.000781 91.000729 88.421331 103.627198 10
# f3() 1.000000 1.000000 1.000000 1.000000 1.000000 10
# f4() 1.591301 1.663222 1.650136 1.652701 2.133943 10

在 Martin Morgan 的建议下

f3.1 <- function() names(df1)[unlist(lapply(df1, anyNA),use.names=FALSE)]

microbenchmark(f1(), f2(),f3() ,f3.1(),f4(),unit="relative",times=10)
# Unit: relative
# expr min lq median uq max neval
# f1() 18.125295 17.902925 18.17514 18.410682 9.2177043 10
# f2() 147.914282 145.805223 145.05835 143.630573 81.9495460 10
# f3() 1.608688 1.623366 1.66078 1.648530 0.8257108 10
# f3.1() 1.000000 1.000000 1.00000 1.000000 1.0000000 10
# f4() 2.555962 2.553768 2.60892 2.646575 1.3510561 10

关于r - 为什么在 R 的这个例子中 data.table 这么慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26091445/

25 4 0