Modify Legend using ggplot2 in R - r

I'm currently using the ggplot package to plot a histogram of normal variates with a N(0, 1) density overlay. I'm very new to this package and the code I'm using is
x = rnorm(1000)
qplot(x, geom = 'blank') +
geom_histogram(aes(y = ..density.., colour = 'Histogram'), legend = FALSE,
binwidth = 0.5, fill = "blue") +
stat_function(fun = dnorm, aes(colour = 'Density'))+
scale_x_continuous('x', limits = c(-4, 4))+
opts(title = "Histogram with Overlay")+
scale_colour_manual(name = 'Legend', values = c('darkblue', 'red')) +
scale_y_continuous('Frequency')+
opts(legend.key=theme_rect(fill="white",colour="white"))+
opts(legend.background = theme_rect())
This code produces the following diagram. How do I change the legend so that the line representing the histogram is replaced with a filled blue box (that represents the bars of the histogram)? Thank You!

Maybe something like this...
dat = data.frame(x=rnorm(1000))
ggplot(dat,aes(x=x)) +
geom_histogram(aes(y=..density..,fill="Histogram"),binwidth=0.5) +
stat_function(fun = dnorm, aes(colour= "Density")) +
scale_x_continuous('x', limits = c(-4, 4)) +
opts(title = "Histogram with Overlay") +
scale_fill_manual(name="",value="blue") +
scale_colour_manual(name="",value="red") +
scale_y_continuous('Frequency')+
opts(legend.key=theme_rect(fill="white",colour="white"))+
opts(legend.background = theme_blank())
Note: Since version 0.9.2 opts has been replaced by theme. So for example, the last two lines above would be:
theme(legend.key = element_rect(fill = "white",colour = "white")) +
theme(legend.background = element_blank())

Related

Merge legend in ggplot when the geoms are different

I have the following code which yields the figure below:
ggplot(data=data.frame(x=x, y=y, mass=mass)) +
geom_line(mapping = aes(x=x, y=y, linetype='Gompertz predicted mass', col='Gompertz predicted mass')) +
geom_point(mapping = aes(x=x, y=mass, shape='Actual mass',col='Actual mass')) +
theme_bw() +
ylab('Mass') +
xlab('t') +
scale_color_manual(name='',values = c("black",'red')) +
scale_linetype_manual(name='',values = c("solid")) +
scale_shape_manual(name='', values = c(19)) +
scale_x_continuous(breaks=seq(4,26,2)) +
ylim(c(0, 20000)) +
ggtitle('Problem 3: Plot of tumor mass with time')
Notice how the legend is separated. I'd like to merge it for shape and color. When the geoms are the same, the technique of using scale_something_manual works perfectly fine to merge the legends. However, I'm having trouble with it here since I have two different geoms.
The problem is similar to the one described in https://github.com/tidyverse/ggplot2/issues/3648. There is no elegant solution at the moment. Because you haven't included any data, I've presumed that your problem is conceptually similar to the plot below:
library(ggplot2)
ggplot(mpg, aes(displ, hwy)) +
geom_point(aes(shape = "Point", colour = "Point")) +
geom_smooth(aes(linetype = "Line", colour = "Line"),
formula = y ~ x, se = FALSE, method = "loess") +
scale_colour_manual(values = c("red", "black")) +
scale_linetype_manual(values = "solid") +
scale_shape_manual(values = 19)
The way to fix the problem is to get rid of the linetype and shape aesthetics and scales, and instead override aesthetics at the level of the legend.
ggplot(mpg, aes(displ, hwy)) +
geom_point(aes(colour = "Point")) +
geom_smooth(aes(colour = "Line"),
formula = y ~ x, se = FALSE, method = "loess") +
scale_colour_manual(
values = c("red", "black"),
guide = guide_legend(override.aes = list(shape = c(NA, 19),
linetype = c(1, NA)))
)
Created on 2021-09-04 by the reprex package (v2.0.1)

Raincloud plot - histogram?

