I'm using ggplot, and am trying to add a ribbon in the form of a simple rectangle to a barplot I have. The idea is to show a cutoff below a certain value.
The barplot is fine but I can't quite get the ribbon right - I'd like it displayed a little wider but it seems to be limited to the width of the barplot data.
I tried using xmin and xmax but that doesn't increase the width of the shaded area.
Is there a way of explicitly controlling the width of geom_ribbon?
# Where df is a data frame containing the data to plot
library(cowplot)
ggplot(df, aes(x=treatments, y=propNotEliminated)) +
geom_ribbon(aes(xmin=0, xmax=21, ymin=0, ymax=20)) + # the xmin and xmax don't do what I'd expect
geom_bar(stat="identity", fill="white", colour="black", size=1) +
theme_cowplot()
Why not use geom_rect?
ggplot(mtcars, aes(factor(cyl))) +
geom_bar() +
geom_rect(xmin = 0, xmax = Inf, ymin = 0, ymax = 1, fill = "blue") +
geom_rect(xmin = 1, xmax = 3, ymin = 1, ymax = 2, fill = "red") +
geom_rect(xmin = 1 - 0.5, xmax = 3 + 0.5, ymin = 2, ymax = 3, fill = "green")
After you're satisfied with the placement, put geom_bar last.
Related
I made a faceted graph using ggplot, and then tried to use the function annotate to create a grey highlighted area in one specific panel of the plot only.
I tried to adapt the labeling method from this question, but I couldn't get it to work:
How to add annotation on each facet
Here is a reproducible example:
ggplot(iris, aes(x = Sepal.Length))+
geom_point(aes(y = Petal.Length))+
facet_grid(Species~.)+
annotate(geom = 'rect', xmin = 6, xmax = 6.5, ymin= 0, ymax= Inf,
fill = 'grey20', alpha = 0.2)
output:
I want the grey highlight to appear on only the versicolor facet, not every facet.
EDIT
As the user #user11362344 has proposed, i test his indication to use geom_rect(), and add to the code in the place of annotate() and WORKED VERY WELL!:
ggplot(data_2, aes(x = Sepal.Length))+
geom_point(aes(y = Petal.Length))+
facet_grid(Species~.)+
geom_rect(data=data.frame(Species='versicolor'), inherit.aes=F,
xmin = 6, xmax = 6.5, ymin = 0, ymax = Inf, fill = 'grey20', alpha = 0.2)
output:
Thanks everyone for the help! And specially thanks for #user11362344!
geom_rect(data=data.frame(Species='versicolor'), inherit.aes=FALSE,
xmin = 6, xmax = 6.5, ymin= 0, ymax= Inf,
fill = 'grey20', alpha = 0.2)
I am trying to annotate a ggplot histogram with a shaded rectangle, and am trying to figure out if there is a way to pass an argument to ymax that will dynamically scale the rectangle to the ymax of the plotting area.
I can achieve the desired effect by hard coding the ymax value of the annotate() to be greater than the plot ymax then 'cropping' back the plot using coord_cartesian() shown in the example below. However, this requires me to know a priori what the max of the histogram will be, which of course will change if I adjust binwidth. There is some way to scale ymax dynamically?
ggplot(
data = mtcars,
aes(
x=mpg
)
)+
geom_histogram(
binwidth = 3,
fill = "gray63"
)+
annotate(
"rect",
xmin = 21,
xmax = 22,
ymin = 0,
ymax = 10, #hardcode ymax to be > plot ymax
fill = "gray18",
alpha = 0.5
)+
theme_bw()
coord_cartesian(
ylim = c(0,8) #crop back to plot ymax
)
Many position arguments can accept Inf or -Inf, setting them to whatever is the highest/lowest value currently shown. That's set by the plot limits, not necessarily the data. You can then drop the coord_cartesian bit, because you don't need to hard-code the limits any more.
library(ggplot2)
ggplot(mtcars, aes(x = mpg)) +
geom_histogram(binwidth = 3, fill = "gray63") +
annotate("rect", xmin = 21, xmax = 22, ymin = 0, ymax = Inf, fill = "gray18", alpha = 0.5)
If, for whatever reason, you needed the plot to show a higher limit, you can see that Inf will then adjust accordingly:
ggplot(mtcars, aes(x = mpg)) +
geom_histogram(binwidth = 3, fill = "gray63") +
annotate("rect", xmin = 21, xmax = 22, ymin = 0, ymax = Inf, fill = "gray18", alpha = 0.5) +
ylim(0, 12)
This question already has answers here:
geom_rect and alpha - does this work with hard coded values?
(4 answers)
Closed 2 years ago.
I recently upgraded to R version 3.2.3 and also to ggplot version 2.0.0.
Trying to upgrade some old code to the newer versions I encountered a weird behaviour with ggplot2 and its transparency settings.
Now my question is, is this a bug or a feature (if so, can someone enlighten me as to why its good to have it this way)? The result I want to have is (obviously) plot 2.
Say I plot a line and lay a rectangle with transparency over it like this:
library(ggplot2)
plot_data <- data.frame(x = 1:100, y = rnorm(100))
# Plot 1
ggplot(data = plot_data, aes(x = x, y = y)) +
geom_line() +
geom_rect(aes(xmin = 20, xmax = 50, ymin = -Inf, ymax = Inf), fill = "red",
alpha = 0.1) + ggtitle("Plot 1")
# Plot 2
ggplot() +
geom_line(data = plot_data, aes(x = x, y = y)) +
geom_rect(aes(xmin = 20, xmax = 50, ymin = -Inf, ymax = Inf), fill = "red",
alpha = 0.1) + ggtitle("Plot 2")
To my understanding plot 1 and 2 should be identical. However, I get the following plots:
Plot 1:
and plot 2:
Additionally, if I play around with the alpha-values (for example setting them to 0.01, I get the two following plots:
and
I believe that calling geom_rect without a data parameter will effectively draw an individual rectangle for each row of the data.frame which is why the alpha is "working", but not quite as expected. I have not been able to replicate and get to parity/agreement between the methods, but as you noted, I think it is doing something along the lines of drawing either 100 individual rectangles, or 30 (the width of the rectangles; from 20 to 50) which is why alpha = 0.1 / 100 and alpha = 0.1 / 30 gets you closer, but not quite matching.
Regardless, I would probably use annotate, as that better describes the behavior/result you are trying to achieve without issues and works, as expected, in both cases -- annotations will draw a single instance per geom:
ggplot(data = plot_data, aes(x = x, y = y)) +
# geom_rect(aes(xmin = 20, xmax = 50, ymin = -Inf, ymax = Inf, alpha = 0.1, fill = "red")) +
annotate("rect", xmin = 20, xmax = 50, ymin = -Inf, ymax = Inf, alpha = 0.1, fill = "red") +
geom_line() +
ggtitle("Plot 1")
ggplot() +
geom_line(data = plot_data, aes(x = x, y = y)) +
# geom_rect(aes(xmin = 20, xmax = 50, ymin = -Inf, ymax = Inf), fill = "red", alpha = 0.1) +
annotate("rect", xmin = 20, xmax = 50, ymin = -Inf, ymax = Inf, fill = "red", alpha = 0.1) +
ggtitle("Plot 2")
I have a plot in R to analyse the functional behaviour of this function :
-2.5*log10(x) in different regions , the inputs are like this
curve(-2.5*log10(x),0,5,main="Behaviour of magnification function",col=2)
abline(v=0,col=3)
abline(v=1,col=4)
abline(h=0,col=8)
Now I would like to shade those regions on the right of the v=1 line and left with two different shades, but can't figure it out how to do. the polygon function not giving the shade , please help
thanks,
Ayan
You can use the panel.first argument to draw in the background.
Define a function to do the drawing:
fnShade = function(v,colL,colR) {
p = par("usr") # limits of the plot
rect(p[1],p[3],v,p[4],col=colL,border=NA)
rect(v,p[3],p[2],p[4],col=colR,border=NA)
abline(v=v,col=4)
}
Then use it
curve(-2.5*log10(x),0,5,main="Behaviour of magnification function",col=2,
panel.first=fnShade(1,5,"grey80"))
You can add your other ablines into the function if you like. And it should be easy to extend to draw 4 rectangles - one for each quardant - if desired.
Here is a ggplot solution to the problem, using annotate:
First, save the results from curve in df:
df <- curve(-2.5*log10(x),0,5,main="Behaviour of magnification function",col=2)
Then use geom_vline to add the vertical lines, and annotate to add a rect geom to the data for the shaded areas. We use annotate, because we do not want to use data from the original data frame as suggested in this answer.
plot <- ggplot(data.frame(df)) +
geom_line(aes(x, y), size = 1) +
geom_vline(xintercept = 1, color = "blue", size = 1) +
geom_hline(yintercept = 0, color ="grey", size = 1) +
geom_vline(xintercept = 0, color = "green", size = 1) +
annotate("rect", xmin = 1, xmax = Inf, ymax = Inf, ymin = -Inf, fill = "blue", alpha = 0.2) +
annotate("rect", xmin = -Inf, xmax = 1, ymax = Inf, ymin = -Inf, fill = "green", alpha = 0.2) +
labs(title = "Behaviour of magnification function\n") +
theme_bw()
plot
I am trying to shade a certain section of a time series plot (a bit like recession shading - similarly to the graph at the bottom of this article on recession shading in excel). I have put a little, possibly clumsy, sample together to illustrate.
I first create a time series, plot it with ggplot2 and then want to use geom_rect to provide the shading. But I must get something wrong in the arguments.
a<-rnorm(300)
a_ts<-ts(a, start=c(1910, 1), frequency=12)
a_time<-time(a_ts)
a_series<-ts.union(big=a_ts, month=a_time)
a_series_df<-as.data.frame(a_series)
ggplot(a_series)+
geom_line(mapping=aes_string(x="month", y="big"))+
geom_rect(
fill="red",alpha=0.5,
mapping=aes_string(x="month", y="big"),
xmin=as.numeric(as.Date(c("1924-01-01"))),
xmax=as.numeric(as.Date(c("1928-12-31"))),
ymin=0,
ymax=2
)
Note that I have also tried which also did not work.
geom_rect(
fill="red",alpha=0.5,
mapping=aes_string(x="month", y="big"),
aes(
xmin=as.numeric(as.Date(c("1924-01-01"))),
xmax=as.numeric(as.Date(c("1928-12-31"))),
ymin=0,
ymax=2)
)
Its a bit easier using annotate and also note that the bounds for the rectange can be specified as shown:
ggplot(a_series_df, aes(month, big)) +
geom_line() +
annotate("rect", fill = "red", alpha = 0.5,
xmin = 1924, xmax = 1928 + 11/12,
ymin = -Inf, ymax = Inf) +
xlab("time")
This would also work:
library(zoo)
z <- read.zoo(a_series_df, index = 2)
autoplot(z) +
annotate("rect", fill = "red", alpha = 0.5,
xmin = 1924, xmax = 1928 + 11/12,
ymin = -Inf, ymax = Inf) +
xlab("time") +
ylab("big")
Either one gives this:
Code works fine, conversion to decimal date is needed for xmin and xmax, see below, requires lubridate package.
library("lubridate")
library("ggplot2")
ggplot(a_series_df)+
geom_line(mapping = aes_string(x = "month", y = "big")) +
geom_rect(
fill = "red", alpha = 0.5,
mapping = aes_string(x = "month", y = "big"),
xmin = decimal_date(as.Date(c("1924-01-01"))),
xmax = decimal_date(as.Date(c("1928-12-31"))),
ymin = 0,
ymax = 2
)
Cleaner version, shading plotted first so the line colour doesn't change.
ggplot() +
geom_rect(data = data.frame(xmin = decimal_date(as.Date(c("1924-01-01"))),
xmax = decimal_date(as.Date(c("1928-12-31"))),
ymin = -Inf,
ymax = Inf),
aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax),
fill = "grey", alpha = 0.5) +
geom_line(data = a_series_df,aes(month, big), colour = "blue") +
theme_classic()
To use geom_rect you need to define your rectangle coordinate through a data.frame:
shade = data.frame(x1=c(1918,1930), x2=c(1921,1932), y1=c(-3,-3), y2=c(4,4))
# x1 x2 y1 y2
#1 1918 1921 -3 4
#2 1930 1932 -3 4
Then you give ggplot your data and the shade data.frame:
ggplot() +
geom_line(aes(x=month, y=big), color='red',data=a_series_df)+
geom_rect(data=shade,
mapping=aes(xmin=x1, xmax=x2, ymin=y1, ymax=y2), color='grey', alpha=0.2)
library(xts)
library(zoo)
library(ggts)
Creating an xts object
data<-as.xts(x=runif(228,20,40),order.by = seq(as.Date("2000/01/01"), by = "month", length.out = 228))
Creating data frame of dates for which you want to crate shades
date<-data.frame(as.Date("2008-01-01"),as.Date("2009-01-01"))
Now create plot with shaded area
plot_data<-ggts(data)+geom_cycle(date)