等效于 min() 的 rowMeans()
Posted
技术标签:
【中文标题】等效于 min() 的 rowMeans()【英文标题】:Equivalent to rowMeans() for min() 【发布时间】:2011-09-14 09:00:45 【问题描述】:我在 R 邮件列表上看到这个问题被问了多次,但仍然找不到满意的答案。
假设我是一个矩阵m
m <- matrix(rnorm(10000000), ncol=10)
我可以通过以下方式获得每一行的平均值:
system.time(rowMeans(m))
user system elapsed
0.100 0.000 0.097
但是通过获取每一行的最小值
system.time(apply(m,1,min))
user system elapsed
16.157 0.400 17.029
需要超过 100 倍的时间,有没有办法加快速度?
【问题讨论】:
【参考方案1】:library("sos")
findFn("rowMin")
在来自 Bioconductor 的 Biobase
包中获得成功...
source("http://bioconductor.org/biocLite.R")
biocLite("Biobase")
m <- matrix(rnorm(10000000), ncol=10)
system.time(rowMeans(m))
## user system elapsed
## 0.132 0.148 0.279
system.time(apply(m,1,min))
## user system elapsed
## 11.825 1.688 13.603
library(Biobase)
system.time(rowMin(m))
## user system elapsed
## 0.688 0.172 0.864
不如rowMeans
快,但比apply(...,1,min)
快很多
【讨论】:
谢谢,我不知道 sos 包,rowMin 也解决了我的问题。 也想为do.call
解决方案计时?【参考方案2】:
您可以使用pmin
,但您必须将矩阵的每一列放入一个单独的向量中。一种方法是将其转换为 data.frame,然后通过 do.call
调用 pmin
(因为 data.frames 是列表)。
system.time(do.call(pmin, as.data.frame(m)))
# user system elapsed
# 0.940 0.000 0.949
system.time(apply(m,1,min))
# user system elapsed
# 16.84 0.00 16.95
【讨论】:
我喜欢使用do.call
。我想到了pmin
,但没有想到一个巧妙的方法来合并它。所有很酷的孩子似乎都可以使用do.call
来实现他们的目标……我需要对此进行一些阅读。
do.call
在您希望能够动态创建函数参数时派上用场(通常是在不知道通过 ...
传递的参数数量时)。
很好的答案,谢谢!使用 pmin.int() 甚至更快
Hadley 的 functions that you need to know 词汇量不错。还有pmin
。
@danas.zuokas: do.call(pmin, c(na.rm=TRUE, lapply(...)))
【参考方案3】:
我一直想在 R 2.13.0 中试用新的 compiler
包。这基本上遵循 Dirk here 概述的帖子。
library(compiler)
library(rbenchmark)
rowMin <- function(x, ind) apply(x, ind, min)
crowMin <- cmpfun(rowMin)
benchmark(
rowMin(m,1)
, crowMin(m,1)
, columns=c("test", "replications","elapsed","relative")
, order="relative"
, replications=10)
)
结果:
test replications elapsed relative
2 crowMin(m, 1) 10 120.091 1.0000
1 rowMin(m, 1) 10 122.745 1.0221
至少可以说有点不合时宜,不过看起来您还有其他一些不错的选择。
【讨论】:
感谢您的回答,我将不得不深入研究您的回答,这对我来说是新领域:) 编译器在优化显式循环方面效果更好。试试例如:rowMin <- function(x) n <- nrow(x);r <- numeric(n);for (i in 1:n) r[i] <- min(x[i,]);r
【参考方案4】:
不是特别 R-idiosyncratic,但肯定最快的方法就是使用 pmin
并遍历列:
x <- m[,1]
for (i in 2:ncol(m)) x <- pmin(x, m[,i])
在我的机器上,对于 1e+07x10 矩阵,它只需要比 rowMeans 长 3 倍的时间,并且比通过 data.frame
的 do.call
方法稍快。
【讨论】:
还有pmin(m[,1], m[,2], m[,3], m[,4], m[,5], m[,6], m[,7], m[,8], m[,9], m[,10])
的另一个速度提升。 Joshua as.data.frame
很耗时。
虽然打字速度不快,但对于不同的输入来说一般:)
我在对 Joshua 答案的评论中添加了更通用的解决方案。【参考方案5】:
如果你想坚持使用 CRAN 包,那么 matrixStats
和 fBasics
包都具有函数 rowMins
[注意 s
不在 Biobase
函数中 em>] 以及各种其他行和列统计信息。
【讨论】:
【参考方案6】:聚会迟到了,但作为matrixStats 的作者,如果有人发现这一点,请注意matrixStats::rowMins()
这些天很快,例如
library(microbenchmark)
library(Biobase) # rowMin()
library(matrixStats) # rowMins()
options(digits=3)
m <- matrix(rnorm(10000000), ncol=10)
stats <- microbenchmark(
rowMeans(m), ## A benchmark by OP
rowMins(m),
rowMin(m),
do.call(pmin, as.data.frame(m)),
apply(m, MARGIN=1L, FUN=min),
times=10
)
> stats
Unit: milliseconds
expr min lq mean median uq max
rowMeans(m) 77.7 82.7 85.7 84.4 90.3 98.2
rowMins(m) 72.9 74.1 88.0 79.0 90.2 147.4
rowMin(m) 341.1 347.1 395.9 383.4 395.1 607.7
do.call(pmin, as.data.frame(m)) 326.4 357.0 435.4 401.0 437.6 657.9
apply(m, MARGIN = 1L, FUN = min) 3761.9 3963.8 4120.6 4109.8 4198.7 4567.4
【讨论】:
@HenirkB 如果 matrixStats rowMins 也可以处理 data.frames,那就太好了(无需先将其转换为矩阵) @skan,不幸的是由于各种原因,这不是matrixStats,请看github.com/HenrikBengtsson/matrixStats/issues/18以上是关于等效于 min() 的 rowMeans()的主要内容,如果未能解决你的问题,请参考以下文章
PHP PDO 等效于 mysql_num_rows [重复]
等效于 R 中 big.matrix 的 row() 和 col()
等效于 Jetpack Compose Lazy Column/Row 中的 adapter.notifydatasetchange 或 Diffutils
MySQL FOUND_ROWS() 方法的 SQL 等效项是啥?