I'm trying to combine alpha and fill aesthetics. It works when I'm using geom_bar (or geom_points, for color), but the alpha legend doesn't work in when I'm using geom_boxplot.
library(data.table)
library(ggplot2)
dt = data.table(x = rep(1:5,6), y = rnorm(30),
tag1 = rep(c('hey', 'what'), 15),
tag2 = rep(c('yeah', 'yeah', 'so', 'so', 'so'), 6))
It works for bars:
ggplot(dt[, list(y = mean(y)), by = list(x, tag1, tag2)],
aes(x = x, y = y, fill = tag1, alpha = tag2,
group = interaction(x,tag1,tag2))) +
geom_bar(stat = 'identity', position = 'dodge')
But not for boxplot - the alpha legend is empty.
ggplot(dt, aes(x = x, y = y, fill = tag1, alpha = tag2,
group = interaction(x, tag1, tag2))) +
geom_boxplot()
A simpler version can be done with no fill - it seems like bar defaults to gray/lightgray, and boxplot defaults to white/lightwhite:
ggplot(dt[, list(y = mean(y)), by = list(x, tag2)],
aes(x = x, y = y, alpha = tag2,
group = interaction(x,tag2))) +
geom_bar(stat = 'identity')
ggplot(dt, aes(x = x, y = y, alpha = tag2,
group = interaction(x, tag2))) +
geom_boxplot()
But I'm not really sure how to fix this. Any thoughts?
I'm not sure why ggplot doesn't actually provide the alpha levels in the legend for boxplots, but you can hard code it using override.aes. (Editorial note: I find the alpha aesthetic a bit confusing for either the boxplot or the bar plot. It's hard to mentally separate the transparency from the fill color and the grey-scale alpha legend exacerbates the problem, because nothing is mapped to grey in the plot.)
In the code below, to improve visibility of the legend, I've removed the box lines from the alpha legend and increased the legend key height. I've also edited the aesthetics to remove the need for the group argument.
ggplot(dt, aes(x=factor(x), y=y, fill=tag1, alpha=tag2)) +
geom_boxplot() +
scale_alpha_manual(values=c(0.2,0.7)) +
guides(alpha=guide_legend(override.aes=list(fill=hcl(c(15,195),100,0,alpha=c(0.2,0.7)),
colour=NA))) +
theme(legend.key.height=unit(1,"cm"))
Another option would be to use interaction for both the fill and alpha aesthetics, but it turns out ggplot doesn't include any colors in that case:
ggplot(dt, aes(x=factor(x), y=y, alpha=interaction(tag1,tag2)),
fill=interaction(tag1,tag2)) +
geom_boxplot() +
scale_fill_manual(values=rep(hcl(c(15,195),100,65), 2)) +
scale_alpha_manual(values=rep(c(0.3, 1), each=2)) +
theme(legend.key.height=unit(2,"cm"))
So, instead you can do it all with the fill aesthetic, but include transparency in the colour specification. This works, but, once again, because transparency and color are somewhat intermingled in visual perception, it's probably better to just go with four different colors.
ggplot(dt, aes(x=factor(x), y=y, fill=interaction(tag1,tag2,sep="-"))) +
geom_boxplot() +
scale_fill_manual(values=hcl(c(15,195,15,195),100,65, alpha=c(0.4,0.4,1,1))) +
theme(legend.key.height=unit(1,"cm")) +
labs(fill="Tag 1 - Tag 2")
Related
I intended to color lines in pink, and points in yellow. I don't want to use colour argument in respective geom(), I want to use scale to change colour.
p3 <- ggplot(dfcc,aes(x = yr, y = mean)) +
geom_line(aes(color = '')) +
geom_point(aes(color = ''))
p3 + scale_colour_manual(values =c('pink', 'yellow'))
This gives this plot, both lines and points are not in the right colours.
Hence, I have two questions
can I use "scale_colour_manual" to change the line and point colors in one go?
if having multiple geoms and multiple scales, how does the system know which scale applies to which geom?
Any help and explanation would be much appreciated!
Use package ggnewscale.
set.seed(2022)
df1 <- data.frame(x = 1:20, y = cumsum(rnorm(20, 2)))
library(ggplot2)
ggplot(df1, aes(x, y)) +
geom_line(color = "pink", linewidth = 2) +
ggnewscale::new_scale_color() +
geom_point(color = "yellow", size = 3) +
theme_classic()
Created on 2022-12-25 with reprex v2.0.2
I have the following example data:
d <- data.frame(x = 1:3, y = 1:3, category = letters[1:3], p = c(TRUE, TRUE, FALSE))
I'd like to plot this coloring by category.
ggplot(d, aes(x, y, color = category) + geom_point(shape = "circle filled")
Then I'd like to make the fill:
the same as the category if p is TRUE
white otherwise
ggplot(d, aes(x, y, color = category, fill = ???) + geom_point(shape = "circle filled")
Has anyone any suggestions?
Could I
access the color scale results and then manipulate them?
calculate color and fill manually, but still have the same legend labels?
You can use fill = after_scale(color) to assign the fill to the same value as the color scale. Using after_scale(ifelse(p, color, "white") should give you the optional white fill value instead.
The only minor snag is that the usual NSE we get inside aes doesn't work inside after_scale, so we need to use d$p instead of just p for the first argument of ifelse
ggplot(d, aes(x, y, color = category)) +
geom_point(aes(fill = after_scale(ifelse(d$p, color, "white"))),
shape = "circle filled", size = 10)
Using the following code generates this plot
ggplot(df_44, aes(x = latest_tli_date, y = farmer_created_at, fill = ward_id)) +
geom_point()+ scale_color_brewer(palette = "BuPu")
I need the 4 wards to have different colours. What am I doing wrong?
try using the fill argument in the geom_point function
Edit: I just tried an example code, the fill and col arguments is going to color it with on a continuous scale because the data is continuous.
If you factor your value you want to color, it should color it discretely.
ggplot(df_44, aes(x = latest_tli_date, y = farmer_created_at)) +
geom_point(aes(col = factor(ward_id))
Use colour aesthetics:
If ward_id is numeric then you might want to replace by colour = factor(ward_id):
Have a look here: https://ggplot2.tidyverse.org/reference/scale_brewer.html
library(ggplot2)
ggplot(df_44, aes(x = latest_tli_date, y = farmer_created_at, colour = ward_id)) +
geom_point()+ scale_color_brewer(palette = "BuPu")
I'm trying to use ggplot2 to make some sort of timeline using values from a dataframe (df). I've managed to plot the data exactly how I want it (the different colored line segments connecting the x-marks in this exact order, i.e., from left to right: 'early', 'unknown', 'late', 'sub'). The startpoint and endpoint columns in the dataframe are used to define the positions of the points and line segments.
The problem is that the legend doesn't show the color of the 'x' icons, they are just grey. I've tried adding scale_color_manual() and scale_fill_manual() commands but they don't seem to change anything. The legend does display the correct color when I change the shape to shape = 21, however, I really want the shape to be 4 (x icons). I don't care about the shape of the legend though but scale_shape_manual() again didn't change anything about the legend.
I have also tried placing different color arguments inside and outside the aes() argument of ggplot(), geom_segment() and/or geom_point().
How can I make the icons from the legend show the correct color?
Below I added a piece of code to reproduce the problem.
library(ggplot2)
library(RColorBrewer)
## Define dataframe
df <- data.frame(Var = c("sub","late","unknown","early"),
Time = c(10,267,0,1256),
Endpoint = c(1533,1523,1256,1256),
Startpoint = c(1523,1256,1256,0))
colorscheme <- RColorBrewer::brewer.pal(9, "Set1")[c(1,4,2,3)]
## Make plot
ggplot(df, aes(x="", y=Endpoint, fill=Var), color =colorscheme) +
geom_segment( aes(x="", xend="", y=Startpoint, yend=Endpoint), color = colorscheme) +
geom_point(aes(x="", y=Endpoint),size=5, shape=4 , color = colorscheme) +
coord_flip()
Thanks in advance for any suggestions!
You should use color instead of fill. To remove the line from the legend, use guides(color = guide_legend(override.aes = list(linetype = 0))) or use show.legend = F in geom_segment.
Also, arguments passed in ggplot need not to be repeated afterward.
ggplot(df, aes(x="", y=Endpoint, color=Var), colorscheme) +
geom_segment(aes(xend="", y=Startpoint, yend=Endpoint)) +
geom_point(size=5, shape=4) +
coord_flip() +
guides(color = guide_legend(override.aes = list(linetype = 0)))
#or
ggplot(df, aes(x="", y=Endpoint, color=Var), colorscheme) +
geom_segment(aes(xend="", y=Startpoint, yend=Endpoint)) +
geom_point(size=5, shape=4) +
coord_flip()
Try this:
ggplot(df, aes(x = "", y = Endpoint, color = Var), colorscheme) +
geom_segment(aes(x = "", xend = "", y = Startpoint, yend = Endpoint), show.legend = FALSE) +
geom_point(aes(x = "", y = Endpoint), size = 5, shape = 4) +
coord_flip()
In this way legend will show only X
I'm trying to add shapes on the lines plotted using geom_freqpoly to give more visibility to them if the plot is printed b/w on paper.
data <- data.frame(time=runif(1000,0,20000),
class=c("a","b","c","d"))
ggplot(data, aes(time, colour = class)) + geom_freqpoly(binwidth = 1000) + geom_point(aes(shape=class))
but this generates this error:
'Error: geom_point requires the following missing aesthetics: y'
How can I solve this error?
Another thing is that I want to use a single colour (eg. blue) to draw the lines
but with scale_colour_brewer() I can't change the colour scale, I want to change it because the lightest colour is nearly white and you can barely see it.
How can I add a custom min and max for the colours?
How about this? The error you are getting is being produced by geom_point which needs x and y, so I removed it.
ggplot(data, aes(x = time, color = class)) +
geom_freqpoly(binwidth = 1000) +
scale_color_brewer(palette = "Blues") +
theme_dark()
If you don't want the dark background, pass manual values from RColorBrewer. The following example uses every second color to increase the contrast.
p1 <- ggplot(data, aes(x = time, color = class)) +
geom_freqpoly(binwidth = 1000) +
scale_color_manual(values = RColorBrewer::brewer.pal(9, name = "Blues")[c(3, 5, 7, 9)])
EDIT
You can extract summarised data from a ggplot object using layer_data function.
xy <- layer_data(p1)
ggplot(xy, aes(x = x, y = count, color = colour)) +
theme_bw() +
geom_line() +
geom_point() +
scale_color_manual(values = RColorBrewer::brewer.pal(9, name = "Blues")[c(3, 5, 7, 9)])