Related: Order Bars in ggplot2 bar graph. That question deals with re-ordering based on some numerical characteristic (e.g. greatest to least). I want to re-order based on an arbitrary reason not inherent to the data.
Also, how to change the order of a discrete x scale in ggplot?. This suggests ordering the factor levels, which I've done below, however I can't seem to combine the act of subsetting the data and keeping the factor order I want.
I have some product test data and I'd like to make a particular sample stand out in my bar charts. In my particular case, I want to push my sample of interest all the way to one side and color it differently (i.e. move my highlighted sample to the right out of alphabetical order and have it be green).
Here's an example of what I tried to do:
library(ggplot2)
test <- data.frame(names = c("A", "B", "C", "Last", "X", "Y", "Z"))
test$y <- 1:7
If I plot this as is, the factors, as we all know, will be arranged alphabetically.
ggplot(test, aes(x=Names, y=y)) + geom_bar()
I rearranged the levels like so:
test$names <- factor(test$names, levels = test$names[ c(1:3, 5:7, 4) ])
test$names
[1] A B C Last X Y Z
Levels: A B C X Y Z Last
So far so good. If we plot now, I get this, which gives me the order I want:
ggplot(test, aes(x=names, y=y)) + geom_bar()
But I'd like to color Last
green, so I tried this:
p <- ggplot(test[!test$names=="Last" ,], aes(x=names, y=y)) + geom_bar()
p <- p + geom_bar(aes(x=names, y=y), test[test$names=="Last" ,], fill="darkgreen")
p
If we look at my in situ subsets passed to ggplot:
test[!test$names=="Last" , ]$names
[1] A B C X Y Z
Levels: A B C X Y Z Last
test[!test$names=="Last" , ]$names
[1] A B C X Y Z
Levels: A B C X Y Z Last
So the level ordering is correct but ggplot's not using that to determine plot order.
I wondered if the issue was the plot data coming from the same data frame, so I split them wondering if ggplot would append the separate data to the end:
test2 <- test[test$names=="Last" , ]
test <- droplevels(test)
test2 <- droplevels(test2)
p <- ggplot(test, aes(x=names, y=y)) + geom_bar()
p <- p + geom_bar(aes(x=names, y=y), test2, fill="darkgreen")
p
The result is the same as the last graph, with Last
in the middle.
Lastly, I thought this might be done via scale_x_discrete
, so I tried this:
p <- ggplot(test[!test$names=="Last" ,], aes(x=names, y=y)) + geom_bar()
p <- p + geom_bar(aes(x=names, y=y), test[test$names=="Last" ,], fill="darkgreen")
p <- p + scale_x_discrete(breaks=test$names[c(1:3, 5:7, 4)])
p
I still get Last
in the middle.
Questions
- Why is ggplot reverting to alphabetical plot order instead of looking to the factor level ordering?
- Is there another (or better way) to single out a row for "special treatment" in a plot?