warner_sc
warner_sc

Reputation: 848

R Sort/order specific named columns containing numbers and letters (data.frame)

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

Answers (3)

tyluRp
tyluRp

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

Imran Ali
Imran Ali

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

Jordan Hackett
Jordan Hackett

Reputation: 749

db[,order(as.numeric(gsub("X","",names(db))),na.last=F)]

Upvotes: 1

Related Questions