Reputation: 848
I would like to know how can I order or sort named columns in R containing letters and numbers using base R
This is my sample data:
Names <- c("Name1","Name2")
X2 <- c("10","1")
X1 <- c("7","5")
X10 <- c("8","3")
db <- data.frame(Names, X2, X1, X10)
Output/view(data.frame):
Names X2 X1 X10
Name1 10 7 5
Name2 1 5 7
Let's say I want to sort or order the columns containing the "X" character at the beginning but using its numeric "value"? expecting this output:
Names X1 X2 X10
Name1 7 10 5
Name2 5 1 7
This is my current solution, I hope this helps anyone :)
db_names <- colnames(db[,2:ncol(db)])
db_names <- db_names[order(nchar(db_names), db_names)]
cbind(Names = db[,1],db[,db_names])
Output:
Names X1 X2 X10
Name1 7 10 5
Name2 5 1 7
The number of columns in my real data frame is greater, a dynamic solution will be appreciated.
Thank you for your attention and sorry for bad english!
Upvotes: 0
Views: 3138
Reputation: 4768
With dplyr
:
library(dplyr)
# With the pipe
db %>%
select(Names, num_range("X", range = 1:10))
# Without the pipe
select(db, Names, num_range("X", range = 1:10))
Both return:
Names X1 X2 X10
1 Name1 7 10 8
2 Name2 5 1 3
This assumes that all columns have the prefix "X". Adjust the range accordingly.
One base R solution might be:
db[order(as.numeric(substring(colnames(db), 2)), na.last = FALSE)]
This returns:
Names X1 X2 X10
1 Name1 7 10 8
2 Name2 5 1 3
Which is similar to the other answer but uses substring
instead of gsub
. This also produces the following warning message:
Warning message: In order(as.numeric(substring(colnames(db), 2)), na.last = FALSE) : NAs introduced by coercion
This is because we can't turn Names
into a numeric value:
as.numeric(substring(colnames(db), 2))
Warning message: NAs introduced by coercion
[1] NA 2 1 10
Upvotes: 2
Reputation: 2279
Update: I have extended the sample data to make sure the alpha numeric sort works
Names <- c("Name1","Name2")
X2 <- c("10","1")
X1 <- c("7","5")
X10 <- c("8","5")
X11 <- c("6","5")
using mixedorder
from the package gtools
db <- db[mixedorder(colnames(db))]
Output:
Names X1 X2 X10 X11
Name1 7 10 8 6
Name2 5 1 5 5
Upvotes: 0