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
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.
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.
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