Order Bars in ggplot2 bar graph
I am trying to make a bar graph where the largest bar would be nearest to the y axis and the shortest bar would be furthest. So this is kind of like the Table I have
Name Position
1 James Goalkeeper
2 Frank Goalkeeper
3 Jean Defense
4 Steve Defense
5 John Defense
6 Tim Striker
So I am trying to build a bar graph that would show the number of players according to position
p <- ggplot(theTable, aes(x = Position)) + geom_bar(binwidth = 1)
but the graph shows the goalkeeper bar first then the defense, and finally the striker one. I would want the graph to be ordered so that the defense bar is closest to the y axis, the goalkeeper one, and finally the striker one. Thanks
@GavinSimpson: reorder
is a powerful and effective solution for this:
ggplot(theTable,
aes(x=reorder(Position,Position,
function(x)-length(x)))) +
geom_bar()
The key with ordering is to set the levels of the factor in the order you want. An ordered factor is not required; the extra information in an ordered factor isn't necessary and if these data are being used in any statistical model, the wrong parametrisation might result — polynomial contrasts aren't right for nominal data such as this.
## set the levels in order we want
theTable <- within(theTable,
Position <- factor(Position,
levels=names(sort(table(Position),
decreasing=TRUE))))
## plot
ggplot(theTable,aes(x=Position))+geom_bar(binwidth=1)
In the most general sense, we simply need to set the factor levels to be in the desired order. If left unspecified, the levels of a factor will be sorted alphabetically. You can also specify the level order within the call to factor as above, and other ways are possible as well.
theTable$Position <- factor(theTable$Position, levels = c(...))
Using scale_x_discrete (limits = ...)
to specify the order of bars.
positions <- c("Goalkeeper", "Defense", "Striker")
p <- ggplot(theTable, aes(x = Position)) + scale_x_discrete(limits = positions)
I think the already provided solutions are overly verbose. A more concise way to do a frequency sorted barplot with ggplot is
ggplot(theTable, aes(x=reorder(Position, -table(Position)[Position]))) + geom_bar()
It's similar to what Alex Brown suggested, but a bit shorter and works without an anynymous function definition.
Update
I think my old solution was good at the time, but nowadays I'd rather use forcats::fct_infreq
which is sorting factor levels by frequency:
require(forcats)
ggplot(theTable, aes(fct_infreq(Position))) + geom_bar()