如何优化从矩阵统计频次的R代码?兼顾可读性与运行速度
代码优化:可读性+运行速度优化方案
这段代码核心是按给定概率模拟1000次26人选秀,统计每个球员在各顺位被选中的次数,下面是优化后的实现:
优化后代码(tidyverse风格)
library(tidyverse) # 模拟参数(语义化命名,方便后续调整) num_players <- 26 num_simulations <- 1000 player_names <- letters # 生成并归一化球员选秀概率 player_probs <- rbeta(num_players, 10, 20) player_probs <- player_probs / sum(player_probs) # 执行选秀模拟:行=选秀顺位,列=模拟次数,每个值是选中的球员编号 draft_simulations <- replicate( n = num_simulations, expr = sample(1:num_players, num_players, replace = FALSE, prob = player_probs) ) %>% matrix(nrow = num_players, ncol = num_simulations) # 高效统计各球员在各顺位的出现次数 draft_counts <- table( Draft_Pick = rep(1:num_players, num_simulations), Player_ID = as.vector(draft_simulations) ) %>% as_tibble() %>% pivot_wider(names_from = Draft_Pick, values_from = n, values_fill = 0) %>% mutate(Skater = player_names[Player_ID]) %>% select(Skater, everything(), -Player_ID)
优化细节
可读性提升
- 变量语义化:把
random_probs改为player_probs,新增num_players、num_simulations参数变量,参数含义一目了然,后续调整模拟规模更便捷 - 逻辑模块化:将参数配置、概率生成、模拟执行、统计整理拆分为独立区块,逻辑线条清晰
- 注释辅助:关键步骤添加注释,明确每部分作用
运行速度提升
- 替换循环统计:原代码用
map循环26次,每次生成26×1000的逻辑矩阵再求和,效率极低。优化后用table()一次性统计所有顺位-球员的组合频数,大幅减少重复计算 - 减少冗余转换:去掉原代码中
do.call(rbind, list_sims)这类冗余的数组拼接操作,直接用pivot_wider完成宽表转换,降低数据转换开销
纯Base R替代方案(无tidyverse依赖)
如果不需要tidyverse语法风格,用纯Base R实现速度会更快:
# 配置参数 num_players <- 26 num_simulations <- 1000 player_names <- letters # 生成并归一化概率 player_probs <- rbeta(num_players, 10, 20) player_probs <- player_probs / sum(player_probs) # 执行选秀模拟 draft_simulations <- replicate( num_simulations, sample(1:num_players, num_players, replace = FALSE, prob = player_probs) ) # 统计并整理结果 draft_counts <- table(row(draft_simulations), draft_simulations) draft_counts <- as.data.frame.matrix(draft_counts) colnames(draft_counts) <- paste0("Pick_", 1:num_players) draft_counts$Skater <- player_names draft_counts <- draft_counts[, c("Skater", paste0("Pick_", 1:num_players))]
内容的提问来源于stack exchange,提问作者spazznolo
相关产品推荐
相关产品推荐

