r - 如何在矩阵中按行将 0 分配给最小值(以快速/有效的方式)?
问题描述
一个有一个Lambda
包含p
列和n
行的矩阵,并且对于每一行都希望将所有值分配给0
除了第一列中的值和其他列中的最大值(在这个意义上p - 2
,避开第一列之后的所有最小值)。
目前我正在使用for
循环执行此操作,如下所示:
set.seed(60)
(Lambda = matrix(sample.int(30),5))
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 19 20 27 18 15 25
[2,] 16 28 1 4 22 7
[3,] 2 10 8 23 3 12
[4,] 5 6 9 17 11 29
[5,] 26 30 24 13 14 21
m <- ncol(Lambda) - 2
for(ir in seq_len(nrow(Lambda))){
Lambda[ir, match(tail(sort(abs(Lambda[ir, 2:ncol(Lambda)]), decreasing = TRUE), m), Lambda[ir,])] <- 0
}
Lambda
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 19 0 27 0 0 0
[2,] 16 28 0 0 0 0
[3,] 2 0 0 23 0 0
[4,] 5 0 0 0 0 29
[5,] 26 30 0 0 0 0
很好,一个人得到了目标,但如果有很多行,这将成为一个问题。有没有不使用for
循环的解决方案?可能是这样,lapply
但我不确定它是否真的有效。也许data.table
在转换矩阵之后?
谢谢!
解决方案
所以有关
有没有不使用 for 循环的解决方案。
对于某些算法,您只需要编写一个 for 循环。没关系!为 lapply 之类的东西交换 for 循环并不是真正的性能改进(请参阅https://stackoverflow.com/a/42440872/4917834)。
不过,可以加快您的代码速度:
# your example
set.seed(60)
Lambda = matrix(sample.int(30),5)
original <- function(Lambda) {
m <- ncol(Lambda) - 2
for (ir in seq_len(nrow(Lambda))){
Lambda[ir, match(tail(sort(abs(Lambda[ir, 2:ncol(Lambda)]), decreasing = TRUE), m), Lambda[ir,])] <- 0
}
Lambda
}
original(Lambda)
# a faster alternative
proposal <- function(Lambda) {
nc <- ncol(Lambda)
for (i in seq_len(nrow(Lambda))) {
m <- which.max(abs(Lambda[i, -1L]))
Lambda[i, (2:nc)[-m]] <- 0
}
Lambda
}
proposal(Lambda)
让我们对这两种方法进行基准测试:
bch <- bench::mark(
original(Lambda),
proposal(Lambda)
)
summary(bch, relative = TRUE)
# A tibble: 2 x 13
expression min median `itr/sec` mem_alloc `gc/sec` n_itr n_gc
<bch:expr> <dbl> <dbl> <dbl> <dbl> <dbl> <int> <dbl>
1 original(Lambda) 25.7 24.1 1 1 1 1447 4
2 proposal(Lambda) 1 1 23.6 1 2.57 9997 3
所以proposal
比您的原始解决方案快大约 24 倍(原始解决方案的中位时间为 313.8µs,建议为 13.1µs)。如果这还不够快,可能值得寻找在 C 或 C++ 中实现此功能的包。我玩过matrixStats
但没有运气。或者,您可以将其移植到 C++ 中,Rcpp
这样也可以加快代码速度。
推荐阅读
- java - 无法解决 ArithmeticException?/ 零?
- r - gghistogram + gganimate中的鬼条
- date - 将日期格式 yywwd 转换为 dd-mm-yy
- c++ - 关于在 STL 列表和函数对象 C++ 中使用 while 循环而不是 for 的问题
- javascript - 角度(表单数组)值更改不起作用
- opencv - 使用opencv将浮点和双精度值保存或读取到yaml文件时值发生变化
- android - 转换数组列表
到 MutableLiveData > 在科特林 - ios - Do i need IOS developer account for React native ios developing
- c++ - 使用 STL 向量的自定义向量容器
- java - 发送不带“根”的 JSON 对象