Add legend to manually added lines using ggplot - r

I'm trying to add the corresponding legend for 3 manually added lines using ggplot. My code is the following:
library(ggplot2)
df = data.frame(error = c(0.0832544999, 0.0226680026, 0.0082536264, 0.0049199958, 0.0003917755, 0.0003859976, 0.0003888253, 0.0003953918, 0.0003958398), sDev = c(8.188111e-03, 2.976161e-03, 1.466221e-03, 2.141425e-03, 2.126976e-05, 2.139364e-05, 2.169059e-05, 2.629895e-05, 2.745938e-05))
minimum <- 6
best.model <- 5
gplot <- ggplot(df, aes(x=1:length(error), y=error)) +
scale_x_continuous(breaks = seq_along(df$error)) +
geom_point(size = 3) +
geom_line() +
geom_errorbar(data = df, aes(x = 1:length(error), ymin = error - sDev, ymax = error + sDev),
width = 0.1) +
geom_hline(data = df, aes(yintercept = error[minimum] + sDev[minimum]), linetype = "dashed") +
geom_vline(xintercept = minimum, linetype = "dotted", color = "red", size = 1) +
geom_vline(xintercept = best.model, linetype = "dotted", color = "blue", size = 1) +
theme_gray(base_size = 18) +
theme(axis.text = element_text(color = "black")) +
labs(x = "# of parameters", fontface = "bold") +
labs(y = "CV error") +
labs(title = "Cross-validation error curve")
I'd like to know how to add the legends for the 3 dotted lines in black, red, and blue.
Thanks a lot in advance!

The trick is to use appropriate mapping:
gplot <- ggplot(df, aes(x=1:length(error), y=error)) +
scale_x_continuous(breaks = seq_along(df$error)) +
geom_point(size = 3) +
geom_line() +
geom_errorbar(data = df, aes(x = 1:length(error), ymin = error - sDev, ymax = error + sDev),
width = 0.1) +
geom_hline(data = df, aes(yintercept = error[minimum] + sDev[minimum], linetype="a", colour="a")) +
geom_vline(data= data.frame(type="b", col="b", minimum=minimum),
aes(linetype=type, colour=col, xintercept = minimum), size = 1, show_guide = TRUE) +
geom_vline(data= data.frame(type="b", col="b", best.model=best.model),
aes(linetype="c", colour="c", xintercept = best.model), size = 1, show_guide = TRUE) +
scale_colour_manual(name="Legend", values = c("a" = "black", "b" = "red", "c" = "blue")) +
scale_linetype_manual(name="Legend", values = c("a" = "dashed", "b" = "dotted", "c" = "dotted")) +
theme_gray(base_size = 18) +
theme(axis.text = element_text(color = "black"),
legend.key.height = grid::unit(0.1, "npc")) +
labs(x = "# of parameters", fontface = "bold") +
labs(y = "CV error") +
labs(title = "Cross-validation error curve")

Related

How to put 3rd variable on right axis in Horizontal dots plot?

