Change the order of the discrete scale x

I am making a biased histogram using ggplot with a discrete x scale, the x axis is now ordered in alphabetical order, but I need to rearrange it so that it is ordered by the value of the y axis (i.e. the highest bar will be located on the left).

I tried ordering or sorting, but will result in sorting the x axis, but not the bars, respectively.

What did I do wrong?

+94
r ggplot2
Jul 15 '10 at 8:11
source share
5 answers

Try manually setting the factor levels on the x axis. For example:

library(ggplot2) # Automatic levels ggplot(mtcars, aes(factor(cyl))) + geom_bar() 

ggplot of the cars dataset with factor levels automatically determined

 # Manual levels cyl_table <- table(mtcars$cyl) cyl_levels <- names(cyl_table)[order(cyl_table)] mtcars$cyl2 <- factor(mtcars$cyl, levels = cyl_levels) # Just to be clear, the above line is no different than: # mtcars$cyl2 <- factor(mtcars$cyl, levels = c("6","4","8")) # You can manually set the levels in whatever order you please. ggplot(mtcars, aes(cyl2)) + geom_bar() 

ggplot of the cars dataset with factor levels reordered manually

As James noted in his answer, reorder is an idiomatic way to redistribute factor levels.

 mtcars$cyl3 <- with(mtcars, reorder(cyl, cyl, function(x) -length(x))) ggplot(mtcars, aes(cyl3)) + geom_bar() 

ggplot of the cars dataset with factor levels reordered using the reorder function

+86
Jul 15 '10 at 12:23
source share

The best way for me is to use a vector with categories so that I need as the limits parameter for scale_x_discrete . I think this is a pretty simple and easy solution.

 ggplot(mtcars, aes(factor(cyl))) + geom_bar() + scale_x_discrete(limits=c(8,4,6)) 

enter image description here

+150
Sep 18 '11 at 10:15
source share

You can use reorder :

 qplot(reorder(factor(cyl),factor(cyl),length),data=mtcars,geom="bar") 

Edit:

To have the highest bar on the left, you should use a little kludge:

 qplot(reorder(factor(cyl),factor(cyl),function(x) length(x)*-1), data=mtcars,geom="bar") 

I expect this to also have negative heights, but it is not, so it works!

+28
Jul 15 2018-10-15T00:
source share

Hadley is developing a package called forcats . This package makes the task much easier. You can use fct_infreq() when you want to change the order of the x axis by the frequency of the factor. In the case of the mtcars example in this post, you want to reorder the cyl levels by the frequency of each level. The level that most often remains on the left side. All you need is fct_infreq() .

 library(ggplot2) library(forcats) ggplot(mtcars, aes(fct_infreq(factor(cyl)))) + geom_bar() + labs(x = "cyl") 

If you want to go the other way around, you can use fct_rev() along with fct_infreq() .

 ggplot(mtcars, aes(fct_rev(fct_infreq(factor(cyl))))) + geom_bar() + labs(x = "cyl") 

enter image description here

+19
Dec 22 '16 at 6:46
source share

I understand that this is old, but maybe this function that I created is useful to someone there:

 order_axis<-function(data, axis, column) { # for interactivity with ggplot2 arguments <- as.list(match.call()) col <- eval(arguments$column, data) ax <- eval(arguments$axis, data) # evaluated factors a<-reorder(with(data, ax), with(data, col)) #new_data df<-cbind.data.frame(data) # define new var within(df, do.call("<-",list(paste0(as.character(arguments$axis),"_o"), a))) } 

Now, with this function, you can interactively draw with ggplot2, for example:

 ggplot(order_axis(df, AXIS_X, COLUMN_Y), aes(x = AXIS_X_o, y = COLUMN_Y)) + geom_bar(stat = "identity") 

As you can see, the order_axis function creates another data frame with a new column with the same name, but with _o at the end. This new column has levels in ascending order, so ggplot2 is automatically laid in that order.

This is somewhat limited (it only works for symbolic or factorial and numeric combinations of columns and in ascending order), but I still find it very useful for plotting on the go.

+2
Oct 08 '15 at 23:00
source share



All Articles