shaded area between two lines in ggplot - r

I would like to create a shaded area in color blue between the two dotted lines (-0.5 and 0.5), tried with geom_polygon() but didn't work.
How can this be done in the best possible way?
model <- lm(Sepal.Width ~ Petal.Length, data = iris)
ggplot(data.frame(x = seq(model$residuals), y = model$residuals)) +
geom_point(aes(x, y)) +
geom_hline(yintercept = 0, linetype = "dashed") +
geom_hline(yintercept = 0.5, linetype = "dotted") +
geom_hline(yintercept = -0.5, linetype = "dotted") +
labs(x = "Index", y = "Residuals",
title = paste("Residuals of", format(model$call)))

You can use geom_ribbon
ggplot(data.frame(x = seq(model$residuals), y = model$residuals)) +
geom_point(aes(x, y)) +
geom_ribbon(aes(x, ymin = -0.5, ymax = 0.5), alpha = 0.3, fill = 'steelblue')+
geom_hline(yintercept = 0, linetype = "dashed") +
geom_hline(yintercept = 0.5, linetype = "dotted") +
geom_hline(yintercept = -0.5, linetype = "dotted") +
labs(x = "Index", y = "Residuals",
title = paste("Residuals of", format(model$call)))

With annotate:
annotate("rect", xmin = -Inf, xmax = Inf, ymin = -0.5, ymax = 0.5, alpha = .2, fill = "blue")
Output:
ggplot(data.frame(x = seq(model$residuals), y = model$residuals)) +
geom_point(aes(x, y)) +
geom_hline(yintercept = 0, linetype = "dashed") +
geom_hline(yintercept = c(-0.5, 0.5), linetype = "dotted") +
annotate("rect", xmin = -Inf, xmax = Inf, ymin = -0.5, ymax = 0.5, alpha = .2, fill = "blue") +
labs(x = "Index", y = "Residuals",
title = paste("Residuals of", format(model$call)))

Related

Ggplot2: Create legend using scale_fill_manual() for geom_rect() and geom_line() in one plot?

