I need to re-order some of the rows of my dataframe. I have a list of observations (names) that I need to be at the top. It's a string variable, and just a selection of them need to be at the top--the rest can be in their existing order.
Example dataset:
df <- data.frame(name = c("Alan", "Betty", "Clyde", "Diane", "Eric",
"Francine", "George", "Harriett"),
height = c(60, 68, 70, 66, 68, 70, 63, 64))
I can't order from lowest to highest or vice versa, and there's no part of the string that is unique to these observations. I only care about the order for some of the observations, not all. And for the ones I do care about, they have to be in a specific order - it's not enough for them to be in the top in the wrong order.
Long version:
df$order[df$name == "Betty"] <- 1
df$order[df$name == "Diane"] <- 2
df$order[df$name == "Alan"] <- 3
df$order[df$name == "Clyde"] <- 4
df <- arrange(df, order)
df$order <- NULL
The above code works, but there are too many observations for me to feel comfortable copy/pasting a bunch of lines.
I tried doing the above code as a for loop (looping either over a list of the names or 1:4), but I couldn't get it to work. Similar for ifelse(). lapply or sapply might work, but frankly I don't understand them.
I'm hoping someone can show me how to loop/automate my solution so it's doable for more observations or show me a different way altogether.
Try match in arrange
> df %>% arrange(match(name, c("Betty", "Diane", "Alan", "Clyde")))
name height
1 Betty 68
2 Diane 66
3 Alan 60
4 Clyde 70
5 Eric 68
6 Francine 70
7 George 63
8 Harriett 64
If you have the order of the first few values in a vector nm you can relevel them so they are first:
Edit
Rather than overwrite name you can pass it directly to arrange. This will preserve name as a character vector in the output:
library(forcats)
library(dplyr)
nm <- c("Betty", "Diane", "Alan", "Clyde")
df |>
arrange(fct_relevel(fct_inorder(name), !!nm))
# name height
# 1 Betty 68
# 2 Diane 66
# 3 Alan 60
# 4 Clyde 70
# 5 Eric 68
# 6 Francine 70
# 7 George 63
# 8 Harriett 64
fct_inorder() will ensure the original order is preserved, while fct_relevel() will move those names to the top. Without fct_inorder() the remaining names will be in alphabetical order (which is how you have them arranged in your example anyway, but just FYI).
Original Answer
library(forcats)
library(dplyr)
nm <- c("Betty", "Diane", "Alan", "Clyde")
df |>
mutate(name = fct_relevel(fct_inorder(name), !!nm)) |>
arrange(name)
Note: name will be a factor variable not a character variable. To return them to character, you can pipe to mutate(name = as.character(name)).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With