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)
Related
I have a code to plot histogram in R that works fine:
fun_hist <- function(c, E, HS, log_EC_50) {
df <- data.frame(log_c = c, response = V({{c}}, {{E}}, {{HS}}, {{log_EC50}}))
ggplot2::ggplot(df, aes( response)) + geom_histogram(binwidth=0.03)
}
I want to correct my histogram so that its bars have a graphic design as in the attached photo.
This looks pretty similar to my eye:
library(ggplot2)
set.seed(1)
df <- data.frame(response = rnorm(25000, 15, 2))
ggplot(df, aes(response)) +
geom_histogram(binwidth = 0.5, color = 'black', fill = "#547fbf") +
xlim(c(0, 24)) +
labs(x = NULL, y = NULL) +
theme_bw(base_size = 16)
Created on 2022-11-03 with reprex v2.0.2
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
I first make a plot
df <- data.frame(x = c(1:40, rep(1:20, 3), 15:40))
p <- ggplot(df, aes(x=x, y = x)) +
stat_density2d(aes(fill='red',alpha=..level..),geom='polygon', show.legend = F)
Then I want to change the geom_density values and use these in another plot.
# build plot
q <- ggplot_build(p)
# Change density
dens <- q$data[[1]]
dens$y <- dens$y - dens$x
Build the other plot using the changed densities, something like this:
# Built another plot
ggplot(df, aes(x=x, y =1)) +
geom_point(alpha = 0.3) +
geom_density2d(dens)
This does not work however is there a way of doing this?
EDIT: doing it when there are multiple groups:
df <- data.frame(x = c(1:40, rep(1:20, 3), 15:40), group = c(rep('A',40), rep('B',60), rep('C',26)))
p <- ggplot(df, aes(x=x, y = x)) +
stat_density2d(aes(fill=group,alpha=..level..),geom='polygon', show.legend = F)
q <- ggplot_build(p)
dens <- q$data[[1]]
dens$y <- dens$y - dens$x
ggplot(df, aes(x=x, y =1)) +
geom_point(aes(col = group), alpha = 0.3) +
geom_polygon(data = dens, aes(x, y, fill = fill, group = piece, alpha = alpha)) +
scale_alpha_identity() +
guides(fill = F, alpha = F)
Results when applied to my own dataset
Although this is exactly what I'm looking for the fill colors seem not to correspond to the initial colors (linked to A, B and C):
Like this? It is possible to plot a transformation of the shapes plotted by geom_density. But that's not quite the same as manipulating the underlying density...
ggplot(df, aes(x=x, y =1)) +
geom_point(alpha = 0.3) +
geom_polygon(data = dens, aes(x, y, fill = fill, group = piece, alpha = alpha)) +
scale_alpha_identity() +
guides(fill = F, alpha = F)
Edit - OP now has multiple groups. We can plot those with the code below, which produces an artistic plot of questionably utility. It does what you propose, but I would suggest it would be more fruitful to transform the underlying data and summarize that, if you are looking for representative output.
ggplot(df, aes(x=x, y =1)) +
geom_point(aes(col = group), alpha = 0.3) +
geom_polygon(data = dens, aes(x, y, fill = group, group = piece, alpha = alpha)) +
scale_alpha_identity() +
guides(fill = F, alpha = F) +
theme_minimal()
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)))
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