I would like to create a raincloud plot. I have successfully done it. But I would like to know if instead of the density curve, I can put a histogram (it's better for my dataset).
This is my code if it can be usefull
ATSC <- ggplot(data = data, aes(y = atsc, x = numlecteur, fill = numlecteur)) +
geom_flat_violin(position = position_nudge(x = .2, y = 0), alpha = .5) +
geom_point(aes(y = atsc, color = numlecteur), position = position_jitter(width = .15), size = .5, alpha = 0.8) +
geom_point(data = sumld, aes(x = numlecteur, y = mean), position = position_nudge(x = 0.25), size = 2.5) +
geom_errorbar(data = sumld, aes(ymin = lower, ymax = upper, y = mean), position = position_nudge(x = 0.25), width = 0) +
guides(fill = FALSE) +
guides(color = FALSE) +
scale_color_brewer(palette = "Spectral") +
scale_y_continuous(breaks=c(0,2,4,6,8,10), labels=c("0","2","4","6","8","10"))+
scale_fill_brewer(palette = "Spectral") +
coord_flip() +
theme_bw() +
expand_limits(y=c(0, 10))+
xlab("Lecteur") + ylab("Age total sans check")+
raincloud_theme
I think we can maybe put the "geom_histogram()" but it doesn't work
Thank you in advance for your help !
(sources : https://peerj.com/preprints/27137v1.pdf
https://neuroconscience.wordpress.com/2018/03/15/introducing-raincloud-plots/)
This is actually not quite easy. There are a few challenges.
geom_histogram is "horizontal by nature", and the custom geom_flat_violin is vertical - as are boxplots. Therefore the final call to coord_flip in that tutorial. In order to combine both, I think best is switch x and y, forget about coord_flip, and use ggstance::geom_boxploth instead.
Creating separate histograms for each category is another challenge. My workaround to create facets and "merge them together".
The histograms are scaled way bigger than the width of the points/boxplots. My workaround scale via after_stat function.
How to nudge the histograms to the right position above Boxplot and points - I am converting the discrete scale to a continuous by mapping a constant numeric to the global y aesthetic, and then using the facet labels for discrete labels.
library(tidyverse)
my_data<-read.csv("https://data.bris.ac.uk/datasets/112g2vkxomjoo1l26vjmvnlexj/2016.08.14_AnxietyPaper_Data%20Sheet.csv")
my_datal <-
my_data %>%
pivot_longer(cols = c("AngerUH", "DisgustUH", "FearUH", "HappyUH"), names_to = "EmotionCondition", values_to = "Sensitivity")
# use y = -... to position boxplot and jitterplot below the histogram
ggplot(data = my_datal, aes(x = Sensitivity, y = -.5, fill = EmotionCondition)) +
# after_stat for scaling
geom_histogram(aes(y = after_stat(count/100)), binwidth = .05, alpha = .8) +
# from ggstance
ggstance::geom_boxploth( width = .1, outlier.shape = NA, alpha = 0.5) +
geom_point(aes(color = EmotionCondition), position = position_jitter(width = .15), size = .5, alpha = 0.8) +
# merged those calls to one
guides(fill = FALSE, color = FALSE) +
# scale_y_continuous(breaks = 1, labels = unique(my_datal$EmotionCondition))
scale_color_brewer(palette = "Spectral") +
scale_fill_brewer(palette = "Spectral") +
# facetting, because each histogram needs its own y
# strip position = left to fake discrete labels in continuous scale
facet_wrap(~EmotionCondition, nrow = 4, scales = "free_y" , strip.position = "left") +
# remove all continuous labels from the y axis
theme(axis.title.y = element_blank(), axis.text.y = element_blank(),
axis.ticks.y = element_blank())
Created on 2021-04-15 by the reprex package (v1.0.0)

How to scale a Geom_bar to be in line with an overlaid line graph in R ggplot

I am trying to overlay a bar chart with a line graph on a single plot with ggplot in R. My line graph works fine but the data are much larger than the data for the bar chart component.
How could I use an additional scale for this bar chart or do something that will get this to look nice all in one graph.
Here is my plot code thus far:
chart <- data.frame("QuantileName" = 1:5, "AvgLoss" = c(100, 500, 1000, 2500, 3000), "AvgFactor" = c(1.0, 1.1, 1.3, 1.4, 1.5))
Plot <- ggplot(chart, aes(x = 1:5)) +
scale_x_continuous(name = "Quintile", limits = c(0, 5 + .5), breaks = seq(1, 5)) +
geom_line(aes(y = AvgLoss, colour = "AvgLoss")) +
geom_bar(aes(y = AvgFactor, colour = "AvgFactor" ), stat = "identity") +
geom_text(aes(y = AvgLoss, label = round(AvgLoss)), position = position_nudge(x = .3)) +
geom_point(aes(y = AvgLoss)) +
ylab("AvgLoss") +
scale_colour_manual("",breaks = c("AvgLoss","AvgFactor"), values = c("AvgLoss" = "red", "AvgFactor" = "grey")) +
ggtitle("Quintile Plot") +
theme(plot.title = element_text(hjust=0.5))
Plot
Thank you for any help!
Essentialy, multiply your AvgFactor variable by a number
+ geom_bar(aes(y = AvgFactor*1000, colour = "AvgFactor" ), stat = "identity")
and set
+ scale_y_continuous(sec.axis = sec_axis(~ ./1000, name = "AvgFactor"))
so your plot code would look like
Plot <- ggplot(chart, aes(x = 1:5)) +
scale_x_continuous(name = "Quintile", limits = c(0, 5 + .5),
breaks = seq(1, 5)) +
geom_bar(aes(y = AvgFactor*1000, colour = "AvgFactor" ),
stat = "identity") +
geom_line(aes(y = AvgLoss, colour = "AvgLoss")) +
geom_text(aes(y = AvgLoss,
label = round(AvgLoss)),
position = position_nudge(x = .3)) +
geom_point(aes(y = AvgLoss)) +
ylab("AvgLoss") +
scale_colour_manual("",breaks = c("AvgLoss","AvgFactor"),
values = c("AvgLoss" = "red", "AvgFactor" = "grey")) +
ggtitle("Quintile Plot") +
theme(plot.title = element_text(hjust=0.5)) +
scale_y_continuous(sec.axis = sec_axis(~ ./1000, name = "AvgFactor"))
However, I think it is probably more elegant to avoid secondary axes whenever possible.
It may be useful to know that geom_col(...) is shorthand for geom_bar(..., stat = 'identity')

geom_abline legend - How can I add abline text legend

I'm trying to build charts control. I want to explicit that green line (abline1) is central line and red line (abline2 and abline3) are the limits control.
Can you help me?
library(ggplot2)
amostra <- rnorm(30, 10)
qplot(y = amostra, x = seq_along(amostra), ylim = c(5,15), main = "Gráfico de Controle", xlab = 'Período', ylab = 'Valores') + geom_line() +
geom_abline(aes(slope=0, intercept=10), colour = 'green', size=1) +
geom_abline(aes(slope=0, intercept=7), colour='red', size = 1) +
geom_abline(aes(slope=0, intercept=13), colour='red', size = 1) +
theme(plot.title = element_text(hjust = 0.5))
If you want a legend, then you need an aesthetic mapping. Move color in the aes() and add a scale_color_identity(). You can do this with
qplot(y = amostra, x = seq_along(amostra), ylim = c(5,15), main = "Gráfico de Controle", xlab = 'Período', ylab = 'Valores') + geom_line() +
geom_abline(aes(slope=0, intercept=10, colour = 'green'), size=1) +
geom_abline(aes(slope=0, intercept=7, colour='red'), size = 1) +
geom_abline(aes(slope=0, intercept=13, colour='red'), size = 1) +
theme(plot.title = element_text(hjust = 0.5)) +
scale_color_identity(labels=c("central","limits"), guide="legend")
This is a rather bad hack, but to force the lines to be in the legend, you could try to draw them using the geom_errorbarh() function. This will plot errorbars. If you make them as wide as the plot while setting the plot width explicitly with scale_x_continuous(), you can have horizontal bars that are shown in figure legend.

Lineplot legend + ABLINE ggplot

I have the following ggplot and trying to add the legend and a geom_abline at median.
purple line is for 2013 prods and red is for 2014
This is what I did to generate the plot:
ggplot(prods[Year==2013,], aes(x = Date, y = Prod, group = SOM)) +
geom_line(lwd = 1.3, colour = "purple") +
ylab("Actual Productivity") + theme(axis.title.x=element_blank()) +
geom_line(data=prods[Year==2014,], aes(x = Date, y = Prod, group = SOM),lwd = 1.3, colour = "red") +
geom_abline(data = prods,h=median(Prod))+
scale_color_manual("Period", values = c("purple","red"), labels = c("2013","2014")) +
facet_wrap(~ SOM)
I am not getting any error but there is no legend nor abline is popping up on the image. Plot looks like
this:
any help would be highly appreciated.
regards,
As per aosmith's advice:
I did the following and was able to get the following plot:
ggplot(data=prods,aes(Date)) +
geom_line(data=prods[Year==2013,],aes(y=Prod, colour="red"),lwd = 1.3,) +
geom_line(data=prods[Year==2014,],aes(y=Prod, colour="blue"),lwd = 1.3) +
geom_hline(data=prods, aes(yintercept = median(Prod))) +
scale_colour_manual(name="Period",values=c("blue","red", "black"), labels = c("2014","2013", "Median")) +
ylab("Actual Prod") + xlab(" ") +
theme(axis.title.y = element_text(size = 15, vjust=0.3)) +
facet_wrap(~ SOM)
Plot looks like this:

Resources