Wrong legend in ggplot output - r

The output of this code gives a distribution and two vertical lines, one red and one blue. But in the legend the blue line is marked "red" and vice versa. What might be the reason? Distribution and 2 vertical lines
variances <- apply(matrix(rexp(40*1000,0.2),1000),1,var)
hist(variances)
v_theo <- 45 ## need to define v_theo
g <- ggplot(data.frame(x=variances), aes(x = x))
g <- g + geom_density(alpha=0.2,size=1,fill="red")
g <- g + geom_vline(aes(xintercept = mean(variances),color="red"), size=1)
g <- g + geom_vline(aes(xintercept = (v_theo),color="blue"), size=1)
g

library(ggplot2)
variances <- apply(matrix(rexp(40*1000,0.2),1000),1,var)
hist(variances)
v_theo <- 45
g <- ggplot(data.frame(x=variances), aes(x = x))
g <- g + geom_density(alpha=0.2,size=1,fill="red")
g <- g + geom_vline(aes(xintercept = v_theo, color="blue"), size=1)
g
g <- ggplot(data.frame(x=variances), aes(x = x))
g <- g + geom_density(alpha=0.2,size=1,fill="red")
g <- g + geom_vline(aes(xintercept = mean(variances),color="mean"), size=1)
g <- g + geom_vline(aes(xintercept = v_theo,color="v_theo"), size=1) +
scale_color_manual(name = "Legend name", values = c(mean = "red", v_theo = "blue"))
g
See here as well:
Add legend to geom_vline

That's because the colors are mapped by the aes function. If you want to map them manually, you could either take them out of the aes like this
variances <- apply(matrix(rexp(40*1000,0.2),1000),1,var)
hist(variances)
g <- ggplot(data.frame(x=variances), aes(x = x))
g <- g + geom_density(alpha=0.2,size=1,fill="red")
g <- g + geom_vline(aes(xintercept = mean(variances)), color="red", size=1)
g <- g + geom_vline(aes(xintercept = (v_theo)), color="blue", size=1)
g
You'll lose the legen by doing this though. If you want the legend, you can use scale_color_manual to fix the order of the colors.
variances <- apply(matrix(rexp(40*1000,0.2),1000),1,var)
hist(variances)
g <- ggplot(data.frame(x=variances), aes(x = x))
g <- g + geom_density(alpha=0.2,size=1,fill="red")
g <- g + geom_vline(aes(xintercept = mean(variances),color="red"), size=1)
g <- g + geom_vline(aes(xintercept = (v_theo),color="blue"), size=1)
g <- g + scale_color_manual(values = c("blue", "red"))
g

Related

Why does ggplot2 not show colours in mylegend?

I'm wondering why I don't get colors in my legend:
test=data.frame(a=1:6,b=7:12,c=13:18,d=rep(c("a","b"),each=3))
ggplot() +
geom_line(data=test,aes(y=a,x= b,colour=d,group=d),size=1,alpha=0.5)+
theme(legend.position="bottom") +
xlab("x-axis")
I don't think this has happened before... has it got anything to do with my data?
It's because of your alpha value. You can reset it for the legend like so:
df <- data.frame(a=1:6,b=7:12,c=13:18,d=rep(c("a","b"),each=3))
library(ggplot2)
g <- ggplot()
g <- g + geom_line(data = df, aes(y = a, x = b, colour = d, group = d),
size = 1, alpha = 0.5)
g <- g + theme(legend.position="bottom")
g <- g + xlab("x-axis")
g <- g + guides(colour = guide_legend(override.aes = list(alpha = 1)))
print(g)
Created on 2019-06-24 by the reprex package (v0.3.0)

Plotting multiple densities in ggplot2: How to add an extra variable with a different scale?

