Ordina le righe del frame di dati in base al vettore con un ordine specifico

Esiste un modo più semplice per garantire che le righe di un frame di dati siano ordinate in base a un vettore “target” come quello che ho implementato nel breve esempio di seguito?

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") 

Questo in qualche modo sembra essere un po ‘troppo “complicato” per portare a termine il lavoro:

 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 

Prova la 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 

Funzionerà finché il target contiene esattamente gli stessi elementi di df$name e non contiene valori duplicati.

Da ?match :

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

Pertanto, la match trova i numeri di riga che corrispondono agli elementi di destinazione, quindi restituiamo df in tale ordine.

Questo metodo è un po ‘diverso, mi ha fornito un po’ più di flessibilità rispetto alla risposta precedente. Rendendolo in un fattore ordinato, è ansible utilizzarlo piacevolmente per arrange e così via. Ho usato reorder.factor dal pacchetto 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) 

Quindi, utilizza il fatto che ora è ordinato:

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

Se vuoi tornare all'originale (in ordine alfabetico), usa as.character() per riportarlo allo stato originale.

Preferisco usare ***_join in dplyr ogni volta che ho bisogno di abbinare i dati. Un ansible tentativo per questo

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

Si noti che l’input per ***_join richiede tbls o data.frame