I want to create a plot with geom_line() and geom_rect(). For both I would like to create a legend, but I does not work. How can both be combined? As you can see in the attached picture, my legend is messed up: Colours and shapes are not correctly displayed.
graph= data.frame(seq(as.Date("2004/01/01"), as.Date("2022/01/01"), by="month"),rnorm(217,mean=1,sd=2),rnorm(217,mean=1,sd=2),rnorm(217,mean=1,sd=2))
colnames(graph) = c("Datum","VPI","VPIF","VPIE")
plot1 = ggplot(graph, aes(x = graph$Datum)) +
geom_line(aes(y = graph$VPI, colour = "black"), size = 0.8) +
geom_line(aes(y = graph$VPIF, colour = "red"), size = 0.8) +
geom_line(aes(y = graph$VPIE, colour = "snow4"), size = 0.8) +
geom_rect(aes(xmin = graph$Datum[49], xmax = graph$Datum[72], ymin = 125, ymax = 130,fill="cyan") ,alpha = 0.5)+
geom_rect(aes(xmin = graph$Datum[84], xmax = graph$Datum[120], ymin = 125, ymax = 130,fill="darkolivegreen"), alpha = 0.5)+
geom_rect(aes(xmin = graph$Datum[195], xmax = graph$Datum[217], ymin = 125, ymax = 130,fill="blueviolet"), alpha = 0.5)+
scale_fill_manual(name=NULL,values=c("black","red","snow4","cyan","darkolivegreen","blueviolet"), labels=c("VPI","VPI Lebensmittel","VPI Energie","Weltfinanzkrise","Euro-/Schuldenkrise","Coronakrise"),aesthetics = c("colour","fill")) +
theme_bw() +
theme(legend.position = "bottom",
axis.text.x = element_text(angle = 90)) +
labs(title = "Verbraucherpreisindex: Gesamt, Lebensmittel, Energie", subtitle = "2015=100",
y = "Prozent",
x = "Jahre")
plot1
Transform the data from wide to long. Here I used pivot_longer from the tidyverse package. But you can also use melt or reshape.
library(tidyverse)
data_rect <- tibble(xmin = graph$Datum[c(49,84,195)],
xmax = graph$Datum[c(72,120,217)],
ymin = 50,
ymax=53,
gr = c("1", "2", "3"))
graph %>%
pivot_longer(-1) %>%
ggplot(aes(Datum, value)) +
geom_line(aes(color = name)) +
geom_rect(data=data_rect, inherit.aes = F, aes(xmin=xmin, xmax=xmax, ymin=ymin, ymax=ymax, fill=gr))
Something like this?
graph %>%
pivot_longer(
-Datum
) %>%
ggplot(aes(x=Datum, y = value)) +
geom_line(aes(color = name)) +
scale_color_manual(name = NULL, values = c("black", "red", "snow4"))+
geom_rect(aes(xmin = graph$Datum[49], xmax = graph$Datum[72], ymin = 125, ymax = 130,fill="cyan") ,alpha = 0.5)+
geom_rect(aes(xmin = graph$Datum[84], xmax = graph$Datum[120], ymin = 125, ymax = 130,fill="darkolivegreen"), alpha = 0.5)+
geom_rect(aes(xmin = graph$Datum[195], xmax = graph$Datum[217], ymin = 125, ymax = 130,fill="blueviolet"), alpha = 0.5)+
scale_fill_manual(name = NULL, values = c("cyan", "darkolivegreen", "blueviolet"))
theme_bw() +
theme(legend.position = "bottom",
axis.text.x = element_text(angle = 90)) +
labs(title = "Verbraucherpreisindex: Gesamt, Lebensmittel, Energie", subtitle = "2015=100",
y = "Prozent",
x = "Jahre")

Recreate a plot without data

Is there a way to create a figure similar to the one below without having any data on this?
You could do something like this. You could add another geom_curve and a couple of geom_vlines.
library(tidyverse)
ggplot() +
geom_abline() +
geom_curve(aes(x = 0, y = 0, xend = 1, yend = 1), curvature = -0.4) +
annotate("text", x = 0.5, y = 0.5, label = "Line of Equality", angle = 35, vjust = 2) +
labs(x = "Individuals Neighbourhoods\nAcross Space", y = "Scoioeconomic Position") +
theme_minimal() +
theme(axis.text = element_blank())
Created on 2022-04-27 by the reprex package (v2.0.1)
For the arrows you can use this code: arrow = arrow(length = unit(0.5, "cm")) in a geom_segment. It is a bit tricky without any numbers, but maybe you want something like this:
library(ggplot2)
ggplot() +
geom_abline(slope = 1) +
geom_curve(aes(x = 0, y = 0, xend = 1, yend = 1), curvature = -0.4) +
geom_curve(aes(x = 0, y = 1, xend = 1, yend = 0.1), curvature = 0.4, linetype = "dashed") +
geom_segment(aes(x=0.9,y=0.98,xend=0.9,yend=0.12), arrow = arrow(length = unit(0.5, "cm"))) +
geom_segment(aes(x=0.02,y=0.85,xend=0.02,yend=0.23), arrow = arrow(length = unit(0.5, "cm"))) +
annotate("text", x = 0.5, y = 0.5, label = "Line of Equality", angle = 45, vjust = 2) +
annotate("text", x = 0.25, y = 0.75, label = "Income (etc.)", angle = 45, vjust = 2) +
annotate("text", x = 1.2, y = 0.1, label = "Corresponding\nExposure", angle = 0) +
labs(x = "Individuals Neighbourhoods\nAcross Space", y = "Scoioeconomic Position") +
scale_x_continuous(limits = c(0, 1.3)) +
theme_minimal() +
theme(axis.text = element_blank())
Output:

