3

I think this should be really simple, but I cannot find a way to do this.

I want to reorder a dataframe based on a factor. All the answers I can find so far provide logical sorting, but this is arbitrary, and a mixture of numbers and letters. Maybe it's a problem because it is a factor not a vector? But none of the answers for vectors seem to work either.

Any suggestions would be really appreciated!

Example data (note; this data is just for this question, in my real code the dataframe is the output of some other calculations and so I can't just alter the names to something sensible right at the start)

DATA<- data.frame(This=c("120", "60", "90", "OG"), That=c(453, 679,12,252))

DATA

  This That
1  120  453
2   60  679
3   90   12
4   OG  252

I want to sort it in the order 60 - 90 - 120 - OG, i.e.

  This That
1  60   679
2  90   12
3  120  453
4  OG   252

Edit: This is not a duplicate question. As explained above, and in the comment below, the sorting is arbitrary. Lexicographical sorting assumes the row names are inter-related, that isn't the case here. I could have labelled the rows ("unicorn", "18.1", "TREES", "234234235") and wanted them in the order ("234234235", "unicorn", "TREES", "18.1")

EcologyTom
  • 2,344
  • 2
  • 27
  • 38
  • Does the order of characters matter? Or you want to sort them alphabetically? i.e. if there are `OG` and `AB`, do you want `AB, OG`? – Psidom Jun 30 '16 at 13:58
  • Hi @user2100721, thanks, but the other answer wasn't what I was looking for. The ordering was arbitrary not lexicographical. In this case it was complicated because I couldn't change the labels. – EcologyTom Jun 30 '16 at 14:22

2 Answers2

7

You can adjust the order with the factor variable as follows:

DATA$This <- factor(DATA$This, levels=c("60", "90", "120", "OG"))

Note that this doesn't change the label values:

DATA
  This That
1  120  453
2   60  679
3   90   12
4   OG  252

But it changes the underlying integers that are mapped to those labels, so that you can order the data as you wanted:

DATA[order(DATA$This),]
  This That
2   60  679
3   90   12
1  120  453
4   OG  252
lmo
  • 37,904
  • 9
  • 56
  • 69
  • Thanks @lmo, this was exactly the sort of thing I was looking for. I didn't realise it would be a two-step process, I was getting discouraged after the first stage hadn't altered it as I expected. – EcologyTom Jun 30 '16 at 14:16
0

Here is an option for sorting mixed type column, where we convert the column to numeric firstly and sort which makes sure numeric values are always in front of character values and it is by its natural order and then sort by the character type which makes sure the character values are in alphabetical order, assuming This column is of class character already:

library(dplyr)
DATA %>% arrange(as.numeric(This), as.character(This))
#   This That
# 1   60  679
# 2   90   12
# 3  120  453
# 4   OG  252
Psidom
  • 209,562
  • 33
  • 339
  • 356
  • Thanks @Psidom. At the moment I am still a bit uncertain around dplyr, which is why I've chosen the other answer. But I can see it will be really helpful in a different context. – EcologyTom Jun 30 '16 at 14:20