I have horizontal dots plot visualized by Plotly in R.
My data set contains 3 numerical and 1 categorical variable.
'origin' is on y-axis. 'change' and 'rate' variables are visualized into circles. Now I want to put 'Percentage' variable on right axis in the circles
df <- data.frame (origin = c("A","B","C","D","E","F","G","H","I","J"),
Percentage = c(23,16,32,71,3,60,15,21,44,60),
rate = c(10,12,20,200,-25,12,13,90,-105,23),
change = c(10,12,-5,12,6,8,0.5,-2,5,-2))
library(ggplot2)
ggplot(df, aes(x = rate, y = factor(origin, rev(origin)))) +
geom_hline(aes(yintercept = origin), color = 'gray') +
geom_vline(xintercept = 0, linetype = 2, color = 'gray') +
geom_point(aes(color = 'Rate'), size = 10) +
geom_text(aes(label = rate), color = 'white') +
geom_point(aes(x = change, color = 'Change'), size = 10) +
geom_text(aes(label = change, x = change)) +
theme_minimal(base_size = 16) +
scale_x_continuous(labels = ~paste0(.x, '%'), name = NULL) +
scale_color_manual(values = c('#aac7c4', '#5f9299')) +
theme(panel.grid = element_blank(),
axis.text.y = element_text(color = 'gray50')) +
labs(color = NULL, y = NULL)
Output:
Expected Output:
You could do
ggplot(df, aes(x = rate, y = factor(origin, rev(origin)))) +
geom_hline(aes(yintercept = origin), color = 'gray') +
geom_vline(xintercept = 0, linetype = 2, color = 'gray') +
geom_point(aes(color = 'Rate'), size = 10) +
geom_text(aes(label = rate), color = 'white') +
geom_point(aes(x = change, color = 'Change'), size = 10) +
geom_text(aes(label = change, x = change)) +
geom_point(aes(x = 220, fill = "Percentage"), color = "blue",
size = 12, shape = 21) +
geom_text(aes(x = 220, label = paste0(Percentage, "%"))) +
theme_minimal(base_size = 16) +
scale_x_continuous(labels = ~paste0(.x, '%'), name = NULL) +
scale_color_manual(values = c('#aac7c4', '#5f9299')) +
scale_fill_manual(values = "white", name = NULL) +
theme(panel.grid = element_blank(),
axis.text.y = element_text(color = 'gray50')) +
coord_cartesian(xlim = c(-120, 230), ylim = c(0, 11),
expand = FALSE) +
labs(color = NULL, y = NULL)

How to change the label color of hline in ggplot2

Here is my data:
month=c("Jan","Feb","Mar","Apr","May","Jun")
rate=c(70,80,90,85,88,76)
data=data.frame(month,rate)
data$month=factor(data$month, levels = month.abb)
I created the y label as below:
library(ggplot2)
ggplot(data,aes(x=month,y=rate)) +
geom_point(aes(x=month,y=rate), color="#00BFC4", size=2) +
geom_text(aes(label = paste(format(rate, digits = 4, format = "f"), "%")),
color="black",vjust = -0.5, size = 3.5) +
geom_line(aes(x = month, y = rate, group=1), color="#00BFC4", size=1) +
geom_hline(aes(yintercept=87), color = "#F8766D", linetype = "dashed", size = 0.5) +
scale_y_continuous(breaks = sort(c(seq(0,100,20),87)),
labels = paste0(sort(c(seq(0,100,20),87)),"%")) +
expand_limits(y = c(0,100)) +
labs(y = NULL, x= NULL)
As you can see, the hline label at 87% is in grey color, I'd like to know how to change the color into the "#F8766D" as the same color of the dashed line.
In addition, I'd like to know how to change the position of 87% to the right side of the picture (i.e how to modify the position as a second y axis) and change the label color at the same time. Thanks!
To change the color of hline label as the primary axis:
ylabel=sort(c(seq(0,100,20),87))
color1 <- ifelse(ylabel == 87, "#F8766D", "grey30")
library(ggplot2)
ggplot(data,aes(x=month,y=rate)) +
geom_point(aes(x=month,y=rate), color="#00BFC4", size=2) +
geom_text(aes(label = paste(format(rate, digits = 4, format = "f"), "%")),
color="black",vjust = -0.5, size = 3.5) +
geom_line(aes(x = month, y = rate, group=1), color="#00BFC4", size=1) +
geom_hline(aes(yintercept=87), color = "#F8766D", linetype = "dashed", size = 0.5) +
scale_y_continuous(breaks = sort(c(seq(0,100,20),87)),
labels = paste0(sort(c(seq(0,100,20),87)),"%")) +
expand_limits(y = c(0,100)) +
labs(y = NULL, x= NULL) +
theme(axis.ticks.y = element_line(color = color1),
axis.text.y=element_text(color=color1))
To change the color of hline label as the second axis:
ggplot(data,aes(x=month,y=rate)) +
geom_point(aes(x=month,y=rate), color="#00BFC4", size=2) +
geom_text(aes(label = paste(format(rate, digits = 4, format = "f"), "%")),
color="black",vjust = -0.5, size = 3.5) +
geom_line(aes(x = month, y = rate, group=1), color="#00BFC4", size=1) +
geom_hline(aes(yintercept=87), color = "#F8766D", linetype = "dashed", size = 0.5) +
scale_y_continuous(breaks = seq(0,100,20),
labels = paste0(seq(0,100,20),"%"),
sec.axis = sec_axis(trans=~., breaks=87, labels=paste0(87,"%"))) +
expand_limits(y = c(0,100)) +
labs(y = NULL, x= NULL) +
theme(axis.ticks.y.right = element_line(color = "#F8766D"),
axis.text.y.right = element_text(color = "#F8766D"))