Adding labels to this ggridge plot

I can't see, to figure out how to add labels to this plot:
ggplot(input_cleaned, aes(x =DAYS_TO_FA, y = fct_rev(DATE_TEXT), group = fct_rev(DATE_TEXT))) +
geom_density_ridges2(stat="binline", bins = 75, scale = 0.95, draw_baseline = FALSE) +
labs(title = 'Monthly Plots of Time to First Nose Pickin', y='Month Tracked', x = 'Days to First Pickin Action') +
theme(plot.title = element_text(hjust = 0.5), plot.subtitle = element_text(hjust = 0.5)) +
scale_x_continuous(breaks=seq(0,130,5)) +
geom_segment(aes(x=50, xend = 50, y=1,yend=5),
linetype = "dashed", size = 1.5,
color = "black") +
geom_segment(aes(x=75, xend = 75, y=5,yend=30),
linetype = "dashed", size = 1.5,
color = "black")
which produces:
I have tried this:
ggplot(input_cleaned, aes(x =DAYS_TO_FA, y = fct_rev(DATE_TEXT), group = fct_rev(DATE_TEXT))) +
geom_density_ridges2(stat="binline", bins = 75, scale = 0.95, draw_baseline = FALSE) +
geom_text(stat = "bin",
aes(y = fct_rev(input_cleaned$DATE_TEXT) + 0.95*(..count../max(..count..)), label = ifelse(..count..>0, ..count.., "")),
vjust = 1.4, size = 3, color = "white", binwidth = 1) +
labs(title = 'Monthly Plots of Time to First Nose Pickin', y='Month Tracked', x = 'Days to First Pickin Action') +
theme(plot.title = element_text(hjust = 0.5), plot.subtitle = element_text(hjust = 0.5)) +
scale_x_continuous(breaks=seq(0,130,5)) +
geom_segment(aes(x=50, xend = 50, y=1,yend=5),
linetype = "dashed", size = 1.5,
color = "black") +
geom_segment(aes(x=75, xend = 75, y=5,yend=30),
linetype = "dashed", size = 1.5,
color = "black")
based on the example found here:
Visualization of Groups of Poisson random samples using ggridges
but I can't get it to work. Nothing changes.
I know it may not be a good idea for this graph, but I am interested in seeing how it looks and more or less learning how to apply it.

ggplot2: Highlight area depending on dnorm function