I will try to describe my problem using a simplified example. I am trying to plot several densities with ggplot2, something like:
library(reshape2)
library(ggplot2)
set.seed(1)
x <- replicate(5, rnorm(100))
colnames(x) <- paste0("x", 1:5)
ggplot(melt(x), aes(value, color = Var2)) + geom_density()
This works as expected. Now, I would like to add a new variable with a very different scale:
z <- cbind(x, y = rnorm(100) * 50)
ggplot(melt(z), aes(value, color = Var2)) + geom_density()
This produces the expected graph, but not the one I would like to make unfortunately. I would like to keep the original scales of both axes, so that the differences between the first five densities would still be visible, and the density of the new variable would appear as flat.
Is it possible to do this in a simple way? Like telling ggplot to overlay the new density without changing the scaling? Or telling ggplot to ignore a variable when computing the limits of the axes?
I could consider a manual solution that would save the limits of the axes in a first step, and then specify them when the graph is made with the new variable. But that might not be the most elegant solution and might require a lot of extra code. I would prefer avoiding this kind of solution if possible (especially because my case is actually much more complex and implies multiple graphs with facet_wrap())
Any suggestions or hints would be most welcome. Many thanks in advance!
PS: To give you more background information, I am trying to plot several posterior distributions against their prior distribution (the flat one). I only have draws from the prior, not its exact density function - otherwise I would just have overlaid this prior with stat_function().
Here's a cool way to change get a second Y axis:
First let's recreate your chart in a more generalized format. I'm going to create a data frame X (Note: it's Capitalized)
X <- data.frame(x)
g <- ggplot()
g <- g + geom_density(data = X, aes(x1, colour= "X1"))
g <- g + geom_density(data = X, aes(x2, colour= "x2"))
g <- g + geom_density(data = X, aes(x3, colour= "x3"))
g <- g + geom_density(data = X, aes(x3, colour= "x4"))
g
Which produces a the density chart
OK, cool now let's recreate the issue in z you mentioned
Z <- data.frame(z)
g <- ggplot()
g <- g + geom_density(data = Z, aes(x1, colour= "X1"))
g <- g + geom_density(data = Z, aes(x2, colour= "x2"))
g <- g + geom_density(data = Z, aes(x3, colour= "x3"))
g <- g + geom_density(data = Z, aes(x3, colour= "x4"))
g <- g + geom_density(data = Z, aes(x3, colour= "x4"))
g <- g + geom_density(data = Z, aes(y, colour= "y"))
g
Which gives
OK, now here's we can subset a second axis by the difference given in
z <- cbind(x, y = rnorm(100) * 50)
Namely, 50. but you can really make it whatever proportion you would like.
Z <- data.frame(z)
g <- ggplot()
g <- g + geom_density(data = Z, aes(x1, colour= "x1"))
g <- g + geom_density(data = Z, aes(x2, colour= "x2"))
g <- g + geom_density(data = Z, aes(x3, colour= "x3"))
g <- g + geom_density(data = Z, aes(x3, colour= "x4"))
g <- g + geom_density(data = Z, aes(y/50, colour= "y"))
g <- g + scale_y_continuous(sec.axis = sec_axis(~.*50, name= "Y Second Axis"))
g
Which gives us the desired double y axis!
You can also do a double x axis as well.
g <- ggplot()
g <- g + geom_density(data = Z, aes(x1, colour= "x1"))
g <- g + geom_density(data = Z, aes(x2, colour= "x2"))
g <- g + geom_density(data = Z, aes(x3, colour= "x3"))
g <- g + geom_density(data = Z, aes(x3, colour= "x4"))
g <- g + geom_density(data = Z, aes(y/50, colour= "y"))
g <- g + scale_x_continuous(sec.axis = sec_axis(~.*50, name= "x Second Axis"))
g
Hope that helps!
Edit:
After clarification it looks like the desired result would simply to keep the original x-axis limits but to add the new larger density. We can do that both in my style and with the melt format you were using.
g <- ggplot()
g <- g + geom_density(data = Z, aes(x1, colour= "x1"))
g <- g + geom_density(data = Z, aes(x2, colour= "x2"))
g <- g + geom_density(data = Z, aes(x3, colour= "x3"))
g <- g + geom_density(data = Z, aes(x3, colour= "x4"))
g <- g + geom_density(data = Z, aes(y, colour= "y"))
g <- g + xlim(range(-4:4))
g
OR
ggplot(melt(z), aes(value, color = Var2)) + geom_density() + xlim(range(-4, 4)
Edit 2: This gives us a plot with the right axis but it removes values from the density plot (as pointed out by Remek, and a solution in the comments which was correct from Jon Spring). Can we get a plot that leaves the density values unchanged? Yes! we need coord_cartesian() this will also us to preform a 'zoom in' rather than exude values outside of our limits.
Here's the solution in both styles:
g <- ggplot()
g <- g + geom_density(data = Z, aes(x1, colour= "X1"))
g <- g + geom_density(data = Z, aes(x2, colour= "x2"))
g <- g + geom_density(data = Z, aes(x3, colour= "x3"))
g <- g + geom_density(data = Z, aes(x3, colour= "x4"))
g <- g + geom_density(data = Z, aes(x3, colour= "x4"))
g <- g + geom_density(data = Z, aes(y, colour= "y"))
g <- g + coord_cartesian(xlim=c(-4, 4))
g
ggplot(melt(z), aes(value, color = Var2)) + geom_density() + coord_cartesian(xlim=c(-4, 4))
both of which will produce the desired results!
How about using the pre-combined data to specify range?
ggplot(melt(z), aes(value, color = Var2)) +
geom_density() +
coord_cartesian(xlim = c(min(melt(x)$value),
max(melt(x)$value)))
or, we could use the same melt(z) but back out the data with the new variable:
ggplot(melt(z), aes(value, color = Var2)) +
geom_density() +
coord_cartesian(xlim = c(min(subset(melt(z), Var2 != "y")$value),
max(subset(melt(z), Var2 != "y")$value)))

Change facet label text and background colour

How can I change the grey facet labels (A and B) into say red background with white text?
library(data.table)
A = data.table(x = 1:4, y = 1:4, z = c('A','A','B','B'))
ggplot(A) + geom_point(aes(x = x, y = y)) + facet_wrap(~z) + theme_bw()
You can do:
ggplot(A) +
geom_point(aes(x = x, y = y)) +
facet_wrap(~z) +
theme_bw()+
theme(strip.background =element_rect(fill="red"))+
theme(strip.text = element_text(colour = 'white'))
For anyone else looking to change individual facet labels, there's a solution here:
g <- ggplot_gtable(ggplot_build(p))
stripr <- which(grepl('strip-r', g$layout$name))
fills <- c("red","green","blue","yellow")
k <- 1
for (i in stripr) {
j <- which(grepl('rect', g$grobs[[i]]$grobs[[1]]$childrenOrder))
g$grobs[[i]]$grobs[[1]]$children[[j]]$gp$fill <- fills[k]
k <- k+1
}
grid::grid.draw(g)

Add a specific value of x-axis on ggplot

I am using the ggplot function to plot this kind of graph
image
I want to add the specific value of the x-axis as shown in the picture
this is my code :
quantiles <- quantile(mat,prob = quant)
x <- as.vector(mat)
d <- as.data.frame(x=x)
p <- ggplot(data = d,aes(x=x)) + theme_bw() +
geom_histogram(aes(y = ..density..), binwidth=0.001,color="black",fill="white") +
geom_density(aes(x=x, y = ..density..),fill="blue", alpha=0.5, color = 'black')
x.dens <- density(x)
df.dens <- data.frame(x = x.dens$x, y = x.dens$y)
p <- p + geom_area(data = subset(df.dens, x <= quantiles), aes(x=x,y=y),
fill = 'green', alpha=0.6)
print(p)

Set legend according to line colour using ggplot

I have a plot as
Using ggplot, how can I set the legend with two labels only, i.e, red lines with name say "prediction intervals" and blue line with name "fit line"
I used following R lines for this
dfs <- data.frame("x"=1:50,"fit" = rnorm(50,30,4),"upper"=rnorm(50,30,4)+15, "lower"=rnorm(50,30,4)-15)
df_melt <- reshape2::melt(dfs,id="x")
g <- ggplot(df_melt,aes(x=x,y=value,colour=variable)) + geom_line(linetype=5)
g <- g + scale_colour_manual(values=c("blue","red","red"))
g <- g + theme_grey(base_size = 16) + theme(axis.text=element_text(colour = "black",size = 12))
g
You can simply add a new column with 2 values ("prediction intervals" or "fit line")
# Add a new group column
df_melt$group[df_melt$variable == "fit"] <- "fit line"
df_melt$group[df_melt$variable != "fit"] <- "prediction intervals"
# don't forget `group = variable`
g <- ggplot(df_melt, aes(x = x, y = value, colour = group, group = variable)) +
geom_line(linetype=5)
g <- g + scale_colour_manual(values = c("blue" ,"red", "red"))
g <- g + theme_grey(base_size = 16) +
theme(axis.text = element_text(colour = "black", size = 12))
g

Resources