R语言:将计算子向量中6占比的循环代码向量化
嘿,我来帮你优化这段计算子向量中数字6占比的代码!你提到的获取不同子向量中6的计数确实是原代码里效率瓶颈的核心,咱们一步步来改进它:
问题分析
原代码的两个主要性能问题:
- 每次循环调用
table():table()会统计子向量中所有数字的频率,但你只关心数字6的数量,这会做很多无用功;而且随着子向量越来越长,重复遍历的开销会越来越大。 - 用
c()动态扩展sixes.ratio:每次调用c()都会创建一个新向量并复制原有数据,当循环次数达到1000次(对应10万样本)时,内存开销和时间损耗会非常明显。
向量化优化方案(推荐)
R最擅长向量化操作,我们可以用**累积和(cumsum())**来一次性计算所有位置的累积6的数量,再直接提取我们需要的步长值,完全不用循环:
rolls.max <- 100000 a <- sample(1:6, size=rolls.max, replace=TRUE) # 第一步:标记每个元素是否为6,得到逻辑向量 is_six <- a == 6 # 第二步:计算累积的6的数量——前1个、前2个...前100000个元素中6的总数 cumulative_sixes <- cumsum(is_six) # 第三步:提取每100步的累积值,计算占比 indices <- seq(100, rolls.max, by=100) sixes.ratio <- cumulative_sixes[indices] / indices
这个方案的优势:
- 只需要遍历原始向量一次,计算效率比循环高几个数量级
- 直接预分配结果向量,避免了动态扩展的内存浪费
- 逻辑清晰,代码简洁易读
优化后的循环版本(如果坚持用循环)
如果你因为某些原因必须保留循环结构,也可以做两个关键优化:
- 预分配结果向量的长度,避免
c()的动态扩展 - 用
sum()代替table()来统计6的数量,因为sum()只关注我们需要的条件,比table()高效得多
rolls.max <- 100000 a <- sample(1:6, size=rolls.max, replace=TRUE) # 预分配结果向量,长度等于循环次数 n_steps <- rolls.max %/% 100 sixes.ratio <- numeric(n_steps) for(i in 1:n_steps) { end <- i * 100 # 直接统计前end个元素中等于6的数量,比table快很多 sixes.count <- sum(a[1:end] == 6) sixes.ratio[i] <- sixes.count / end }
这样修改后,循环的性能会比原代码提升不少,尤其是当样本量很大的时候。
内容的提问来源于stack exchange,提问作者Codey
相关产品推荐
相关产品推荐

