【问题标题】:Creating balanced groups based on three categorical variables基于三个分类变量创建平衡组
【发布时间】:2023-04-02 02:06:01
【问题描述】:

我正在为我正在指导的大学班级(约 180 名学生)创建一个小组作业。重要的是,这些群体在三个变量(学习领域 (FOS)、性别、部门:即新老学生)中尽可能地异质化。

FOS 有 5 个级别,性别有 2 个,部门有 2 个。鉴于该项目,我想创建大约 8-9 个组。换句话说,我想要大约 6 人的小组,在不同的学习领域、男性/女性以及新老学生之间取得“良好”的平衡。然后,我只需将名称与自动分配一起发布。

之前的导师都是手工完成的,但我尝试过使用 R 来查看是否有更系统的方法来执行此操作,但只是想出了重复(且笨拙)的排序。我预计 5 个 FOS 级别的大小会有所不同,因此我认识到这不是一个完美的解决方案。对人们的聪明解决方案感兴趣。这是一个可重复的样本:

dat <- data.frame(
  student = 1:180,
  gender = factor(sample(LETTERS[1:2], 180, replace = T, prob = c(.52,.48)),
                  labels=c("female","male")),
  division = factor(sample(LETTERS[1:2], 180, replace = T, prob = c(.6,.4)),
                  labels=c("lower","upper")),
  field = factor(sample(LETTERS[1:5], 180, replace = T, 
                   prob = c(.26,.21,.35,.07,.11)),
                   labels = c("humanities","natural science",
                              "social science","engineer","other")))

这是我一直在玩的,但它确实增加了分配的随机性,而不是可以看出的平衡:

library(dplyr)
dat$rand <- sample(1:180,180)

dat1 <- arrange(dat, field, division, gender, rand)
dat1$grp <- 1:(nrow(dat1)/6) #issue if not divisible 

这不会导致足够的平衡:

with(dat1, table(gender, grp)) #as a check
with(dat1, table(field, grp))
with(dat1, table(division, grp))

【问题讨论】:

    标签: r


    【解决方案1】:

    我知道这是一个老问题,但我今天遇到了类似的问题,这是我想出的解决方案。基本上,您随机分配组,然后对分类变量使用卡方检验或对连续变量使用方差分析来测试每个变量的组差异。您为不希望低于的 p 值设置阈值。代码将重新洗牌组,直到所有 p 值都高于该阈值。如果它经过 10,000 次迭代而没有达到分组解决方案,它将停止并建议您降低阈值。

    set.seed(905)
    #let's say you have a continuous variable you would also like to keep steady across groups
    dat$age <- sample(18:35, nrow(dat), replace = TRUE)
    
    dat$group <- rep_len(1:20, length.out = nrow(dat)) #if you wanted to make 20 groups
    dat$group <- as.factor(dat$group)
    a <- 0.1; b <- 0.1; c <- 0.1; d <- 0.1
    thresh <- 0.85 #Minimum threshold for p value
    z <- 1
    while (a < thresh | b < thresh |c < thresh |d < thresh) {
      dat <- transform(dat, group = sample(group)) #shuffles the groups
      x <- summary(aov(age ~ group, dat)) #ANOVA for continuous variables
      a <- x[[1]]['group','Pr(>F)']
      x <- summary(table(dat$group, dat$gender)) #Chi Sq for categorical variables
      b <- x[['p.value']]
      x <- summary(table(dat$group, dat$division))
      c <- x[['p.value']]
      x <- summary(table(dat$group, dat$field))
      d <- x[['p.value']]
      z <- z + 1
      if (z > 10000) {
        print('10,000 tries, no solution, reduce threshold')
        break
      }
    }
    

    【讨论】:

      【解决方案2】:

      每个变量组合都有足够的数据点,您应该能够做到这一点:

      dat <- groupdata2::fold(dat, k = 8, 
                              cat_col = c("gender", "division", "field")) 
      
      with(dat, table(gender, .folds))
      ##         .folds
      ## gender    1  2  3  4  5  6  7  8
      ## female   11 12 11 12 12 11 12 12
      ##   male   10 11 11 11 11 11 11 11
      
      with(dat, table(field, .folds))
      ##                 .folds
      ##   field           1 2 3 4 5 6 7 8
      ##   humanities      5 8 9 7 9 6 6 5
      ##   natural science 2 3 4 6 3 9 2 4
      ##   social science  9 7 6 8 5 6 9 6
      ##   engineer        3 3 2 1 3 0 2 4
      ##   other           2 2 1 1 3 1 4 4
      
      with(dat, table(division, .folds))
      ##         .folds
      ## division  1  2  3  4  5  6  7  8
      ##    lower 11 15 13 14 10 13 11 15
      ##    upper 10  8  9  9 13  9 12  8
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-12-02
        • 1970-01-01
        • 1970-01-01
        • 2019-06-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多