81

With arrange function in dplyr, we can arrange row in ascending or descending order. Wonder how to arrange rows in custom order. Please see MWE.

Reg <- rep(LETTERS[1:3], each = 2)
Res <- rep(c("Urban", "Rural"), times = 3)
set.seed(12345)
Pop <- rpois(n = 6, lambda = 500000)
df <- data.frame(Reg, Res, Pop)

df
   Reg   Res    Pop
1    A Urban 500414
2    A Rural 500501
3    B Urban 499922
4    B Rural 500016
5    C Urban 501638
6    C Rural 499274

df %>%
  arrange()

Desired Output

   Reg   Res    Pop
5    C Urban 501638
6    C Rural 499274
1    A Urban 500414
2    A Rural 500501
3    B Urban 499922
4    B Rural 500016
Hobo
  • 7,536
  • 5
  • 40
  • 50
MYaseen208
  • 22,666
  • 37
  • 165
  • 309

3 Answers3

137

We can use factor to change the order in a custom way

df %>%
    arrange(factor(Reg, levels = LETTERS[c(3, 1, 2)]), desc(Res), desc(Pop))
#  Reg   Res    Pop
#1   C Urban 501638
#2   C Rural 499274
#3   A Urban 500414
#4   A Rural 500501
#5   B Urban 499922
#6   B Rural 500016

Or with match to get the index and arrange on it

df %>%
    arrange(match(Reg, c("C", "A", "B")), desc(Res), desc(Pop))

If we have multiple columns to arrange in descending order

df %>%
     arrange_at(2:3, desc) %>%
     arrange(match(Reg, c("C", "A", "B")))
akrun
  • 874,273
  • 37
  • 540
  • 662
  • 2
    Thanks @akrun for nice solution. Is there any was to use `desc` for all remaining variables without typing their names? Thanks – MYaseen208 Sep 09 '17 at 10:28
  • @MYaseen208 Thanks for the note. I added another option. Hope it helps – akrun Sep 09 '17 at 10:49
  • Yes, to echo @MYaseen208, is there any way to pick a couple to be at the bottom, but have the rest at the top? For instance, if i have 20 vars, and i want 2 of them at the bottom, this method seems to only work if I name the first 18 in the match. Regardless of the desc() and !match I use, I always get the unnamed values at the bottom. – jzadra Feb 22 '18 at 21:11
  • 1
    Just a side note for future viewers: first solution can be shortened to `df %>% arrange(factor(Reg, levels = LETTERS[c(3,1,2)]))` –  Jan 13 '19 at 16:31
  • 2
    It seems that if the sorting variable is already defined as an ordered factor outside of `arrange`, the behaviour of `arrange` is still to order alphabetically... How come? – Fons MA Apr 07 '19 at 23:50
  • @FonsMA Not clear about the comment. Can you post a small example – akrun Apr 08 '19 at 03:18
14

I used the slice() function:

   df %<>%
   slice(5,6,1:4)
Peter Dorey
  • 141
  • 1
  • 2
4

using data.table

df1[order(factor(Reg,levels = LETTERS[c(3,1,2)]))]

Here df1 is data.table

dondapati
  • 829
  • 6
  • 18