How to add the legend for hline in ggplot2

My data looks like this:
month=c("Jan","Feb","Mar","Apr","May","Jun")
rate=c(70,80,90,85,88,76)
dd=data.frame(month,rate)
dd$type="Rate"
dd$month=factor(dd$month)
I tried to create the plot like this:
ggplot(dd,aes(x=month,y=rate,color=type)) +
geom_point(aes(x=month,y=rate, group=1), size=2) +
geom_text(aes(label = paste(format(rate, digits = 4, format = "f"), "%")),
color="black",vjust = -0.5, size = 3.5) +
geom_line(aes(x = month, y = rate, group=1), size=1) +
geom_hline(aes(yintercept=85), linetype='dashed',colour="#F8766D", show.legend=T) +
labs(y="", x="") +
scale_colour_manual(values = c("#00BFC4")) +
scale_fill_discrete(limits = c("Target")) +
theme(legend.position="bottom") +
theme(legend.title = element_blank())
As you can see, the legend of Rate and Target are overlapping together (there is red dash line in the green line), I'd like to know how to create the legend for Target and Rate in the correct way. Thanks!
One option to achieve your desired result would be to map on aesthetics and make use of scale_xxx_manual instead of setting the color, linetypes, ... via arguments:
month=c("Jan","Feb","Mar","Apr","May","Jun")
rate=c(70,80,90,85,88,76)
dd=data.frame(month,rate)
dd$type="Rate"
dd$month=factor(dd$month)
library(ggplot2)
ggplot(dd,aes(x=month,y=rate, color="Rate", linetype = "Rate")) +
geom_point(aes(x=month,y=rate, shape = "Rate"), size=2) +
geom_text(aes(label = paste(format(rate, digits = 4, format = "f"), "%")),
color="black",vjust = -0.5, size = 3.5) +
geom_line(aes(x = month, y = rate, group=1, size = "Rate")) +
geom_hline(aes(yintercept=85, color = "Target", linetype = "Target", size = "Target")) +
labs(y = NULL, x= NULL, color = NULL, linetype = NULL, shape = NULL, size = NULL) +
scale_colour_manual(values = c(Rate = "#00BFC4", Target = "#F8766D")) +
scale_linetype_manual(values = c(Rate = "solid", Target = "dashed")) +
scale_shape_manual(values = c(Rate = 16, Target = NA)) +
scale_size_manual(values = c(Rate = 1, Target = .5)) +
theme(legend.position="bottom")

Customize lines in ggplot linegraph with multiple lines

