I’m having a problem with geom_bars wherein the bars are not rendered when I specify limits on the y-axis. I believe the following should reproduce the problem:
data <- structure(list(RoleCond = structure(c(1L, 1L, 2L, 2L), .Label = c("Buyer", "Seller"), class = "factor"),
ArgCond = structure(c(1L, 2L, 1L, 2L), .Label = c("No Argument", "Argument"), class = "factor"),
mean = c(2210.71428571429, 2142.70833333333, 2282.40740740741, 2346.2962962963),
se = c(20.1231042081511, 16.7408757749718, 20.1471554637891, 15.708092540868)),
.Names = c("RoleCond", "ArgCond", "mean", "se"), row.names = c(NA, -4L), class = "data.frame")
library(ggplot2)
ggplot(data=data, aes(fill=RoleCond, y=mean, x=ArgCond)) +
geom_bar(position="dodge", stat="identity") +
geom_errorbar(limits, position=dodge, width=0.1, size=.75) +
scale_y_continuous(limits=c(2000,2500))
which gives me this
The same code without the limits specified works fine. The geom_errorbar() doesn’t seem to be related to the problem, but it does illustrate where the bars should be showing up.
I’ve tried using coord_cartesian(ylim=c(2000,2500))
which works for limiting the yaxis and getting the bars to display, but the axis labels get messed up and I don’t understand what I’m doing with it.
Thanks for any suggestions! (I’m using R 2.15.0 and ggplot2 0.9.0)
1
Answer recommended by R Language
Collective
You could try, with library(scales)
:
+ scale_y_continuous(limits=c(2000,2500),oob = rescale_none)
instead, as outlined here.
5
This worked for me based on the link shared previously.
p + coord_cartesian(ylim=c(5,15))
0
Adding an answer for my case which was slightly different in case someone comes across this:
When using position="dodge"
, the bars get horizontally resized automatically to fill space that is often well beyond the limits of the data itself. As a result, even if both your x-axis
and y-axis
limits are limits=c(min-1, max+1
, for certain data sets, the position="dodge"
might resize it beyond that limit range, causing the bars to not appear. This might even occur if your limit floor is 0, unlike the case above.
Using oob=rescale_none
in both scale_y_continous()
AND scale_x_continuous()
fixes this issue by simply cutting off the resizing done by position="dodge"
.
As per earlier comment, it requires package:scales
so run library(scales)
first.
Hope this helps someone else where the above answers only get you part way.
1
This is a community wiki essentially copying user teunbrand’s canonical answer to that topic – for more visibility added to this larger thread.
Consider the following plot (geom_col()
is equivalent to geom_bar(stat = "identity")
):
df <- data.frame(x = letters[1:7],
y = 1:7)
g <- ggplot(df, aes(x, y)) +
geom_col()
g
You can clearly see that the bars look like rectangles. Checking the underlying plot data, confirms that the bars are parameterised as rectangles with xmin/xmax/ymin/ymax parametrisation:
> layer_data(g)
x y PANEL group ymin ymax xmin xmax colour fill size linetype alpha
1 1 1 1 1 0 1 0.55 1.45 NA grey35 0.5 1 NA
2 2 2 1 2 0 2 1.55 2.45 NA grey35 0.5 1 NA
3 3 3 1 3 0 3 2.55 3.45 NA grey35 0.5 1 NA
4 4 4 1 4 0 4 3.55 4.45 NA grey35 0.5 1 NA
5 5 5 1 5 0 5 4.55 5.45 NA grey35 0.5 1 NA
6 6 6 1 6 0 6 5.55 6.45 NA grey35 0.5 1 NA
7 7 7 1 7 0 7 6.55 7.45 NA grey35 0.5 1 NA
Now consider the following plot:
g2 <- ggplot(df, aes(x, y)) +
geom_col() +
scale_y_continuous(limits = c(1, 7))
This one is empty, and reflects the case you have posted. Inspecting the underlying data yields the following:
> layer_data(g2)
y x PANEL group ymin ymax xmin xmax colour fill size linetype alpha
1 1 1 1 1 NA 1 0.55 1.45 NA grey35 0.5 1 NA
2 2 2 1 2 NA 2 1.55 2.45 NA grey35 0.5 1 NA
3 3 3 1 3 NA 3 2.55 3.45 NA grey35 0.5 1 NA
4 4 4 1 4 NA 4 3.55 4.45 NA grey35 0.5 1 NA
5 5 5 1 5 NA 5 4.55 5.45 NA grey35 0.5 1 NA
6 6 6 1 6 NA 6 5.55 6.45 NA grey35 0.5 1 NA
7 7 7 1 7 NA 7 6.55 7.45 NA grey35 0.5 1 NA
You can see that the ymin
column is replaced by NA
s. This behaviour depends on the oob
(out-of-bounds) argument of scale_y_continuous()
, which defaults to the scales::censor()
function. This censors (replaces with NA
) any values that are outside the axis limits, which includes the 0 which should be the ymin
column. As a consequence, the rectangles can’t be drawn.
There are two ways to work around this. One candidate is indeed as Magnus suggested to use the ylim
argument in the coord_cartesian()
function:
ggplot(df, aes(x, y)) +
geom_col() +
coord_cartesian(ylim = c(1, 7))
Specifying the limits inside a coord_*
function causes the graphical objects to be clipped. You can see this in action when you turn the clipping off:
ggplot(df, aes(x, y)) +
geom_col() +
coord_cartesian(ylim = c(1, 7), clip = "off")
The other option is to use an alternative oob
argument in the scale_y_continuous
, for example scales::squish
:
g3 <- ggplot(df, aes(x, y)) +
geom_col() +
scale_y_continuous(limits = c(1, 7),
oob = scales::squish)
g3
What this does, is that it replaces any value outside the limits by the nearest limit, e.g. the ymin
of 0 becomes 1:
> layer_data(g3)
y x PANEL group ymin ymax xmin xmax colour fill size linetype alpha
1 1 1 1 1 1 1 0.55 1.45 NA grey35 0.5 1 NA
2 2 2 1 2 1 2 1.55 2.45 NA grey35 0.5 1 NA
3 3 3 1 3 1 3 2.55 3.45 NA grey35 0.5 1 NA
4 4 4 1 4 1 4 3.55 4.45 NA grey35 0.5 1 NA
5 5 5 1 5 1 5 4.55 5.45 NA grey35 0.5 1 NA
6 6 6 1 6 1 6 5.55 6.45 NA grey35 0.5 1 NA
7 7 7 1 7 1 7 6.55 7.45 NA grey35 0.5 1 NA
Another thing you could do is provide a custom function to the oob
argument, that simply returns it’s input. Since by default, clipping is on, this reflects the coord_cartesian(ylim = c(1,7))
case:
ggplot(df, aes(x, y)) +
geom_col() +
scale_y_continuous(limits = c(1, 7),
oob = function(x, ...){x})