1

Supposing I have (very simple example):

df <- data.frame(factor_name = c("fac_Y", "fac_Y", "fac_Y", "fac_X", "fac_X", "fac_X", "fac_X", "fac_X", "fac_X"), factor_level = c("cherry", "apple", "peach", 2, 1, 3, 4, 6, 8), value = c(1, 3, 2, 6, 3, 4, 1, 5, 2)) 

I need to sort df based on factor_name and factor_level without relying on alphabetic/numerical order (because in the more complex case I'm working on, the sort order is completely unrelated to these things) such that:

(i) factor_name should be sorted as (fac_X, fac_Y)

(ii) within fac_X, the factor_level sort order should be (1, 2, 3, 4, 6, 8)

(iii) within fac_Y, the factor_level sort order should be ("apple", "peach", "cherry")

So I'll need to supply information by hand about the ordering I want (ie (i)-(iii) above) but I'm unsure how to do that.

I'd like my output therefore to be:

df_sorted <- data.frame(factor_name = c("fac_X", "fac_X", "fac_X", "fac_X", "fac_X", "fac_X", "fac_Y", "fac_Y", "fac_Y"), factor_level = c(1, 2, 3, 4, 6, 8, "apple", "peach", "cherry"), value = c(3, 6, 4, 1, 5, 2, 3, 2, 1)) 

Can anyone help please? Thank you.

1
  • It can also work: df[order(df$factor_name,df$factor_level,df$value),] Commented Aug 27, 2020 at 22:32

2 Answers 2

1

You can use match after defining the correct_order.

library(dplyr) correct_order <- c(1, 2, 3, 4, 6, 8, "apple", "peach", "cherry") df %>% arrange(factor_name, match(factor_level, correct_order)) # factor_name factor_level value #1 fac_X 1 3 #2 fac_X 2 6 #3 fac_X 3 4 #4 fac_X 4 1 #5 fac_X 6 5 #6 fac_X 8 2 #7 fac_Y apple 3 #8 fac_Y peach 2 #9 fac_Y cherry 1 

You could use the same in base R order :

df[with(df, order(factor_name, match(factor_level, correct_order))), ] 

Note that it is not important that correct_order should have values for "fac_X" first and then "fac_Y". It could be in any order provided values between themselves are maintained. So the above answers would give the same output with :

correct_order <- c("apple", "peach", "cherry", 1, 2, 3, 4, 6, 8) 
Sign up to request clarification or add additional context in comments.

1 Comment

I think this works (and still works in a more complex example that I've just tried). Thank you.
1

We could use factor with levels specified

library(dplyr) df %>% arrange(factor_name, factor(factor_level, levels = c(1, 2, 3, 4, 6, 8, 'apple', 'peach', 'cherry'))) # factor_name factor_level value #1 fac_X 1 3 #2 fac_X 2 6 #3 fac_X 3 4 #4 fac_X 4 1 #5 fac_X 6 5 #6 fac_X 8 2 #7 fac_Y apple 3 #8 fac_Y peach 2 #9 fac_Y cherry 1 

4 Comments

Doesn't this rely on being able to sort fac_Y in the same order as fac_X? In general I won't be able to make that assumption here. Each factor will have its own specific ordering.
@Alan Do you have completely different levels or do you have case where one of them follows in opposite direction of another
Completely different - will amend OP to show more clearly
Ah yes, ok, I can see the logic now. I’ll play with this some more tomorrow. Thank you.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.