You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何拆分R数据框:每个块含因子列所有唯一值且最大化分块数

问题与解决方案

问题背景

我们通过以下R代码生成了数据框df:

library(dplyr)
library(stringr)

letters_comb <- expand.grid(LETTERS, LETTERS) %>% 
  mutate(Combination = paste0(Var1, Var2)) %>% 
  select(Combination) %>% 
  sample_n(100)

set.seed(123) 
n_times <- round(runif(100, 80, 120)) 

df <- data.frame(fac_var = as.factor(rep(letters_comb$Combination, times = n_times)))

需要将df拆分成尽可能多的子块,满足两个核心要求:

  • 每个子块都包含fac_var列的所有唯一取值
  • 原数据的每一行都必须被分配到某个子块中

优先采用dplyr或tidyverse生态下的实现方案。


实现方案

核心思路

要拆分出最多的有效块,本质是找到所有fac_var分组中行数最少的那个组——这个组的行数就是能拆分的最大块数。我们给每个fac_var组内的行按顺序编号,然后将编号相同的行归为一个块,这样每个块都会覆盖所有fac_var的取值。

代码实现

library(dplyr)

# 第一步:为每个fac_var分组内的行分配组内序号
df_with_block <- df %>%
  group_by(fac_var) %>%
  mutate(block_id = row_number()) %>%
  ungroup()

# 第二步:按序号拆分数据,得到子块列表
df_blocks <- df_with_block %>%
  group_split(block_id, .keep = FALSE)

代码说明

  • group_by(fac_var) %>% mutate(block_id = row_number()):对每个fac_var的分组,给组内每行从1开始递增编号。比如某个fac_var有90行,它的block_id就是1到90;另一个只有81行,编号就是1到81。
  • group_split(block_id, .keep = FALSE):根据block_id拆分数据,每个编号对应一个子块。最终子块的数量等于所有fac_var分组中最小的行数(因为超过该行数的编号,会有部分fac_var分组没有对应行,无法形成有效块)。.keep = FALSE用于移除辅助列block_id,让子块只保留原数据的列。

结果验证

可以通过以下代码确认所有子块都满足要求:

# 验证第一个子块是否包含所有fac_var唯一值
length(unique(df_blocks[[1]]$fac_var)) == length(unique(df$fac_var))

# 批量验证所有子块
all(sapply(df_blocks, function(block) {
  length(unique(block$fac_var)) == length(unique(df$fac_var))
}))

内容的提问来源于stack exchange,提问作者nicholas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 11:42:47