Quero designar alunos da coorte de 2024 (n=105, mulheres=61, homens=44) em grupos para 2025. A distribuição que espero alcançar (em ordem de importância):
- não mais do que dois alunos de um grupo de 2024 podem ser transferidos para o mesmo grupo de 2025
- Os grupos de 2025 devem ser o mais equilibrados possível em termos de gênero, algo como 7 ou 8 mulheres e 5 ou 6 homens por grupo
- Os tamanhos dos grupos de 2025 devem ser o mais uniformes possível, idealmente 7 x 13 e 1 x 14
- sempre que possível, a distribuição deve ser aleatória
Dado que uma solução pode não ser possível se os critérios 1 a 3 forem rigorosamente respeitados, há alguma flexibilidade em relação ao tamanho do grupo e à aleatoriedade.
Os tamanhos e o equilíbrio de gênero para os grupos de 2024 são relativamente desiguais:
table(df[, c("Gender", "g2024")])
# g2024
# Gender 1 2 3 4 5 6 7 8
# Female 7 7 7 7 9 7 9 8
# Male 4 4 8 6 5 7 4 6
table(df[, "g2024"])
# g2024
# 1 2 3 4 5 6 7 8
# 11 11 15 13 14 14 13 14
Usando valores pré-determinados, um exemplo rudimentar do que estou tentando alcançar:
# Create random vector with group ids for females per group, assign to g2025
set.seed(42)
grp_fem <- as.character(rep(1:8, sample(c(rep(7, 3), rep(8, 5)), 8)))
df$g2025 <- unlist(lapply(1:nrow(df), function(i) {
if (df$Gender[i] == "Female") {
x <- sample(grp_fem, 1)
grp_fem <<- grp_fem[-match(x, grp_fem)]
return(x)
} else {
return(NA)
}
}))
# Get males per group, change one group length so y sums to male count
x <- as.integer(table(df$g2025))
y <- 13 - x
z <- sample(which(y == 5), 1)
y[z] <- 6
# Create vector with group ids for males per group, assign to g2025
grp_mal <- as.character(rep(1:8, rep(y)))
df$g2025 <- unlist(lapply(1:nrow(df), function(i) {
if (df$Gender[i] == "Male") {
x <- sample(grp_mal, 1)
grp_mal <<- grp_mal[-match(x, grp_mal)]
return(x)
} else {
return(df$g2025[i])
}
}))
# Gender distribution per group
table(df[, c("Gender", "g2025")])
# g2025
# Gender 1 2 3 4 5 6 7 8
# Female 7 8 8 8 7 8 7 8
# Male 6 5 5 5 6 6 6 5
# Number of students carried from g2024 to g2025 groups
table(df[, c("g2024", "g2025")])
# g2025
# g2024 1 2 3 4 5 6 7 8
# 1 0 2 1 2 1 2 3 0
# 2 1 3 2 2 0 0 1 2
# 3 2 2 1 2 3 2 1 2
# 4 1 1 2 1 2 2 2 2
# 5 2 1 4 0 2 3 1 1
# 6 5 3 1 2 0 0 2 1
# 7 1 1 0 1 2 2 1 5
# 8 1 0 2 3 3 3 2 0
Os tamanhos de grupo predeterminados e os valores de distribuição de gênero obviamente não são ideais e não levam em conta quantos alunos de um determinado grupo de 2024 acabarão no mesmo grupo de 2025.
Tentei usar uma matriz com uma distribuição quase aleatória de alocação de grupo para grupo:
m <- structure(c(1, 1, 2, 1, 2, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 1, 2,
1, 2, 2, 2, 1, 1, 2, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 1, 2, 2,
1, 2, 1, 2, 2, 2, 1, 1, 2, 2, 1, 2, 2, 2, 1, 2, 2, 1, 2, 2, 2,
1, 2, 2, 1, 2), dim = c(8L, 8L))
rowSums(m)
# [1] 11 11 15 13 14 14 13 14
colSums(m)
# [1] 13 13 13 13 13 13 13 14
mas isso também requeria colSums()
valores predefinidos e alguma manipulação manual. Suspeito que o lpSolve
pacote pode ser capaz de lidar com algo assim, mas não consegui entender como usá-lo.
Dados:
df <- structure(list(Student = c("1", "2", "3", "4", "5", "6", "7",
"8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18",
"19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
"30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40",
"41", "42", "43", "44", "45", "46", "47", "48", "49", "50", "51",
"52", "53", "54", "55", "56", "57", "58", "59", "60", "61", "62",
"63", "64", "65", "66", "67", "68", "69", "70", "71", "72", "73",
"74", "75", "76", "77", "78", "79", "80", "81", "82", "83", "84",
"85", "86", "87", "88", "89", "90", "91", "92", "93", "94", "95",
"96", "97", "98", "99", "100", "101", "102", "103", "104", "105"
), Gender = c("Female", "Male", "Male", "Male", "Female", "Female",
"Male", "Female", "Female", "Female", "Male", "Male", "Male",
"Female", "Male", "Female", "Male", "Female", "Female", "Female",
"Male", "Male", "Female", "Female", "Female", "Male", "Male",
"Male", "Female", "Female", "Male", "Female", "Female", "Female",
"Male", "Female", "Female", "Female", "Female", "Male", "Male",
"Female", "Female", "Female", "Female", "Male", "Female", "Male",
"Female", "Female", "Female", "Female", "Male", "Female", "Male",
"Female", "Male", "Male", "Male", "Female", "Female", "Female",
"Female", "Female", "Female", "Male", "Female", "Female", "Male",
"Male", "Female", "Female", "Male", "Female", "Male", "Female",
"Female", "Male", "Female", "Female", "Female", "Male", "Female",
"Male", "Female", "Female", "Male", "Female", "Male", "Male",
"Male", "Male", "Male", "Female", "Male", "Female", "Female",
"Male", "Female", "Male", "Female", "Female", "Male", "Male",
"Female"), g2024 = c("4", "3", "3", "8", "2", "8", "4", "5",
"8", "7", "2", "4", "4", "6", "6", "5", "1", "3", "7", "2", "6",
"8", "2", "8", "1", "5", "8", "3", "3", "1", "5", "5", "1", "3",
"8", "6", "1", "7", "5", "5", "1", "7", "4", "7", "5", "4", "8",
"6", "3", "1", "7", "8", "7", "7", "2", "4", "8", "3", "7", "1",
"6", "3", "6", "8", "2", "3", "3", "5", "7", "2", "2", "2", "8",
"6", "1", "1", "4", "1", "6", "8", "2", "6", "5", "2", "5", "3",
"3", "7", "3", "4", "3", "4", "7", "4", "6", "8", "4", "6", "6",
"6", "5", "4", "5", "5", "7"), g2025 = c(NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA)), row.names = c(NA, -105L), class = c("tbl_df",
"tbl", "data.frame"))