'How ggplot2 seperate the legend of line and point and seperate the color manual of line and point?
I'm trying to plot a graph using ggplot2. And I'm having trouble with the several problems:
- I want to separate the legend of point and line
- I want to manually add color of the line and the point, if I use
scale_colour_manualfunction, I found it can not separate the legend of line and point.
My data is
sec_dt <- data.table::data.table(
DATE = c("2021/10/11","2021/10/12","2021/10/13",
"2021/10/14","2021/10/15","2021/10/18","2021/10/19",
"2021/10/20","2021/10/21","2021/10/22","2021/10/25","2021/10/26",
"2021/10/27","2021/10/28","2021/10/29","2021/10/31",
"2021/11/1","2021/11/2","2021/11/3","2021/11/4","2021/11/5",
"2021/11/8","2021/10/11","2021/10/12","2021/10/13","2021/10/14",
"2021/10/15","2021/10/18","2021/10/19","2021/10/20",
"2021/10/21","2021/10/22","2021/10/25","2021/10/26","2021/10/27",
"2021/10/28","2021/10/29","2021/10/31","2021/11/1",
"2021/11/2","2021/11/3","2021/11/4","2021/11/5","2021/11/8",
"2021/10/11","2021/10/12","2021/10/13","2021/10/14","2021/10/15",
"2021/10/18","2021/10/19","2021/10/20","2021/10/21",
"2021/10/22","2021/10/25","2021/10/26","2021/10/27","2021/10/28",
"2021/10/29","2021/10/31","2021/11/1","2021/11/2",
"2021/11/3","2021/11/4","2021/11/5","2021/11/8","2021/10/11",
"2021/10/12","2021/10/13","2021/10/14","2021/10/15","2021/10/18",
"2021/10/19","2021/10/20","2021/10/21","2021/10/22",
"2021/10/25","2021/10/26","2021/10/27","2021/10/28","2021/10/29",
"2021/10/31","2021/11/1","2021/11/2","2021/11/3",
"2021/11/4","2021/11/5","2021/11/8"),
LINE = c("QUANTITY","QUANTITY","QUANTITY",
"QUANTITY","QUANTITY","QUANTITY","QUANTITY","QUANTITY","QUANTITY",
"QUANTITY","QUANTITY","QUANTITY","QUANTITY","QUANTITY",
"QUANTITY","QUANTITY","QUANTITY","QUANTITY","QUANTITY",
"QUANTITY","QUANTITY","QUANTITY","PRICE","PRICE","PRICE",
"PRICE","PRICE","PRICE","PRICE","PRICE","PRICE","PRICE",
"PRICE","PRICE","PRICE","PRICE","PRICE","PRICE","PRICE",
"PRICE","PRICE","PRICE","PRICE","PRICE","BUY_POINT",
"BUY_POINT","BUY_POINT","BUY_POINT","BUY_POINT","BUY_POINT",
"BUY_POINT","BUY_POINT","BUY_POINT","BUY_POINT","BUY_POINT",
"BUY_POINT","BUY_POINT","BUY_POINT","BUY_POINT","BUY_POINT",
"BUY_POINT","BUY_POINT","BUY_POINT","BUY_POINT","BUY_POINT",
"BUY_POINT","SELL_POINT","SELL_POINT","SELL_POINT",
"SELL_POINT","SELL_POINT","SELL_POINT","SELL_POINT","SELL_POINT",
"SELL_POINT","SELL_POINT","SELL_POINT","SELL_POINT",
"SELL_POINT","SELL_POINT","SELL_POINT","SELL_POINT","SELL_POINT",
"SELL_POINT","SELL_POINT","SELL_POINT","SELL_POINT",
"SELL_POINT"),
POINT = c("QUANTITY","QUANTITY","QUANTITY",
"QUANTITY","QUANTITY","QUANTITY","QUANTITY","QUANTITY","QUANTITY",
"QUANTITY","QUANTITY","QUANTITY","QUANTITY","QUANTITY",
"QUANTITY","QUANTITY","QUANTITY","QUANTITY","QUANTITY",
"QUANTITY","QUANTITY","QUANTITY","PRICE","PRICE","PRICE",
"PRICE","PRICE","PRICE","PRICE","PRICE","PRICE","PRICE",
"PRICE","PRICE","PRICE","PRICE","PRICE","PRICE","PRICE",
"PRICE","PRICE","PRICE","PRICE","PRICE","BUY_POINT",
"BUY_POINT","BUY_POINT","BUY_POINT","BUY_POINT","BUY_POINT",
"BUY_POINT","BUY_POINT","BUY_POINT","BUY_POINT","BUY_POINT",
"BUY_POINT","BUY_POINT","BUY_POINT","BUY_POINT","BUY_POINT",
"BUY_POINT","BUY_POINT","BUY_POINT","BUY_POINT","BUY_POINT",
"BUY_POINT","SELL_POINT","SELL_POINT","SELL_POINT",
"SELL_POINT","SELL_POINT","SELL_POINT","SELL_POINT","SELL_POINT",
"SELL_POINT","SELL_POINT","SELL_POINT","SELL_POINT",
"SELL_POINT","SELL_POINT","SELL_POINT","SELL_POINT","SELL_POINT",
"SELL_POINT","SELL_POINT","SELL_POINT","SELL_POINT",
"SELL_POINT"),
VALUE = c(12500,12500,12500,12500,12500,12500,
12500,12500,12500,12500,10100,10100,10100,10100,10100,
10100,10100,10100,10100,10100,10100,0,49.63,50.36,50.06,
52.8,52.5,50.9,50.99,50.91,50.71,50.06,49.71,50.8,
51.09,51.27,52.8,52.8,51.07,50.35,50.25,49.24,49.03,
52.91,49.63,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,
NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,
NA,NA,49.71,NA,NA,NA,NA,NA,NA,NA,NA,NA,NA,52.91)
)
And my code is
library(data.table)
library(ggplot2)
sec_dt <- sec_dt[, DATE := lubridate::ymd(DATE)]
x1 <- max(sec_dt[LINE == 'QUANTITY', VALUE]) * 2
y1 <- max(sec_dt[LINE == 'PRICE', VALUE])
x2 <- min(sec_dt[LINE == 'QUANTITY', VALUE])
y2 <- min(sec_dt[LINE == 'PRICE', VALUE])
k <- (y2 - y1) / (x2 - x1)
b <- y1 - k*x1
stopifnot(!is.na(k), !is.na(b))
p <- ggplot(sec_dt, aes(x = DATE)) +
geom_point(aes(y = VALUE, size = POINT, color = POINT), data = sec_dt[POINT %in% c('BUY_POINT', 'SELL_POINT')]) +
geom_line(aes(y = VALUE, linetype = LINE, colour = LINE), data = sec_dt[LINE %in% c('PRICE')]) +
geom_line(aes(y = VALUE * k + b, linetype = LINE, colour = LINE), data = sec_dt[LINE %in% c('QUANTITY')]) +
scale_linetype_manual('', values = c('PRICE' = 'solid', 'QUANTITY' = 'dashed')) +
scale_size_manual('', values = c('BUY_POINT' = 2, 'SELL_POINT' = 2)) +
scale_colour_manual('', values = c('PRICE' = '#000000', 'QUANTITY' = '#CC0000', 'BUY_POINT' = '#FF0000', 'SELL_POINT' = '#31FF21')) +
scale_y_continuous(
name = 'price', limits = c(min(sec_dt[LINE == 'PRICE', VALUE]), max(sec_dt[LINE == 'PRICE', VALUE])),
sec.axis = sec_axis(~ (. - b) / k , name = "quantity")
) +
labs(x = NULL, y = NULL) +
scale_x_date(
labels = scales::date_format("%Y-%m"), expand = c(0, 12)
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
axis.title.x = element_text(size = 12),
axis.title.y = element_text(size = 12),
legend.text = element_text(size = 8),
legend.position = "top"
)
p
And my graph is like this:

