Dans R, j'ai l'exemple de tableau de données suivant:
# Output (as desired): Group InternalOrder RandomGroupID 1: d5 1 1 2: d5 2 1 3: d5 3 1 4: d2 1 2 5: d3 1 3 6: d3 2 3 7: d1 1 4 8: d1 2 4 9: d1 3 4 10: d1 4 4 11: d4 1 5 12: d7 1 6 13: d7 2 6 14: d7 3 6 15: d7 4 6 16: d7 5 6 17: d6 1 7
Ce qui ressemble à ceci:
groupsizes <- x[, .N, by = Group]$N # Get number of elements (= rows) for each group set.seed(10) x[, RandomGroupID := rep(sample(c(1:length(unique(x$Group))), replace = F), groupsizes)] # Make new column with random ID for each group setorder(x, RandomGroupID, InternalOrder) # Re-order data by random group ID and internal order
Mon objectif est de randomiser l'ordre des groupes dans la table de données x tout en préservant l'ordre interne de chaque groupe.
J'ai déjà élaboré une solution
# Input: # Group InternalOrder 1: d1 1 2: d1 2 3: d1 3 4: d1 4 5: d2 1 6: d3 1 7: d3 2 8: d4 1 9: d5 1 10: d5 2 11: d5 3 12: d6 1 13: d7 1 14: d7 2 15: d7 3 16: d7 4 17: d7 5
qui donne le résultat souhaité:
library(data.table) x <- data.table(Group = c("d1", "d1", "d1", "d1", "d2", "d3", "d3", "d4", "d5", "d5", "d5", "d6", "d7", "d7", "d7", "d7", "d7")) x[, InternalOrder := seq(.N), by = Group]
Puisque j'essaie d'améliorer mes compétences en matière de table de données, j'aimerais savoir s'il existe une solution plus agréable et plus idiomatique qui ne nécessite pas l'étape intermédiaire de créer le vecteur groupements
mais attribue une nouvelle colonne en utilisant la syntaxe typique de la table de données en utilisant l'argument by
en combinaison avec .GRP
ou .I ou similaire.
J'ai pensé à quelque chose comme x [ RandomGroupIDAlternative: = rep (sample (c (1: length (unique (x $ Group))), replace = F), .GRP), by = Group] code > qui, de toute évidence, ne donne pas le résultat souhaité.
J'ai hâte de recevoir vos commentaires et de voir des solutions alternatives à ce problème.
3 Réponses :
Voici une possibilité:
Group InternalOrder RandomGroupID 1: d1 1 4 2: d1 2 4 3: d1 3 4 4: d1 4 4 5: d2 1 7 6: d3 1 6 7: d3 2 6 8: d4 1 1 9: d5 1 2 10: d5 2 2 11: d5 3 2 12: d6 1 5 13: d7 1 3 14: d7 2 3 15: d7 3 3 16: d7 4 3 17: d7 5 3
Sortie:
x[, RandomGroupID := runif(1), by = Group ] x[order(RandomGroupID), RandomGroupID := as.numeric(.GRP), by = Group]
Cela peut être fait de manière idiomatique en rejoignant une liste aléatoire de groupes.
x[sample(unique(Group)), on = "Group"][, RandomGroupID := .GRP, by = Group][]
Excellente solution, merci. J'ai complètement oublié le paramètre "on", qui est en effet assez puissant.
Vous pouvez également le faire en utilisant split
et rbindlist
:
x_new <- rbindlist(sample(split(x, by='Group'))) Group InternalOrder 1: d4 1 2: d1 1 3: d1 2 4: d1 3 5: d1 4 6: d5 1 7: d5 2 8: d5 3 9: d6 1 10: d7 1 11: d7 2 12: d7 3 13: d7 4 14: d7 5 15: d3 1 16: d3 2 17: d2 1