Testing/Training 数据集按两个交叉变量分层

Testing/Training data sets stratified on two crossed variables

我有一个关于两个分类变量交叉的数据集,每个组合只有 1 个代表:

> examp <- data.frame(group=rep(LETTERS[1:4], each=6), class=rep(LETTERS[16:21], times=4))
> table(examp$group, examp$class)

    P Q R S T U
  A 1 1 1 1 1 1
  B 1 1 1 1 1 1
  C 1 1 1 1 1 1
  D 1 1 1 1 1 1

我需要创建一个 testing/training 数据集(50/50 分割)来平衡 组和 class。

我知道我可以使用 caret 包中的 createDataPartition 来平衡两个因素之一,但这在另一个因素中留下了不平衡:

> library(caret)
> examp$valid <- "test"
> examp$valid[createDataPartition(examp$group, p=0.5, list=FALSE)] <- "train"
> table(examp$group, examp$valid)

    test train
  A    3     3
  B    3     3
  C    3     3
  D    3     3
> table(examp$class, examp$valid)

    test train
  P    1     3
  Q    2     2
  R    2     2
  S    2     2
  T    2     2
  U    3     1
> 
> 
> examp$valid <- "test"
> examp$valid[createDataPartition(examp$class, p=0.5, list=FALSE)] <- "train"
> table(examp$group, examp$valid)

    test train
  A    3     3
  B    3     3
  C    5     1
  D    1     5
> table(examp$class, examp$valid)

    test train
  P    2     2
  Q    2     2
  R    2     2
  S    2     2
  T    2     2
  U    2     2

如何创建一个在两个因素上都平衡的分区? 如果每个 group/class 组合有多个代表,我会按 interaction(group,class) 进行分层,但在这种情况下我不能,因为每个组合中只有一个观察值。

我提出这个算法

  1. 随机排序唯一的 group 个值(例如,DBAC
  2. 迭代随机排序的 group 值的相邻对(例如,首先 DB,然后 AC):
    1. 随机选择 class 值的一半
    2. 将第一个 groupclass 的选定一半的行分配给 TRAIN
    3. class的选定一半中第二个group不是的行分配给TEST