J'ai un vecteur x que je voudrais trier en fonction de l'ordre des valeurs du vecteur y. Les deux vecteurs ne sont pas de même longueur.
x <- c(2, 2, 3, 4, 1, 4, 4, 3, 3)
y <- c(4, 2, 1, 3)
Le résultat attendu serait:
[1] 4 4 4 2 2 1 3 3 3
Voici une doublure ...
y[sort(order(y)[x])]
[modifier:] Cela se décompose comme suit:
order(y) #We want to sort by y, so order() gives us the sorting order
order(y)[x] #looks up the sorting order for each x
sort(order(y)[x]) #sorts by that order
y[sort(order(y)[x])] #converts orders back to numbers from orders
qu'en est-il de celui-ci
x[order(match(x,y))]
Vous pouvez convertir x
en un facteur ordonné:
x.factor <- factor(x, levels = y, ordered=TRUE)
sort(x)
sort(x.factor)
Évidemment, changer vos nombres en facteurs peut changer radicalement la façon dont le code en aval réagit à x
. Mais comme vous ne nous avez donné aucun contexte sur ce qui se passera ensuite, j'ai pensé que je proposerais cela comme une option.
Au cas où vous auriez besoin de commander sur "y", que ce soit des chiffres ou des caractères:
x[order(ordered(x, levels = y))]
4 4 4 2 2 1 3 3 3
Par étapes:
a <- ordered(x, levels = y) # Create ordered factor from "x" upon order in "y".
[1] 2 2 3 4 1 4 4 3 3
Levels: 4 < 2 < 1 < 3
b <- order(a) # Define "x" order that match to order in "y".
[1] 4 6 7 1 2 5 3 8 9
x[b] # Reorder "x" according to order in "y".
[1] 4 4 4 2 2 1 3 3 3
Que diriez-vous?:
rep(y,table(x)[as.character(y)])
(Ian est probablement encore mieux)
[Modifier: Il est clair que Ian a la bonne approche, mais je laisserai cela pour la postérité.]
Vous pouvez le faire sans boucles en indexant sur votre vecteur y. Ajoutez une valeur numérique incrémentielle à y et fusionnez-les:
y <- data.frame(index=1:length(y), x=y)
x <- data.frame(x=x)
x <- merge(x,y)
x <- x[order(x$index),"x"]
x
[1] 4 4 4 2 2 1 3 3 3
Vous pouvez également utiliser sqldf
et le faire par une fonction join
dans sql
aime ce qui suit:
library(sqldf)
x <- data.frame(x = c(2, 2, 3, 4, 1, 4, 4, 3, 3))
y <- data.frame(y = c(4, 2, 1, 3))
result <- sqldf("SELECT x.x FROM y JOIN x on y.y = x.x")
ordered_x <- result[[1]]
x <- c(2, 2, 3, 4, 1, 4, 4, 3, 3)
y <- c(4, 2, 1, 3)
for(i in y) { z <- c(z, rep(i, sum(x==i))) }
Le résultat en z: 4 4 4 2 2 1 3 3 3
Les étapes importantes:
for (i in y) - Boucles sur les éléments d'intérêt.
z <- c (z, ...) - Concatène tour à tour chaque sous-expression
rep (i, sum (x == i)) - Répète i (l'élément d'intérêt actuel) sum (x == i) fois (le nombre de fois où nous avons trouvé i en x).