I build this graph:
labels.minor <- c("nie","selten","manchmal", "mehrmals", "oft", "sehr oft", "immerzu")
df_ebf <- df_ebf %>%
map_df(rev)
ggplot(data=df_ebf, aes(x=forcats::fct_inorder(Skalen), y=Werte, group="")) +
geom_line(aes(y = Werte, color = "#003560")) +
geom_line(aes(y = SD_plus, color = "#8DAE10", linetype = "dashed")) +
geom_line(aes(y = SD_minus, color = "#8DAE10",linetype = "dashed")) +
geom_point(color = "#003560") +
coord_flip() +
labs(x="EBF-Skalen") +
scale_y_continuous(limits = c(0, 6), breaks = c(0,1,2,3,4,5,6), labels = paste0(0:6, "\n", labels.minor), sec.axis = sec_axis(~.x, breaks = 0:6)) +
scale_x_discrete(expand = c(0,0)) +
theme(panel.grid.major.y = element_blank(),panel.grid.minor.x = element_blank(),axis.line.x = element_line(size = 1, colour = "black", linetype=1),axis.title=element_blank())
But instead of changing the style of the lines, the styling just appears in the legend.
take them out of the aes:
aes(...), color="..", linetype=".."

How to draw three differents non-linear regression with ggplot2

