21

I have the following data.frame in R:

> daily
        DoW         Duration
1    Friday 14.0000000000000
2    Monday 21.0000000000000
3  Saturday 12.0000000000000
4  Thursday 28.0000000000000
5   Tuesday 12.0000000000000
6 Wednesday 91.0000000000000
7    Sunday 20.0000000000000

I'd like to change the order of the factor levels so that the weeks are in (US) day-of-week order.

It looks like I can do this in a slow, puzzling way with relevel(). But this only takes 1 numeric argument and moves it to the top. So, relevel(daily$DoW, 7), moves Sunday to the top, but the rest remain unordered (which means I need to relevel it in reverse order).

Doable, but there must be a better way, right?

(Time series solution also acceptable.)

Matthew Lundberg
  • 42,009
  • 6
  • 90
  • 112
Mittenchops
  • 18,633
  • 33
  • 128
  • 246

2 Answers2

25

You need to specify the levels in factor and then use order with indexing:

daily$DoW <- factor(daily$DoW, levels= c("Sunday", "Monday", 
    "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"))

daily[order(daily$DoW), ]
Tyler Rinker
  • 108,132
  • 65
  • 322
  • 519
  • 4
    I checked to see if R has a days of the week constant built in like it does months and it doesn't appear to. Figured it would. – Tyler Rinker Apr 25 '12 at 05:10
  • 1
    This almost worked---I implemented the final line to be an assignment, `daily <- daily[order(daily$DoW),]` But I notice that when I make a histogram out of it with `ggplot(daily, aes(x=DoW, y=Duration)) + geom_histogram()`, the factors are listed in the correct order on the x axis, but not on the y axis---that is, the y values still correspond to the old positions of the x values. ie, Sunday is 14, instead of 20. – Mittenchops Apr 25 '12 at 05:20
  • Yeah, maybe my assignment was incorrect, but when I just type `daily` now, the index is still listed as `7,2,5,6,4,1,3`, even though the DoW column now begins with Sunday. – Mittenchops Apr 25 '12 at 05:22
7

Instead of a factor, what you want is an Ordered.Factor.

This line of R code converts your DoW variable to an "Ordered Factor":

daily$DoW <- ordered(daily$DoW, levels=c("Monday", "Tuesday", "Wednesday", "Thursday", 
"Friday", "Saturday", "Sunday"))

Now when you use table, plot or any other functions on Dow it will be the order you specified above.

onlyphantom
  • 8,606
  • 4
  • 44
  • 58