Problem with GGplot: attaching recession bars to a bar chart in R - r

I have been trying to build a bar chart for GDP growth in UK and overlay it with a recession bands. I can do what is necessary with the bar plot but the moment I overlay with the recession bands, i get an error that a variable cannot be found.
uk.recessions.df <- read.table(textConnection(
"Peak, Trough
1857-06-01, 1858-12-01
1867-06-01, 1869-12-01
1873-10-01, 1879-03-01
1882-03-01, 1885-05-01
1887-03-01, 1888-04-01
1890-07-01, 1891-05-01
1893-01-01, 1894-06-01
1895-12-01, 1897-06-01
1919-03-01, 1921-07-01
1930-01-01, 1931-12-01
1956-04-01, 1956-08-01
1961-07-01, 1962-01-01
1973-09-01, 1974-04-01
1975-04-01, 1975-10-01
1980-01-01, 1981-04-01
1990-07-01, 1991-09-01
2008-04-01, 2009-07-01
2020-01-01, 2020-07-01"), sep=',',
colClasses=c('Date', 'Date'), header=TRUE)
uk.recessions.trim.df <- subset(uk.recessions.df, Peak >= min(tbl.QQGDP$Date))
tbl.data <- tbl.QQGDP %>%
mutate(Value = GDPGrowth < 0)
p <- ggplot(data = tbl.data, aes(x = Date, y = GDPGrowth, fill = Value)) +
geom_col(position = "identity", colour = "black", size = 0.25) +
scale_fill_manual(values = c("#85225f","#dbab01"), guide = FALSE) +
theme_tq()
p <- p +
geom_rect(data = uk.recessions.trim.df,
aes(xmin = Peak, xmax = Trough, ymin = -Inf, ymax = Inf),
fill = "grey", alpha = 0.5)
p
The error i get is
Error in FUN(X[[i]], ...) : object 'GDPGrowth' not found
I am cannot figure out what i am doing wrong. Any help (even if to tell me off for a silly mistake!!) will be greatly appreciated.

By default, geom_*() elements inherit the aesthetic mappings from the top level of the plot (ggplot()). In your case, the geom_rect() call is inheriting aes(x = Date, y = GDPGrowth, fill = Value) but can't find those objects as you have a different data source (uk.recessions.trim.df instead of tbl.data).
If you add the option inherit.aes = FALSE to geom_rect() you'll get the desired plot.
p <- ggplot(data = tbl.data, aes(x = Date, y = GDPGrowth, fill = Value)) +
geom_col(position = "identity", colour = "black", size = 0.25) +
scale_fill_manual(values = c("#85225f","#dbab01"), guide = FALSE)
p <- p +
geom_rect(data = uk.recessions.trim.df,
aes(xmin = Peak, xmax = Trough, ymin = -Inf, ymax = Inf),
fill = "grey", alpha = 0.5,
inherit.aes = FALSE)
p
An alternative (and probably better method) is to define data and aes in each geom separately, instead of in the initial ggplot() call. Eg:
p <- ggplot() +
geom_col(data = tbl.data,
aes(x = Date, y = GDPGrowth, fill = Value),
position = "identity", colour = "black", size = 0.25) +
scale_fill_manual(values = c("#85225f","#dbab01"), guide = FALSE)
p <- p +
geom_rect(data = uk.recessions.trim.df,
aes(xmin = Peak, xmax = Trough, ymin = -Inf, ymax = Inf),
fill = "grey", alpha = 0.5)
p

Related

Adding a dotted line between two categorical points in R

I'm new to R and I've scripted the interaction plot below, for which I want two dotted lines connecting both "coral" and both "darkgoldenrod2" points respectively:
df <- tibble::tribble(~Proportion, ~Lower,~Upper, ~Area,~Time,
invlogit(-0.033886), invlogit(-0.517223067), invlogit(0.449451067), "SNP", "Day",
(invlogit(-0.9231219)+invlogit(-0.3786)), 0.5727 ,0.8087, "SNP", "Night",
invlogit(-0.9231219), invlogit(-1.406458967), invlogit(-0.439784833),"LGCA", "Day",
invlogit(-0.1604356), invlogit(-0.643772667) ,invlogit(0.322901467), "LGCA","Night")
df
dfnew <- df %>%
mutate(ymin = Proportion - Lower,
ymax = Proportion + Upper)
p <- ggplot(data = dfnew, aes(x = Time, y = Proportion, color=Area)) +
geom_point(size = 6, stroke = 0, shape = 16,
position = position_dodge(width = 0.1))+
geom_errorbar(aes(y=Proportion, ymin = Lower, ymax = Upper),width=0.1,size=1,
position = position_dodge(width = 0.1)) +
theme(axis.text=element_text(size=15),
axis.title=element_text(size=20)) +
scale_color_manual(values = c("SNP" = "coral",
"LGCA" = "darkgoldenrod2"))
p
Reading other posts here on SO, I've used the command line: +geom_line(aes(group = 1),size=2)
This however isn't producing the desired plot as you can see below:
Any help with this is truly appreciated!
You should add group=Area to your ggplot mapping and then you just need to call geom_line. You also don't need y=Position in geom_errorbar.
p <- ggplot(data = dfnew, aes(x = Time, y = Proportion, color=Area, group=Area)) +
geom_point(size = 6, stroke = 0, shape = 16,
position = position_dodge(width = 0.1))+
geom_errorbar(aes(ymin = Lower, ymax = Upper), width=0.1, size=1,
position = position_dodge(width = 0.1)) +
theme(axis.text=element_text(size=15),
axis.title=element_text(size=20)) +
scale_color_manual(values = c("SNP" = "coral",
"LGCA" = "darkgoldenrod2")) +
geom_line(size=2)
p

geom_rect equivalent of vjust and hjust [duplicate]

I use an example from here. My question is how can I add a specific bounding box to this heatmap, such as add a red line box to the top left four tiles?
require(ggplot2)
require(reshape)
require(scales)
mydf <- data.frame(industry = c('all industries','steel','cars'),
'all regions' = c(250,150,100), americas = c(150,90,60),
europe = c(150,60,40), check.names = FALSE)
mydf
mymelt <- melt(mydf, id.var = c('industry'))
mymelt
ggplot(mymelt, aes(x = industry, y = variable, fill = value)) +
geom_tile() + geom_text(aes(fill = mymelt$value, label = mymelt$value))
A quick and dirty (some hard-coding) possibility is to use geom_rect, where the positions are given by the numerical values of the levels of x and y variables to be bound with a box, plus/minus an offset.
ggplot(mymelt, aes(x = industry, y = variable, fill = value, label = value)) +
geom_tile() +
geom_text() +
geom_rect(aes(xmin = 1 - 0.5, xmax = 2 + 0.5, ymin = 2 - 0.5, ymax = 3 + 0.5),
fill = "transparent", color = "red", size = 1.5)
A less hard-coded version:
# convert x and y variables to factors
ind <- as.factor(mymelt$industry)
vars <- as.factor(mymelt$variable)
# numeric version of the levels to be bound by a box
xmin <- unique(as.numeric(ind[ind == "all industries"]))
xmax <- unique(as.numeric(ind[ind == "cars"]))
ymin <- unique(as.numeric(vars[vars == "americas"]))
ymax <- unique(as.numeric(vars[vars == "europe"]))
# set offset
offset <- 0.5
ggplot(mymelt, aes(x = industry, y = variable, fill = value, label = value)) +
geom_tile() +
geom_text() +
geom_rect(aes(xmin = xmin - offset,
xmax = xmax + offset,
ymin = ymin - offset,
ymax = ymax + offset),
fill = "transparent", color = "red", size = 1.5)

ggplot2 - Change `geom_rect` colour in a stacked barplot

I am trying to plot a stacked barplot using ggplot2::geom_bar with backgroud shading (using ggplot2::geom_rect()) according to a categorical variable as follows:
shading <- data.frame(min = seq(from = 0.5, to = max(as.numeric(as.factor(diamonds$clarity))), by = 1),
max = seq(from = 1.5, to = max(as.numeric(as.factor(diamonds$clarity))) + 0.5, by = 1),
col = c(0,1))
ggplot() +
theme(panel.background = element_rect(fill = "transparent")) +
geom_bar(data = diamonds, mapping = aes(clarity, fill=cut)) +
geom_rect(data = shading,
aes(xmin = min, xmax = max, ymin = -Inf, ymax = Inf,
fill = factor(col), alpha = 0.1)) +
geom_bar(data = diamonds, mapping = aes(clarity, fill=cut)) +
guides(alpha = FALSE)
How to change the colours of the shading?
I have tried scale_fill_manual(values = c("white", "gray53")), but it seems that multiple scale aesthetics are not possible in ggplot2 (https://github.com/hadley/ggplot2/issues/578). Is there another way to get the desired result ?
Yes, instead of putting your colours in the aes(), put them outside (so they are used as-is). Since it's outside the aes() call you will have to use an explicit fill=shading$col rather than fill=col, and shading$col should have the colour name you are after (rather than a variable interpreted as a factor).
shading$col <- ifelse(shading$col, 'white', 'gray53')
ggplot() +
theme(panel.background = element_rect(fill = "transparent")) +
geom_bar(data = diamonds, mapping = aes(clarity, fill=cut)) +
geom_rect(data = shading,
aes(xmin = min, xmax = max, ymin = -Inf, ymax = Inf, alpha = 0.1),
fill=shading$col) + # <-- here
geom_bar(data = diamonds, mapping = aes(clarity, fill=cut)) +
guides(alpha = FALSE)

How to pass data and aesthetics across ggplot2 functions

I have to create a figure with ggplot2 that has roughly this structure:
p <- ggplot() +
geom_rect(data = regions,aes(xmin = xmin, xmax = xmax, ymin = -Inf, ymax = Inf),
fill = "yellow",alpha = 0.1) +
geom_line(data = data, aes(x=dt, y = y, color = case)) +
geom_point(data = data, aes(x=dt, y = y, color = case)) +
facet_grid(groups ~ ., scale="free_y")
geom_vline(x=as.numeric(dates_start), color = "orange3",linetype="dashed") +
geom_vline(x=as.numeric(dates_end), color = "orange3",linetype="dashed")
p
Is there anyway I can avoid having to pass all the details in geom_point? since they are the same as the one used in geom_line?

How to add bounding box to a specific area in ggplot2 heatmap?

I use an example from here. My question is how can I add a specific bounding box to this heatmap, such as add a red line box to the top left four tiles?
require(ggplot2)
require(reshape)
require(scales)
mydf <- data.frame(industry = c('all industries','steel','cars'),
'all regions' = c(250,150,100), americas = c(150,90,60),
europe = c(150,60,40), check.names = FALSE)
mydf
mymelt <- melt(mydf, id.var = c('industry'))
mymelt
ggplot(mymelt, aes(x = industry, y = variable, fill = value)) +
geom_tile() + geom_text(aes(fill = mymelt$value, label = mymelt$value))
A quick and dirty (some hard-coding) possibility is to use geom_rect, where the positions are given by the numerical values of the levels of x and y variables to be bound with a box, plus/minus an offset.
ggplot(mymelt, aes(x = industry, y = variable, fill = value, label = value)) +
geom_tile() +
geom_text() +
geom_rect(aes(xmin = 1 - 0.5, xmax = 2 + 0.5, ymin = 2 - 0.5, ymax = 3 + 0.5),
fill = "transparent", color = "red", size = 1.5)
A less hard-coded version:
# convert x and y variables to factors
ind <- as.factor(mymelt$industry)
vars <- as.factor(mymelt$variable)
# numeric version of the levels to be bound by a box
xmin <- unique(as.numeric(ind[ind == "all industries"]))
xmax <- unique(as.numeric(ind[ind == "cars"]))
ymin <- unique(as.numeric(vars[vars == "americas"]))
ymax <- unique(as.numeric(vars[vars == "europe"]))
# set offset
offset <- 0.5
ggplot(mymelt, aes(x = industry, y = variable, fill = value, label = value)) +
geom_tile() +
geom_text() +
geom_rect(aes(xmin = xmin - offset,
xmax = xmax + offset,
ymin = ymin - offset,
ymax = ymax + offset),
fill = "transparent", color = "red", size = 1.5)

Resources