But I need the graph like this:

Does anyone know how to separate the legend of point and line? And how to add different color of line and point separately ?
Solution 1:[1]
One option to achieve your desired result would be the ggnewscale package which allows for multiple scales and legends for the same aesthetic. To this end:
- Duplicate your
scale_colour_manualand add dirt straight after thegeom_point - Add a new color scale using
ggnewscale::new_scale_color()
Note: I added limits=force to each scale_colour_manual to drop unused colors from the legend.
library(ggplot2)
library(ggnewscale)
ggplot(sec_dt, aes(x = DATE)) +
geom_point(aes(y = VALUE, size = POINT, color = POINT), data = sec_dt[POINT %in% c('BUY_POINT', 'SELL_POINT')]) +
scale_colour_manual('', values = c('PRICE' = '#000000', 'QUANTITY' = '#CC0000', 'BUY_POINT' = '#FF0000', 'SELL_POINT' = '#31FF21'), limits = force) +
ggnewscale::new_scale_color() +
geom_line(aes(y = VALUE, linetype = LINE, colour = LINE), data = sec_dt[LINE %in% c('PRICE')]) +
geom_line(aes(y = VALUE * k + b, linetype = LINE, colour = LINE), data = sec_dt[LINE %in% c('QUANTITY')]) +
scale_linetype_manual('', values = c('PRICE' = 'solid', 'QUANTITY' = 'dashed')) +
scale_size_manual('', values = c('BUY_POINT' = 2, 'SELL_POINT' = 2)) +
scale_colour_manual('', values = c('PRICE' = '#000000', 'QUANTITY' = '#CC0000', 'BUY_POINT' = '#FF0000', 'SELL_POINT' = '#31FF21'), limits = force) +
scale_y_continuous(
name = 'price', limits = c(min(sec_dt[LINE == 'PRICE', VALUE]), max(sec_dt[LINE == 'PRICE', VALUE])),
sec.axis = sec_axis(~ (. - b) / k , name = "quantity")
) +
labs(x = NULL, y = NULL) +
scale_x_date(
labels = scales::date_format("%Y-%m"), expand = c(0, 12)
) +
theme_minimal() +
theme(
plot.title = element_text(hjust = 0.5),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
axis.title.x = element_text(size = 12),
axis.title.y = element_text(size = 12),
legend.text = element_text(size = 8),
legend.position = "top"
)
#> Warning: Removed 41 rows containing missing values (geom_point).

Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | stefan |
