我想知道,例如,假设您想要转换某些矩阵,并且您需要类似
的内容Y[i,j] = i*j*X[i,j]
使用for循环比其他选项慢很多,而apply()不知道它正在使用哪个i和j。
我能想到的一个解决方案是使用列i,j,X定义一个类似数据帧的对象,然后使用mutate()来获得所需的Y值。
我有两个问题:
(a)是否可以使用apply()而不是for循环构造上述矩阵?如果存在,以这种方式构造它或使用mutate()技巧更有效吗?
(b)假设我有矩阵和data.frame对象表示。如果我想进行包含row和col索引的操作,哪个更有效?例如,如果想要一个统计量,如(Y [i,j] - mean(Y))²/(i * j)之和。我知道我可以用行和col索引构造矩阵然后只使用向量化函数,但它比使用mutate更好吗?
答案 0 :(得分:4)
根据矩阵的大小和稀疏度,您可以尝试的第一件事是使用row
和col
函数分别构造row
和column
索引,然后用它来转换你的矩阵:
X <- matrix(1:9, 3, 3)
row(X) * col(X) * X
# [,1] [,2] [,3]
#[1,] 1 8 21
#[2,] 4 20 48
#[3,] 9 36 81
然后对于(Y[i,j] - mean(Y))²/(i*j)
,它的类似内容:
Y <- row(X) * col(X) * X
(Y - mean(Y)) ^ 2 / (row(Y) * col(Y))
# [,1] [,2] [,3]
#[1,] 592.11111 150.222222 6.259259
#[2,] 227.55556 7.111111 85.629630
#[3,] 88.92593 18.962963 344.308642
这是完全向量化的方法,不需要apply
或for loop
,但需要额外的内存。
答案 1 :(得分:2)
我认为outer
可能比row(X) * col(X)
更快。
# Define dimensions
n.rows <- n.cols <- 1000
# Define matrix
X <- matrix(runif(n.rows * n.cols), ncol = n.cols)
# Psidom's approach
rowcol.method <- function(X){row(X) * col(X) * X}
# Approach using outer
outer.method <- function(X){outer(1:nrow(X), 1:ncol(X)) * X}
# Benchmark library
library(microbenchmark)
# Test
microbenchmark(
rowcol.method(X),
outer.method(X)
)
<强>结果:强>
Unit: milliseconds
expr min lq mean median uq max neval cld
rowcol.method(X) 20.895870 21.154815 23.795695 21.612485 22.584323 62.50660 100 b
outer.method(X) 5.608577 5.729724 6.883643 5.836526 5.977156 50.12508 100 a
比较输出
identical(rowcol.method(X), outer.method(X))
[1] TRUE
与其他计算类似,虽然外部方法有一个疯狂的异常值(221.66718 ms)。
# Define matrix
Y <- row(X) * col(X) * X
# Psidom's approach
rowcol.method.Y <- function(Y) {(Y - mean(Y)) ^ 2 / (row(Y) * col(Y))}
# Approach using outer
outer.method.Y <- function(Y) {(Y - mean(Y)) ^ 2 / outer(1:nrow(X), 1:ncol(X))}
# Test
microbenchmark(
rowcol.method.Y(Y),
outer.method.Y(Y)
)
<强>结果:强>
Unit: milliseconds
expr min lq mean median uq max neval cld
rowcol.method.Y(Y) 27.94405 30.18635 34.63551 33.32627 37.06467 46.58983 100 b
outer.method.Y(Y) 11.27064 12.66349 18.77192 15.66756 18.18864 221.66718 100 a
比较输出
identical(rowcol.method.Y(Y), outer.method.Y(Y))
[1] TRUE