I would like to manually adjust the legend in my plot I'm making with ggplot as well as add two new items to the legend. Right now the legend appears as legend title - factor(CruiseID), followed by a red circle with the text 201905 and then a blue circle with the text 201906 even though I have the scale_fill_manual code in the code.
I would like to have no legend title, followed by red circle and text 2019 MAB Leg 1, blue circle and text 2019 MAB Leg 2, gray box and text Survey Domain white box with black outline and text Access Area
example data
data<-data.frame(CruiseID=c(rep(201905,5),rep(201906,5)),
beglat=c(36.66,36.66,37.07,37.01,37.03,37.033,37.08,37.09,37.07,37.077),
beglong=c(-74.75,-74.75,-74.73,
-74.731,-74.90,-74.90,-74.88,-74.88,
-74.72,-74.72))
ggplot() +
geom_point(data = data, aes(x = beglong, y = beglat,colour=factor(CruiseID))) +
scale_colour_manual(values = c("red", "blue"),drop=T)+
xlim(-76,-71)+
ylim(36,42)+
ggtitle("2019 MAB Survey Stations") +
labs(x = "Longitude", y = "Latitude") +
scale_fill_manual(values = c("red", "blue","gray87","black"),
labels = c('Leg 1', 'MAB Leg 2','Survey Domain','Access Area'))+
theme_bw()+
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
plot.title=element_text(size=14),
text=element_text(size=12),
axis.text.x=element_text(colour="black", size = 12),
axis.text.y=element_text(colour="black", size = 12),
legend.justification=c(.5,.5),
legend.background = element_rect(fill = "white", color = NA),
legend.position=c(0.8, 0.3),legend.box="vertical",
legend.margin=margin())
Here's a solution that uses ggnewscale::new_scale_color
to create two scales for the color, one for the points and another one for the boxes. Additionally, I created an additional data.frame named df to plot 2 rectangles using geom_rect
and create the legend for the boxes.
library(ggplot2)
library(ggnewscale)
# Create another data frame to plot the rectangles and its legend
df <- data.frame (xmin = c(0,0),
xmax = c(0,0),
ymin = c(0,0),
ymax = c(0,0),
fill = c("A","B"))
ggplot() +
geom_point(data = data, aes(x = beglong,
y = beglat,
colour=factor(CruiseID))) +
# Move the color scale for the points before setting a new scale color
scale_color_manual(values = c("red", "blue"),
labels = c('2019 MAB Leg 1', '2019 MAB Leg 2'))+
# Set new scale color
new_scale_color() +
# plot rectangles in 0,0; where they will not appear in the plot's area
geom_rect(data = df,aes(xmin = xmin,
xmax = xmax,
ymin = ymin,
ymax = ymax,
fill = fill,
col = fill)) +
# Manually set color for the boxes
scale_color_manual(values = c("white","black"),
labels = c('Survey Domain', 'Access Area')) +
# Manually set fill for the boxes, use same labels as color so the box legends are combined
scale_fill_manual(values = c("gray87","white"),
labels = c('Survey Domain', 'Access Area'))+
xlim(-76,-71)+
ylim(36,42)+
ggtitle("2019 MAB Survey Stations") +
labs(x = "Longitude", y = "Latitude") +
theme_bw()+
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
plot.title=element_text(size=14),
text=element_text(size=12),
axis.text.x=element_text(colour="black", size = 12),
axis.text.y=element_text(colour="black", size = 12),
legend.justification=c(.5,.5),
# Remove legend title
legend.title = element_blank(),
legend.background = element_rect(fill = "white", color = NA),
legend.position=c(0.8, 0.3),legend.box="vertical",
legend.margin=margin())
Up front, @RuiBarradas's comment about scale_fill_manual
is both correct and misled from your code. I believe you included it with the expectation of adding your areas (survey and access) later. Perhaps you thought that it could have an effect on your color legend (or just confused them). Regardless, his point is correct: scale_fill_manual
here does nothing unless you actually use fill=
as an aes
thetic somewhere in the plot. All of the naming and such would have to be done in scale_color_manual
for your dots.
Further, you have two options for setting your labels. I believe you can use labels=
in your scale calls to set them, and this can be a named vector of c("201905" = "MAB Leg 1", ...)
. Or you can use the labels initially in the aesthetic (as I do below). They both work, but the former requires a little more data-management without ggplot.
I suggest a slightly different data organization.
Since you don't want to show the 201905
(etc) numbers, yet you want to assign labels and colors on them, I'll create a labels
frame that maps them together, and then I'll merge
them in.
Since you have scale_fill_manual
yet have assigned no fill=
aesthetics, I'll create a fake areas
frame that contains your two types of area. I'll assign them arbitrary CruiseID
values so that we can still use the labels
frame to identify them (and their fill as well).
labels <- data.frame(
CruiseID = c(201905, 201906, -1, -2),
# 'factor' to preserve the order
label = factor(c("MAB Leg 1", "MAB Leg 2", "Survey Domain", "Access Area")),
color = c("red", "blue", "#00000000", "black"),
fill = c("#00000000", "#00000000", "gray", "white")
)
areas <- data.frame(
label = c(-1, -2),
beglat = NA_real_, beglong = NA_real_)
Next, the values=
value of the scale_*_manual
functions can work with a named vector. I'll re-use labels
for this, using a small trick to turn two columns into a named vector:
labels
# CruiseID label color fill
# 1 201905 MAB Leg 1 red #00000000
# 2 201906 MAB Leg 2 blue #00000000
# 3 -1 Survey Domain #00000000 gray
# 4 -2 Access Area black white
setNames(labels$color, labels$label)
# MAB Leg 1 MAB Leg 2 Survey Domain Access Area
# "red" "blue" "#00000000" "black"
For removing the legend titles, merely add name=NULL
to the applicable scale_
calls.
The code:
ggplot() +
geom_point( # UPDATED
data = merge(data, labels, by = "CruiseID", all.x = TRUE),
aes(x = beglong, y = beglat, colour = label)) +
scale_colour_manual( # UPDATED
name = NULL,
values = setNames(labels$color, labels$label),
drop = TRUE) +
geom_polygon( # NEW, placeholder
data = merge(areas, labels, by = "CruiseID", all.x = TRUE),
aes(x = beglong, y = beglat, fill = label),
na.rm = TRUE) +
scale_fill_manual( # UPDATED
name = NULL,
values = setNames(labels$fill, labels$label),
drop = TRUE) +
xlim(-76,-71) +
ylim(36,42) +
ggtitle("2019 MAB Survey Stations") +
labs(x = "Longitude", y = "Latitude") +
theme_bw() +
theme(
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
plot.title=element_text(size=14),
text=element_text(size=12),
axis.text.x=element_text(colour="black", size = 12),
axis.text.y=element_text(colour="black", size = 12),
legend.justification=c(.5,.5),
legend.background = element_rect(fill = "white", color = NA),
legend.position=c(0.8, 0.3),legend.box="vertical",
legend.margin=margin(),
legend.key = element_rect(colour = "black") # NEW
)
Finally, without editing the grob ( gr
aphic ob
ject) and/or graphic-table manually, I don't think there's a way to box in the colors of one legend and not the other: the theme option legend.key
allows us to box them in, but it applies to all legends. If you don't mind the boxes around the dots, you're good. If you can't have them, then you can remove the legend.key=
option and change your "Access Area" from white to something different than the background color, so that it is visible.
labels <- data.frame(
CruiseID = c(201905, 201906, -1, -2),
# 'factor' to preserve the order
label = factor(c("MAB Leg 1", "MAB Leg 2", "Survey Domain", "Access Area")),
color = c("red", "blue", "#00000000", "black"),
fill = c("#00000000", "#00000000", "gray", "gray90")
)
ggplot() +
geom_point( # UPDATED
data = merge(data, labels, by = "CruiseID", all.x = TRUE),
aes(x = beglong, y = beglat, colour = label)) +
scale_colour_manual( # UPDATED
name = NULL,
values = setNames(labels$color, labels$label),
drop = TRUE) +
geom_polygon( # NEW, placeholder
data = merge(areas, labels, by = "CruiseID", all.x = TRUE),
aes(x = beglong, y = beglat, fill = label),
na.rm = TRUE) +
scale_fill_manual( # UPDATED
name = NULL,
values = setNames(labels$fill, labels$label),
drop = TRUE) +
xlim(-76,-71) +
ylim(36,42) +
ggtitle("2019 MAB Survey Stations") +
labs(x = "Longitude", y = "Latitude") +
theme_bw() +
theme(
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
plot.title=element_text(size=14),
text=element_text(size=12),
axis.text.x=element_text(colour="black", size = 12),
axis.text.y=element_text(colour="black", size = 12),
legend.justification=c(.5,.5),
legend.background = element_rect(fill = "white", color = NA),
legend.position=c(0.8, 0.3),legend.box="vertical",
legend.margin=margin()
)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.