I have a plot like this:
library("ggplot2")
library("ggtext")
df = data.frame(x = rnorm(n=12), y = rnorm(n=12),
groupshape = rep(c("a","b","c"), 4),
groupcol = rep(c("e","d","f"), 4))
p = ggplot(df, aes(x = x,y = y,
shape = groupshape,
color = groupcol)) +
geom_point() + theme_classic() + labs(shape = "shape", color = "color")
Producing a plot like this:
But I want to know how to get something like this with the legend:
How would I do that? I can get rid of the shape itself through guides by turning them all while, but then the text just hovers menacingly without alignment to the legend below.
This could be achieved via the label.position and the label.theme arguments of guide_legend:
library("ggplot2")
library("ggtext")
df = data.frame(x = rnorm(n=12), y = rnorm(n=12),
groupshape = rep(c("a","b","c"), 4),
groupcol = rep(c("e","d","f"), 4))
ggplot(df, aes(x = x,y = y,
shape = groupshape,
color = groupcol)) +
geom_point() + theme_classic() + labs(shape = "shape", color = "color") +
guides(color = guide_legend(label.position = "left", label.theme = element_text(face = "bold")),
shape = guide_legend(label.position = "left"))
Related
I am creating a plot that has 2 legends using both ggplot2 and ggnewscale. What I'm trying to achieve is to fix the order of the separate legends so they always appear in the same order. The images and code below show a basic example of the issue I'm having.
First, create some data and set the colour palettes:
df <- data.frame(x = c(1:5), y = runif(10))
df_1 <- data.frame(x = c(1:5), y = runif(10))
pal_1 = rev(colorspace::sequential_hcl(palette = "Blues 3", n = 10))
pal_2 = rev(colorspace::sequential_hcl(palette = "Reds 3", n = 10))
Now create a plot (note the limits I set are between 0 and 1 for the legends):
library(ggplot2)
library(ggnewscale)
ggplot(df, mapping = aes(x, y)) +
geom_point(size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_1, limits = c(0,1), name = "val1") +
new_scale_fill() +
geom_point(data = df_1, size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_2, limits = c(0,1), name = "val2")
This will result in the following image (note that the legend for val1 is on the top):
Now, if we change the limits for val2 to something larger, like so:
ggplot(df, mapping = aes(x, y)) +
geom_point(size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_1, limits = c(0,1), name = "val1") +
new_scale_fill() +
geom_point(data = df_1, size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_2, limits = c(0,10), name = "val2")
We will get this (note that val2 legend is now on top:
It seems that ggplot will put the legend with the larger limit range on the top. I was wonder if there was a way to fix the legend order so that, say val1 is always on the top... no matter the range of the limits?
You could specify the order of the legends via the order argument of guide_xxx:
df <- data.frame(x = c(1:5), y = runif(10))
df_1 <- data.frame(x = c(1:5), y = runif(10))
pal_1 = rev(colorspace::sequential_hcl(palette = "Blues 3", n = 10))
pal_2 = rev(colorspace::sequential_hcl(palette = "Reds 3", n = 10))
library(ggplot2)
library(ggnewscale)
ggplot(df, mapping = aes(x, y)) +
geom_point(size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_1, limits = c(0,1), name = "val1",
guide = guide_colorbar(order = 1)) +
new_scale_fill() +
geom_point(data = df_1, size = 3, aes(fill = y)) +
scale_fill_gradientn(colors = pal_2, limits = c(0,10), name = "val2",
guide = guide_colorbar(order = 2))
I would like to have the annotation on the very first facet of the following ggplot. right now, the code draws annotation on all facets. Anyway forward would be appreciate.
library(ggplot2)
library(lubridate)
set.seed(123)
DF <- data.frame(Date = seq(as.Date("2001-01-01"), to = as.Date("2005-12-31"), by = "1 month"),
Ob = runif(60,1,5), L95 =runif(60, 0,4), U95 = runif(60,2,7), Sim = runif(60,1,5)) %>%
pivot_longer(names_to = "Variable", values_to = "Value", -Date)
ggplot(data = DF, aes(x = Date))+
geom_line(aes(y = Value))+
facet_wrap(~ Variable, scales = "free_y", nrow = 4)+
geom_vline(xintercept = as.Date("2004-12-01"),color = "red", size = 1.30)+
annotate(geom = "text", x = as.Date("2002-01-01"), y = 3, label = "Calibration")+
annotate(geom = "text", x = as.Date("2005-06-01"), y = 3, label = "Validation")
You can do this with geom_text. Create a separate dataframe for plotting.
library(ggplot2)
text_data <- data.frame(x = as.Date(c("2002-01-01", "2005-06-01")),
y = 3.5, Variable = sort(unique(DF$Variable))[1],
label = c("Calibration", "Validation"))
ggplot(data = DF, aes(x = Date))+
geom_line(aes(y = Value))+
facet_wrap(~ Variable, scales = "free_y", nrow = 4)+
geom_vline(xintercept = as.Date("2004-12-01"),color = "red", size = 1.30) +
geom_text(data = text_data, aes(x, y, label = label), color = 'blue')
You can try something like this wrapping data coordinates for the value on top of facets using geom_text():
library(ggplot2)
library(lubridate)
#Code
ggplot(data = DF, aes(x = Date))+
geom_line(aes(y = Value,group=Variable))+
facet_wrap(~ Variable, scales = "free_y", nrow = 4)+
geom_vline(xintercept = as.Date("2004-12-01"),color = "red", size = 1.30)+
geom_text(data=data.frame(Variable='L95',Date=as.Date("2002-01-01"),
label="Calibration",Value=max(DF$Value)),
aes(y=Value,label=label))+
geom_text(data=data.frame(Variable='L95',Date=as.Date("2005-06-01"),
label="Validation",Value=max(DF$Value)),
aes(y=Value,label=label))
Output:
Steeling the example of this question (Link), I want to ask if it is possible to add the additional blue point to the legend?
dat <- data.frame(cond = rep(c("A", "B"), each=10),
xvar = 1:20 + rnorm(20,sd=3),
yvar = 1:20 + rnorm(20,sd=3))
g1 <- dat[15,]
ggplot(dat, aes(x = xvar, y = yvar, shape = cond,
colour = cond), size = 2.5) +
geom_point(alpha = 1) +
geom_point(data = g1, colour = "blue", size = 4, show_guide = FALSE)
You can put the aesthetics for the additional points layer inside aes instead of outside to get it added to the legend. You can use any string value; that string will be the name in the legend.
Then you can control the color and shape of that point via scale_*_manual layers.
I additionally changed the size of that point in the legend using override.aes, which is optional.
ggplot(dat, aes(x = xvar, y = yvar, shape = cond,
colour = cond), size = 2.5) +
geom_point(alpha = 1) +
geom_point(data = g1, aes(colour = "Point 15", shape = "Point 15"), size = 4) +
scale_shape_manual(values = c(16, 17, 17) ) +
scale_color_manual(values = c("pink", "turquoise", "blue") ) +
guides(color = guide_legend( override.aes = list(size = c(1.5, 1.5, 4) ) ) )
You probably have to change the condition of that point in the data as in your example or add it to the date, if it is not already part of it.
dat <- data.frame(cond = rep(c("A", "B"), each=10),
xvar = 1:20 + rnorm(20,sd=3),
yvar = 1:20 + rnorm(20,sd=3))
dat$size = 2.5
dat[15,]$cond = "C"
dat$cond = as.character(dat$cond)
dat[15,]$size = 4
ggplot(dat, aes(x = xvar, y = yvar, shape = cond,
colour = cond, size=size)) +
geom_point(alpha = 1) +
scale_colour_manual(values=c("red", "turquoise", "blue")) +
scale_size_continuous(guide = FALSE)
I am doing a plot of densities, I want to add a legend but is overlapped with the symbol. The code is hereunder:
dfGamma = data.frame(a = rgamma(100,shape = 7.1,rate= 0.0055),
b = rgamma(100, shape = 10,rate= 0.0055),
c = rgamma(100, shape = 7.1,rate= 0.0055))
dfGamma = stack(dfGamma)
p <- ggplot(dfGamma, aes(x = values)) +
stat_density(aes(group = ind, colour = ind),position="identity",geom="line",size=1)+
ggtitle("Gamma distribution")+theme(legend.position="right")+
scale_color_manual(labels = c(expression(paste(alpha,"=7.1 ",beta,"=0.0055")),
expression(paste(alpha,"= 10 ",beta,"=0.0055")),
expression(paste(alpha,"=7.1 ",beta,"=0.0055"))),
values = c('red', 'blue',"green"))
p
the plot is:
The guides option, guide_legend is what you need. You can read more about it in the ggplot reference. Does this help?
p <- ggplot(dfGamma, aes(x = values)) +
stat_density(aes(group = ind, colour = ind),position="identity",geom="line",size=1)+
ggtitle("Gamma distribution")+
theme(legend.position="right") +
scale_color_manual(labels = c(expression(paste(alpha, "=7.1 ", beta, "=0.0055")),
expression(paste(alpha,"= 10 ",beta,"=0.0055")),
expression(paste(alpha,"=7.1 ",beta,"=0.0055"))),
values = c('red', 'blue',"green")) +
guides(colour = guide_legend(label.position = "bottom"))
p
I use bars and line to create my plot. The demo code is:
timestamp <- seq(as.Date('2010-01-01'),as.Date('2011-12-01'),by="1 mon")
data1 <- rnorm(length(timestamp), 3000, 30)
data2 <- rnorm(length(timestamp), 30, 3)
df <- data.frame(timestamp, data1, data2)
p <- ggplot()
p <- p + geom_histogram(data=df,aes(timestamp,data1),colour="black",stat="Identity",bindwidth=10)
p <- p + geom_line(data=df,aes(timestamp,y=data2*150),colour="red")
p <- p + scale_y_continuous(sec.axis = sec_axis(~./150, name = "data2"))
p <- p + scale_colour_manual(name="Parameter", labels=c("data1", "data2"), values = c('black', 'red'))
p <- p+ scale_shape_manual(name="Parameter", labels=c("data1", "data2"), values = c(15,95))
p
This results in a plot like this:
This figure does not have a legend. I followed this answer to create a customized legend but it is not working in my case. I want a square and line shape in my legend corresponding to bars and line. How can we get it?
I want legend as shown in below image:
For the type of data you want to display, geom_bar is a better fit then geom_histogram. When you to manipulate the appaerance of the legend(s), you need to place the colour = ... parts inside the aes. To get the desired result it probably best to use different types of legend for the line and the bars. In that way you are better able to change the appearance of the legends with guide_legend and override.aes.
A proposal for your problem:
ggplot(data = df) +
geom_bar(aes(x = timestamp, y = data1, colour = "black"),
stat = "Identity", fill = NA) +
geom_line(aes(x = timestamp, y = data2*150, linetype = "red"), colour = "red", size = 1) +
scale_y_continuous(sec.axis = sec_axis(~./150, name = "data2")) +
scale_linetype_manual(labels = "data2", values = "solid") +
scale_colour_manual(name = "Parameter\n", labels = "data1", values = "black") +
guides(colour = guide_legend(override.aes = list(colour = "black", size = 1),
order = 1),
linetype = guide_legend(title = NULL,
override.aes = list(linetype = "solid",
colour = "red",
size = 1),
order = 2)) +
theme_minimal() +
theme(legend.key = element_rect(fill = "white", colour = NA),
legend.spacing = unit(0, "lines"))
which gives: