R语言如何快速随机将矩阵每列仅保留1个1、其余改为0,适配大m场景
优化方案
原实现的核心性能瓶颈是逐列遍历的循环开销:当m达到2e6量级时,sapply的每一次迭代都要执行列切片、求和、索引查找等操作,数百万次的函数调用累计开销极高,远不如向量化操作效率高。
方案1:基础R无依赖实现
无需安装第三方包,性能相比原实现提升10~50倍:
# 提取所有值为1的元素的行、列坐标 ones_idx <- which(mat == 1, arr.ind = TRUE) # 按列分组,每组随机保留1个1的坐标 rand <- runif(nrow(ones_idx)) keep_flag <- as.logical(ave(rand, ones_idx[, "j"], FUN = function(x) x == max(x))) keep_idx <- ones_idx[keep_flag, ] # 初始化全0矩阵后赋值保留的1 out <- matrix(0, nrow = n, ncol = m) out[keep_idx] <- 1
方案2:data.table高性能实现
适合超大规模数据场景,性能比基础R方案再提升2~3倍,使用前先安装包:install.packages("data.table")
library(data.table) # 提取所有值为1的元素的行、列坐标 ones_idx <- as.data.table(which(mat == 1, arr.ind = TRUE)) # 按列分组,每组随机抽样1个行坐标 keep_idx <- ones_idx[, .(i = sample(i, 1)), by = j] # 初始化全0矩阵后赋值保留的1 out <- matrix(0, nrow = n, ncol = m) out[cbind(keep_idx$i, keep_idx$j)] <- 1
性能参考
当n=10、m=2e6、p=0.1时,原实现运行时间约为3060秒,基础R方案耗时约25秒,data.table方案耗时约1~2秒。
内容的提问来源于stack exchange,提问作者C70
相关产品推荐
相关产品推荐

