Singling out a particular sample for an aesthetic using ggplot
ggplot2, plot, r
Solution
Two other ways to get what you want:
Use `scale_x_discrete(drop=FALSE)` This is necessary because the two sets of data you are using don't have the same x values present despite the `levels()` of the factors being the same.
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(drop = FALSE)
p
Color (well, fill) with a derived aesthetic and map that
ggplot(test, aes(x=names, y=y, fill=(names=="Last"))) +
geom_bar() +
scale_fill_manual(breaks = c(FALSE,TRUE),
values = c("black", "darkgreen"),
guide = "none")
Both give a graph that looks just like the one in your answer.
Problem
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?