我想知道是否存在与colMeans类似的高速min和max函数?
对于'max',虽然我可以使用'apply'模拟行为,如下所示:
colMax <- function (colData) {
apply(colData, MARGIN=c(2), max)
}
它似乎比基础包中的colMeans慢很多。
答案 0 :(得分:11)
pmax
比apply
快〜10倍。仍然没有colMeans
那么快。
data = matrix(rnorm(10^6), 100)
data.df = data.frame(t(data))
system.time(apply(data, MARGIN=c(2), max))
system.time(do.call(pmax, data.df))
system.time(colMeans(data))
> system.time(apply(data, MARGIN=c(2), max))
user system elapsed
0.133 0.006 0.139
> system.time(do.call(pmax, data.df))
user system elapsed
0.013 0.000 0.013
> system.time(colMeans(data))
user system elapsed
0.003 0.000 0.002
答案 1 :(得分:7)
总是可以从分析开始,但你的预感似乎是正确的:
R> colMax <- function(X) apply(X, 2, max)
R> library(rbenchmark)
R> Z <- matrix(rnorm(100*100), 100, 100)
R> benchmark(colMeans(Z), colMax(Z))
test replications elapsed relative user.self sys.self user.child
2 colMax(Z) 100 0.350 87.5 0.12 0 0
1 colMeans(Z) 100 0.004 1.0 0.00 0 0
R>
在这种情况下,您可能需要考虑使用inline和R的基本C API或我们的Rcpp包编写一个简单的C / C ++函数。这应该得到colMeans
- 相似的速度。
编辑:这是一个更完整的例子。 colMeans
仍然获胜,但我们越来越近了:
R> suppressMessages(library(inline))
R> suppressMessages(library(rbenchmark))
R>
R> colMaxR <- function(X) apply(X, 2, max)
R>
R> colMaxRcpp <- cxxfunction(signature(X_="numeric"), plugin="Rcpp",
+ body='
+ Rcpp::NumericMatrix X(X_);
+ int n = X.ncol();
+ Rcpp::NumericVector V(n);
+ for (int i=0; i<n; i++) {
+ Rcpp::NumericVector W = X.column(i);
+ V[i] = *std::max_element(W.begin(), W.end()); // from the STL
+ }
+ return(V);
+ ')
R>
R>
R> Z <- matrix(rnorm(100*100), 100, 100)
R> benchmark(colMeans(Z), colMaxR(Z), colMaxRcpp(Z), replications=1000, order="relative")
test replications elapsed relative user.self sys.self user.child
1 colMeans(Z) 1000 0.036 1.00000 0.04 0 0
3 colMaxRcpp(Z) 1000 0.050 1.38889 0.05 0 0
2 colMaxR(Z) 1000 1.002 27.83333 1.01 0 0
R>
答案 2 :(得分:6)
我发布的答案只是因为我没有足够的声誉来评论或投票/投票。
pmax
比apply
快10倍的最佳答案并不总是正确的。例如,计算每列中10 ^ 6个数字的最大值。
data <- matrix(rnorm(10^8), 10^6)
data.t <- t(data)
data.df <- data.frame(data)
data.t.df = data.frame(data.t)
system.time(a <- apply(data, MARGIN=c(2), max))
system.time(b <- sapply(data.df, max))
system.time(e <- sapply(seq_len(ncol(data)), function(x) max(data[, x])))
system.time(c <- do.call(pmax, data.t.df))
system.time(d <- colMaxs(data))
> system.time(a <- apply(data, MARGIN=c(2), max))
user system elapsed
2 0 2
> system.time(b <- sapply(data.df, max))
user system elapsed
0.25 0.00 0.25
> system.time(e <- sapply(seq_len(ncol(data)), function(x) max(data[, x])))
user system elapsed
0.83 0.00 0.83
> system.time(c <- do.call(pmax, data.t.df))
user system elapsed
15.94 0.00 15.96
> system.time(d <- colMaxs(data))
user system elapsed
0.21 0.00 0.20
现在计算每列中100个数字的最大值。
system.time(a <- apply(data.t, MARGIN=c(2), max))
system.time(b <- sapply(data.t.df, max))
system.time(e <- sapply(seq_len(ncol(data.t)), function(x) max(data.t[, x])))
system.time(c <- do.call(pmax, data.df))
system.time(d <- colMaxs(data.t))
> system.time(a <- apply(data.t, MARGIN=c(2), max))
user system elapsed
4.41 0.00 4.42
> system.time(b <- sapply(data.t.df, max))
user system elapsed
3.23 0.00 3.23
> system.time(e <- sapply(seq_len(ncol(data.t)), function(x) max(data.t[, x])))
user system elapsed
3.57 0.00 3.57
> system.time(c <- do.call(pmax, data.df))
user system elapsed
1.56 0.00 1.56
> system.time(d <- colMaxs(data.t))
user system elapsed
0.25 0.00 0.25
当行数较小(例如100)时,似乎pmax
仅在速度上与apply
相当或更好。当行数很大(例如10 ^ 6)时,pmax
比apply
慢得多。
在任何情况下,colMaxs
包中的matrixStats
都是最快的,似乎是最佳选择。
答案 3 :(得分:5)
matrixStats包有很多很棒的功能,包括colMaxs。
答案 4 :(得分:1)
pmin
和pmax
可以轻松地用于获取行分和最大值,但对于列来说有点尴尬。
# row maxes
do.call("pmax",mtcars)
[1] 160.0 160.0 108.0 258.0 360.0 225.0 360.0 146.7 140.8 167.6 167.6 275.8
[13] 275.8 275.8 472.0 460.0 440.0 78.7 75.7 71.1 120.1 318.0 304.0 350.0
[25] 400.0 79.0 120.3 113.0 351.0 175.0 335.0 121.0
# col maxes
do.call("pmax",data.frame(t(mtcars)))
[1] 33.900 8.000 472.000 335.000 4.930 5.424 22.900 1.000 1.000
[10] 5.000 8.000
另一个选项是max.col
,默认情况下也会(令人困惑)给出行最大值。
mmtcars <- as.matrix(mtcars)
mmtcars[max.col(t(mmtcars))+(seq(dim(mmtcars)[2])-1)*dim(mmtcars)[1]]
[1] 33.900 8.000 472.000 335.000 4.930 5.424 22.900 1.000 1.000
[10] 5.000 8.000