I am trying to draw three differents non-linear regression with ggplot2 (like I did with graphpad below (dotted line) (because graphpad can't compare non-linear regression between groups):
So far, I drew this graph:
With the following code:
gp <- ggplot(datapoidsmono, aes(x = time, y = weight)) +
stat_summary(aes(color = group), fun.data="mean_sdl", fun.args = list(mult=1), geom="errorbar", position = "identity", size=0.5, width=0.2) +
stat_summary(fun.y = "mean", geom = "point", size=3, aes(shape=group,color=group)) +
scale_x_discrete(name = "Days after injection") +
scale_y_continuous(name = "Weight (g)", limits=c(0, 4000), breaks = seq(0, 4000,500)) +
scale_color_manual(values=c("green", "blue", "red"), name="Treatment", labels=c("A","B","C")) +
scale_shape_manual(values=c(15,16,17), name ="Treatment", labels=c("A", "B", "C")) +
ggtitle("Weight variation over time") + theme(plot.title = element_text(hjust = 0.5)) +
theme(legend.position = "right") +
theme(legend.background = element_rect(size=0.5, linetype="solid", color ="black", fill="white")) +
theme(axis.line.x = element_line(size = 0.5, color = "black"),axis.text.x = element_text(color="black", size = 12),axis.line.y = element_line(size = 0.5, color = "black"),axis.text.y = element_text(color="black", size = 12),axis.title = element_text(size =15, face="bold"),plot.title = element_text(size =20, face = "bold"),panel.grid.major = element_line(color = "#F1F1F1"),panel.grid.minor = element_blank(), panel.background = element_blank())
I can't figure out how to draw a non-linear regression for each groups.
The following code did not return any drawn line (no error either):
ggplot(datapoidsmono, aes(time, weight, color = group)) +
geom_point() +
stat_smooth(method = "lm", se=FALSE)
Nor did this one (found here):
ggplot(datapoidsmono, aes(x = time, y = weight, colour=group)) +
stat_smooth(method = 'nls', formula = 'y~a*exp(b*x)') +
stat_smooth(color = 1, method = 'nls', formula = 'y~a*exp(b*x)') +
geom_point(aes(fill=group))
Any idea or clue would be useful to continue! Thanks
Update
As suggested by #PoGibas, I added "group=group" in aes inside first line which worked pefectly to draw the lines!
I tried mulltiple solution to get the perfect fit:
gp + ggplot(aes(group=group))
stat_smooth(method = "lm", formula = y ~ x, size = 1, se = FALSE,colour = "black") +
stat_smooth(method = "lm", formula = y ~ x + I(x^2),size = 1, se = FALSE, colour = "blue") +
stat_smooth(method = "loess", formula = y ~ x, size = 1, se = FALSE, colour = "red") +
stat_smooth(method = "gam", formula = y ~ s(x), size = 1, se = FALSE, colour = "green") +
stat_smooth(method = "gam", formula = y ~ s(x, k = 3), size = 1, se = FALSE, colour = "violet") +
stat_smooth(method = "auto", se=F, colour = "yellow")
But I figured that simply gp + stat_smooth() did perfectly the job (the LOESS method is used).
Now I am trying to change aspect (to a dotted line) and color of the fit...
I tryed gp + stat_smooth(se=F, aes(fill = group)) but now I have another legend box and my lines are always with the same color...
I also tryed to add linetype=group in the aes, but when I use scale_linetype_manual(values=c("dotted", "dotted", "dotted")), every line is dotted (included errorbar)
The complete code is:
ggplot(datapoidsmono, aes(x = time, y = weight, group=group, linetype=group)) +
stat_summary(aes(color = group), fun.data="mean_sdl", fun.args = list(mult=1), geom="errorbar", position = "identity", size=0.5, width=0.2) +
stat_summary(fun.y = "mean", geom = "point", size=3, aes(shape=group,color=group)) +
scale_x_discrete(name = "Days after injection") +
scale_y_continuous(name = "Weight (g)", limits=c(0, 4000), breaks = seq(0, 4000,500)) +
scale_color_manual(values=c("green", "blue", "red"), name="Treatment", labels=c("A","B","C")) +
scale_shape_manual(values=c(15,16,17), name ="Treatment", labels=c("A", "B", "C")) +
ggtitle("Weight variation over time") + theme(plot.title = element_text(hjust = 0.5)) +
theme(legend.position = "right") +
theme(legend.background = element_rect(size=0.5, linetype="solid", color ="black", fill="white")) +
theme(axis.line.x = element_line(size = 0.5, color = "black"),axis.text.x = element_text(color="black", size = 12),axis.line.y = element_line(size = 0.5, color = "black"),axis.text.y = element_text(color="black", size = 12),axis.title = element_text(size =15, face="bold"),plot.title = element_text(size =20, face = "bold"),panel.grid.major = element_line(color = "#F1F1F1"),panel.grid.minor = element_blank(), panel.background = element_blank()) +
stat_smooth(se=F, aes(fill = group)) +
scale_linetype_manual(values=c("dotted", "dotted", "dotted"))
Thanks to #PoGibas and this post, I added
group=group, color=group in the aes of ggplot and it gave me a good result.
ggplot(datapoidsmono, aes(x = time, y = weight, group=group, color=group)) +
stat_summary(aes(color = group), fun.data="mean_sdl", fun.args = list(mult=1), geom="errorbar", position = "identity", size=0.5, width=0.2) +
stat_summary(fun.y = "mean", geom = "point", size=3, aes(shape=group,color=group)) +
scale_x_discrete(name = "Days after injection") +
scale_y_continuous(name = "Weight (g)", limits=c(0, 4000), breaks = seq(0, 4000,500)) +
scale_color_manual(values=c("green", "blue", "red"), name="Treatment", labels=c("A","B","C")) +
scale_shape_manual(values=c(15,16,17), name ="Treatment", labels=c("A", "B", "C")) +
ggtitle("Weight variation over time") + theme(plot.title = element_text(hjust = 0.5)) +
theme(legend.position = "right") +
theme(legend.background = element_rect(size=0.5, linetype="solid", color ="black", fill="white")) +
theme(axis.line.x = element_line(size = 0.5, color = "black"),axis.text.x = element_text(color="black", size = 12),axis.line.y = element_line(size = 0.5, color = "black"),axis.text.y = element_text(color="black", size = 12),axis.title = element_text(size =15, face="bold"),plot.title = element_text(size =20, face = "bold"),panel.grid.major = element_line(color = "#F1F1F1"),panel.grid.minor = element_blank(), panel.background = element_blank()) +
stat_smooth(se=F, linetype="dotted")
Here is the final graph:
NB: the fit proposed by graphpad (see first graph) is more stat_smooth(method = "lm", formula = y ~ x + I(x^2),size = 1, se = FALSE) than the one I finally chose (LOESS)

Resources