R语言dplyr如何按行按条件随机选择取值创建新变量
dplyr按行条件随机选值生成新变量实现方案
规则回顾
需要生成new_regsiege变量,逐行满足以下逻辑:
- 若当前行
regsiege取值为XX,且同列组中nbeta_regXX的取值大于0,则new_regsiege直接取原regsiege值 - 若当前行
regsiege取值为XX,且同列组中nbeta_regXX的取值等于0,则new_regsiege从当前行所有nbeta_reg前缀列取值大于0对应的区域编号中,随机抽取1个作为结果
示例测试数据
mydf <- data.frame( regsiege = c("11","24","93"), nbeta_reg11 = c(0,1,0), nbeta_reg24 = c(1,1,0), nbeta_reg93 = c(1,1,1) )
完整可运行代码
library(dplyr) mydf %>% rowwise() %>% mutate( # 提取当前行所有nbeta值大于0的有效区域编号,作为随机抽取的候选池 valid_reg_pool = gsub( "nbeta_reg", "", names(.)[startsWith(names(.), "nbeta_reg")][c_across(starts_with("nbeta_reg")) > 0] ), # 读取当前regsiege对应的nbeta取值 current_match_val = c_across(paste0("nbeta_reg", regsiege)), # 按规则赋值 new_regsiege = if_else( current_match_val > 0, regsiege, sample(valid_reg_pool, size = 1) ) ) %>% # 移除中间计算用的临时列,解除按行分组 select(-valid_reg_pool, -current_match_val) %>% ungroup()
逻辑说明
- 开启
rowwise()按行计算模式,保证每行的候选池、判断逻辑独立运行,不会跨行取值 - 用
starts_with("nbeta_reg")批量匹配所有区域值列,不需要硬编码列名,后续新增区域列时代码不需要修改 c_across()是dplyr中按行合并多列值的专用函数,适配rowwise模式下的批量列操作- 提前计算有效候选池
valid_reg_pool,避免重复判断,代码可读性更高 - 随机抽取用基础R的
sample()函数,设置抽取大小为1,满足等概率随机选值的要求
运行结果和预期完全一致:第二行、第三行因为原regsiege对应nbeta值大于0,固定返回原regsiege值;第一行原regsiege对应nbeta值为0,会从"24"和"93"中随机选一个,符合预期要求。
内容的提问来源于stack exchange,提问作者Damien Dotta
相关产品推荐
相关产品推荐

