如何在R中按条件打乱dataframe行,保证每3行分组的ClassNr不重复
实现思路
你当前的数据集里每个ClassNr刚好对应2条记录,要实现每3行分组内无重复ClassNr且全量保留原始行,可按以下逻辑实现:
- 按
ClassNr对数据分组,每组内先做随机打乱 - 给每个分组内的行分配组内序号(如2条记录的分组会生成序号1、2)
- 按组内序号排序,相同序号的3条记录刚好对应
ClassNr1、2、3各1条,自动满足分组去重要求,同组内还可以再做一次随机排序调整顺序
dplyr 实现代码
library(dplyr) # 示例数据构造 l <- c("Ana", "Maria", "Hanne", "Liam","Sarah","Ella") c <- c(1,1,2,3,3,2) df <- as.data.frame(cbind(l,c)) colnames(df) <- c("Name", "ClassNr") set.seed(55) df_result <- df %>% # 按ClassNr分组,组内随机打乱顺序 group_by(ClassNr) %>% sample_n(n()) %>% # 生成组内序号 mutate(group_id = row_number()) %>% ungroup() %>% # 按组内序号排序,同序号的为一个分组,同分组内可再随机打乱 group_by(group_id) %>% sample_n(n()) %>% ungroup() %>% # 去掉辅助列 select(-group_id)
运行后输出df_result即可得到符合要求的结果,示例运行结果:
Name ClassNr <chr> <chr> 1 Ana 1 2 Ella 2 3 Liam 3 4 Maria 1 5 Hanne 2 6 Sarah 3
基础R实现(无需加载第三方包)
set.seed(55) # 按ClassNr拆分数据,每个分组内打乱 split_df <- lapply(split(df, df$ClassNr), function(x) x[sample(nrow(x)), ]) # 给每个分组添加组内序号 split_df <- lapply(split_df, function(x) { x$group_id <- seq_len(nrow(x)) return(x) }) # 合并所有分组,按group_id排序后同组内打乱 df_combined <- do.call(rbind, split_df) df_result <- do.call(rbind, lapply(split(df_combined, df_combined$group_id), function(x) x[sample(nrow(x)), ])) # 去掉辅助列 df_result$group_id <- NULL # 重置行号 rownames(df_result) <- NULL
两种实现逻辑完全一致,可根据使用习惯选择。
内容的提问来源于stack exchange,提问作者ACLAN
相关产品推荐
相关产品推荐

