web-dev-qa-db-fra.com

Ordonner les lignes du cadre de données en fonction du vecteur avec un ordre spécifique

Existe-t-il un moyen plus simple de s’assurer que les lignes d’un bloc de données sont ordonnées en fonction d’un vecteur "cible" identique à celui que j’ai implémenté dans le court exemple ci-dessous?

df <- data.frame(name = letters[1:4], value = c(rep(TRUE, 2), rep(FALSE, 2)))

df
#   name value
# 1    a  TRUE
# 2    b  TRUE
# 3    c FALSE
# 4    d FALSE

target <- c("b", "c", "a", "d")

Cela semble en quelque sorte un peu trop "compliqué" pour faire le travail:

idx <- sapply(target, function(x) {
    which(df$name == x)
})
df <- df[idx,]
rownames(df) <- NULL

df 
#   name value
# 1    b  TRUE
# 2    c FALSE
# 3    a  TRUE
# 4    d FALSE
135
Rappster

Essayez match:

df <- data.frame(name=letters[1:4], value=c(rep(TRUE, 2), rep(FALSE, 2)))
target <- c("b", "c", "a", "d")
df[match(target, df$name),]

  name value
2    b  TRUE
3    c FALSE
1    a  TRUE
4    d FALSE

Cela fonctionnera tant que votre target contiendra exactement les mêmes éléments que df$name, et qu’aucun ne contiendra de valeurs en double.

De ?match:

match returns a vector of the positions of (first) matches of its first argument 
in its second.

Par conséquent, match recherche les numéros de ligne correspondant aux éléments de target, puis nous renvoyons df dans cet ordre.

201
Edward

Cette méthode est un peu différente, elle m'a fourni un peu plus de flexibilité que la réponse précédente. En le transformant en facteur ordonné, vous pouvez l'utiliser correctement dans arrange et ainsi de suite. J'ai utilisé reorder.factor du package gdata.

df <- data.frame(name=letters[1:4], value=c(rep(TRUE, 2), rep(FALSE, 2)))
target <- c("b", "c", "a", "d")

require(gdata)
df$name <- reorder.factor(df$name, new.order=target)

Ensuite, utilisez le fait qu'il est maintenant commandé:

require(dplyr)
df %>%
  arrange(name)
    name value
1    b  TRUE
2    c FALSE
3    a  TRUE
4    d FALSE

Si vous souhaitez revenir à l'ordre d'origine (alphabétique), utilisez simplement as.character() pour le ramener à son état d'origine.

18
MattV

Je préfère utiliser ***_join dans dplyr chaque fois que je dois faire correspondre des données. Un essai possible pour cela

left_join(data.frame(name=target),df,by="name")

Notez que l'entrée pour ***_join nécessite des tables ou data.frame

17
Lerong