I want to highlight the area between a vertical line and a normal distributed function. I know how it works with discrete values, but the stat_function confuses me. The code looks something like this:
library(ggplot2)
n1 <- 5
ggplot(data.frame(x = c(-2, 2)), aes(x)) +
stat_function(fun = dnorm, args = list(sd = 1/sqrt(n1))) +
geom_vline(xintercept = 0.5, linetype = "dashed", color = "red", size = 1) +
geom_vline(xintercept = -0.5, linetype = "dashed", color = "red", size = 1) +
ylim(c(0, 1.5)) +
theme_light() +
geom_rect(aes(xmin = 0.5, xmax = Inf, ymax = Inf, ymin = 0), fill = "grey", alpha = .3)
I know I need to change ymax to the values of x > 0.5. The question is how?
EDIT:
I looked into the question which is supposed to be the same as mine. When I rewrite the code the way they did, the highlighting works but it doesn't give me a proper normal distribution anymore, as you can see here:
library(dplyr)
set.seed(123)
range <- seq(from = -2, to = 2, by = .01)
norm <- rnorm(range, sd = 1 / sqrt(n1))
df <- data_frame(x = density(norm)$x, y = density(norm)$y)
ggplot(data_frame(values = norm)) +
stat_density(aes(x = values), geom = "line") +
geom_vline(xintercept = 0.5, linetype = "dashed", color = "red", size = 1) +
geom_vline(xintercept = -0.5, linetype = "dashed", color = "red", size = 1) +
ylim(c(0, 1.5)) +
theme_light() +
geom_ribbon(data = filter(df, x > 0.5),
aes(x = x, ymax = y), ymin = 0, fill = "red", alpha = .5)
When I stick with stat_function and use geom_ribbon with subsetting as proposed in the very same question, it highlights buggy, as you can see here:
ggplot(data_frame(x = c(-2, 2)), aes(x)) +
stat_function(fun = dnorm, args = list(sd = 1/sqrt(n1))) +
geom_vline(xintercept = 0.5, linetype = "dashed", color = "red", size = 1) +
geom_vline(xintercept = -0.5, linetype = "dashed", color = "red", size = 1) +
ylim(c(0, 1.5)) +
theme_light() +
geom_ribbon(data = filter(df, x > 0.5),
aes(x = x, ymax = y), ymin = 0, fill = "red", alpha = .5)
Not satisfying yet.
Here is an approach:
library(ggplot2)
n1 <- 5
ggplot(data.frame(x = c(-2, 2)), aes(x)) +
stat_function(fun = dnorm, geom = "area", fill = "grey", alpha = 0.3, args = list(sd = 1/sqrt(n1)), xlim = c(-0.5,0.5)) +
stat_function(fun = dnorm, args = list(sd = 1/sqrt(n1))) +
geom_vline(xintercept = 0.5, linetype = "dashed", color = "red", size = 1) +
geom_vline(xintercept = -0.5, linetype = "dashed", color = "red", size = 1) +
ylim(c(0, 1.5)) +
theme_light()
in stat_function one can define different geom, just pick the ones that suits your needs.

Transparent masking in ggplot2

I'm interested in ways to only include panel grid lines right near the ribbon--I can do this manually, in a trivial example
library(ggplot2)
d1 <- data.frame(x = seq(0, 1, length.out = 200))
d1$y1 <- -3*(d1$x-.5)^2 + 1
d1$y2 <- -3*(d1$x-.5)^2 + 2
ggplot(d1) +
geom_ribbon(aes(x, ymin = y1, ymax = y2),
alpha = .25) +
geom_ribbon(aes(x, ymax = y1),
ymin = .25,
fill = "white") +
geom_ribbon(aes(x, ymin = y2),
ymax = 2,
fill = "white") +
scale_y_continuous(limits = c(.25, 2.0),
expand = c(0, 0))+
scale_x_continuous(limits = c(0, 1),
expand = c(0, 0))+
theme_bw() +
theme(panel.grid = element_line(linetype = 1, color = "black"))
is there some less hacky way to have a transparent mask for these gridlines, so they only appear underneath a ribbon?
If gridlines the same color as the background are acceptable, you can remove the actual gridlines, then use geom_hline() and geom_vline() to make your own "gridlines" that will show on ribbons but be invisible against the background
d1$y3 <- d1$x + 0.3
d1$y4 <- d1$x + 0.4
ggplot(d1) +
geom_ribbon(aes(x, ymin = y1, ymax = y2), alpha = 0.25) +
geom_ribbon(aes(x, ymin = y3, ymax = y4), alpha = 0.25, fill = "blue") +
# use geom_vline and geom_hline to plot "gridlines" on top of ribbons
geom_hline(yintercept = seq(0, 2, by = 0.25), colour = "white") +
geom_vline(xintercept = seq(0, 1, by = 0.25), colour = "white") +
scale_y_continuous(limits = c(.25, 2.0), expand = c(0, 0)) +
scale_x_continuous(limits = c(0, 1), expand = c(0, 0)) +
theme_bw() +
theme(panel.grid.minor = element_blank(), # remove actual gridlines
panel.grid.major = element_blank())
produces this:
This is still a workaround, and will only make gridlines that match the background color, but it is easy to use with a variety of plots, such as the situation you mentioned with multiple ribbons (I've added a second ribbon to demonstrate that this will work)

Resources