当前位置: 首页 > 知识库问答 >
问题:

为什么数据表在 R 中的此示例中如此缓慢

宗政卓
2023-03-14

这与 R- 查看具有任何 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

预先设置:

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

可能是什么原因?

共有1个答案

施华奥
2023-03-14

在这种情况下,< code>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”方法中,您实际上只是使用数据.frame是一个列表的事实,并迭代该列表。

在< code>data.table方法中,您可以做同样的事情,但是要使用< code >。SD,您将强制复制整个data.table(以使数据可用)。这是< code>data.table聪明地只将您需要的数据复制到< code>j表达式中的结果。通过使用。SD,你在复制所有的东西。

提高性能的最佳方法是使用<code>anyNA

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

你还会发现,取消列表(拉普利(...))通常比苏普利更快。

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

根据马丁·摩根的建议

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
 类似资料:
  • Micronaut用75秒启动它的Hello-World示例项目是正常的吗?这似乎与描述该框架的方式非常不一致。我在一台MacBook pro上运行了这款产品,规格不错,这个项目是按照Micronaut用户指南中的步骤创建的,没有进行任何定制。无论我是从IDE还是从uber JAR开始,情况都是一样的。 最后,我对Micronaut很感兴趣,因为几个月前我偶然发现了它,部分原因是spring变得过

  • 问题内容: 注意:我知道该方法。 在下面的代码示例中,我不明白为什么在方法抛出,但不是在方法。 问题答案: 原因如下:正如中所说: 此类的迭代器和方法返回的迭代器是快速失败的:如果在创建迭代器后的任何时间以任何方式对列表进行结构修改,除非通过迭代器自己的remove或add方法,否则迭代器将抛出。 该检查是在迭代器的方法中完成的(如你在stacktrace中所看到的)。但是,next()只有在传递

  • 为了好玩,我决定用红宝石编码伊拉托西筛子。只是为了好玩,因为我知道有一个库函数。而且,我认为它会很快。但我发现它并不是,至少在我的ruby 1.9.3中,我的上网本速度快了好几倍,甚至在c中也没有。为什么会这样呢。 库实现: 我在红宝石: 图书馆非常慢。

  • 问题内容: 试图弄清楚React的基础知识。 查看此页面上的第二个示例:https : //facebook.github.io/react/ 我看到tick()函数设置Timer类的状态,将前一个值加1。 但是,当我尝试实现自己的简单Counter类时,它失败了,并且出现控制台错误,提示 无法读取未定义的setState属性。 一些谷歌搜索显示我必须将其绑定到增量函数。但是,为什么在我看到的第一

  • 我有两个填充数组[Int]的实现,如下所述。第一个以84毫秒的速度执行,第二个以100倍的速度执行: 为什么第二个变种需要100倍以上的时间?它不是GC,因为我可以删除第一次执行,同时删除第二次执行。我使用Scala 3在Java 11上运行它: 更重要的是,如果你打开implementation,您将通过while。。。 PS:我在Scala 2.12上重复这个测试: 所以Scala 3的问题.

  • NodeJS版本8.11-警告是“此错误源于在没有catch块的情况下抛出异步函数,或者拒绝未用.catch()处理的promise。” 这两个都不是真的,您可以通过检查我的测试用例看出这一点: 翻转标志,查看相同的代码运行时是否有错误。