如何按name分组,为含ignore=0的组随机选行对time应用函数?
使用dplyr实现需求的解决方案
首先定义示例函数f:
f <- function(x) x - 30
核心dplyr代码实现
library(dplyr) set.seed(123) # 设置随机种子,保证随机选择的结果可复现 result_df <- df %>% group_by(name) %>% mutate( # 标记当前组是否存在ignore=0的行 has_zero = any(ignore == 0), # 在有0的组中,随机挑选一行ignore=0的行号;无0的组设为NA selected_row = if (has_zero) sample(which(ignore == 0), size = 1) else NA, # 仅对选中的行应用函数f,其余行保留原time值 time = ifelse(row_number() == selected_row, f(time), time) ) %>% # 移除过程中生成的辅助列 select(-has_zero, -selected_row) %>% ungroup()
代码逻辑解释
group_by(name):按name完成分组,匹配需求第一步。has_zero = any(ignore == 0):快速判断组内是否需要执行修改操作。selected_row = if (has_zero) sample(which(ignore == 0), size = 1) else NA:精准定位要修改的行,sample函数保证随机选择。time = ifelse(row_number() == selected_row, f(time), time):对目标行应用函数,其余行保持原样。select(-has_zero, -selected_row):清理辅助列,保证输出数据框的简洁性。ungroup():取消分组,恢复普通数据框结构。
验证输出结果
运行上述代码后,输出结果与预期一致(因设置了随机种子123,选中的行固定):
print(result_df) # # A tibble: 12 × 3 # name ignore time # <chr> <dbl> <dbl> # 1 abc 0 1 # 2 abc 1 32 # 3 abc 0 33 # 4 def 0 4 # 5 def 1 35 # 6 ghi 1 36 # 7 ghi 1 37 # 8 jkl 0 38 # 9 jkl 0 39 # 10 jkl 0 10 # 11 jkl 1 41 # 12 jkl 1 42
Base R替代实现
如果偏好base R,也可以用ave函数完成分组处理:
set.seed(123) result_df_base <- df result_df_base$time <- ave( result_df_base$time, result_df_base$name, FUN = function(t_vec, ig_vec) { has_zero <- any(ig_vec == 0) if (!has_zero) return(t_vec) selected_idx <- sample(which(ig_vec == 0), size = 1) t_vec[selected_idx] <- f(t_vec[selected_idx]) t_vec }, ig_vec = result_df_base$ignore )
内容的提问来源于stack exchange,提问作者Elis
相关产品推荐
相关产品推荐

