Combining legends for two different aesthetics fails - r

library(ggplot2)
x <- data.frame(Specimen=c("A","B","C","D"), Value=rep(0.5,4),
Type=c("c1","c1","c2","c2"), Treatment=factor(rep("A", 4)),
bar=c("hot", "cold", "cold", "cold"))
list2env(split(x, x$Type), envir = .GlobalEnv)
p1 <- ggplot() +
geom_bar(data=c1, aes(x = Treatment, y = Value, fill = Specimen, colour=bar),
stat="identity", position="fill", width=0.5) +
scale_fill_manual("",values=c("gold", "green"))+
scale_color_manual("",values=c("gray40","black")) +
scale_y_continuous(expand = c(0, 0),labels = scales::percent) +
theme(legend.position = "bottom") +
coord_flip()
p2 <- ggplot() +
geom_bar(data=c2, aes(x = Treatment, y = Value, fill = Specimen),
stat="identity", position="fill", col="gray40", width=0.5) +
scale_fill_manual("",values=c("red", "blue"))+
scale_y_continuous(expand = c(0, 0),labels = scales::percent) +
theme(legend.position = "bottom",
axis.text.y=element_blank()) +
xlab("")+
coord_flip()
library(cowplot)
plot_grid(p1,p2, nrow=1, align="v")
In this example, i had to shut down the guide for color, as i couldnt combine it with the guide for fill, despite following the guidelines proposed in this question.
After turning off the guide for col in p1 (guide=F), the legends now appear to be differently drawn (one with col="gray40", the other without any border, as the col-guide is set to false):
]1
How to combine the two legends in p1?

fill and color are mapped to two different varaibles, it's only by chance that in this (trivial) case "A" is always "hot" and "B" is always "cold".
You can map both fill and color to Specimen or bar, but different variable will always result in different legends.
An alternative may be to create an interaction between the two varaibles:
library(ggplot2)
ggplot() +
geom_col(data=c1, aes(x = Treatment,
y = Value,
fill = interaction(Specimen, bar, sep = '-'),
color = interaction(Specimen, bar, sep = '-')),
position="fill", width=0.5) +
scale_fill_manual("",values=c("gold", "green")) +
scale_color_manual("",values=c("gray40", "black")) +
scale_y_continuous(expand = c(0, 0),labels = scales::percent) +
theme(legend.position = "bottom") +
coord_flip()
Created on 2018-05-08 by the reprex package (v0.2.0).

Related

Merge legend in ggplot when the geoms are different

I have the following code which yields the figure below:
ggplot(data=data.frame(x=x, y=y, mass=mass)) +
geom_line(mapping = aes(x=x, y=y, linetype='Gompertz predicted mass', col='Gompertz predicted mass')) +
geom_point(mapping = aes(x=x, y=mass, shape='Actual mass',col='Actual mass')) +
theme_bw() +
ylab('Mass') +
xlab('t') +
scale_color_manual(name='',values = c("black",'red')) +
scale_linetype_manual(name='',values = c("solid")) +
scale_shape_manual(name='', values = c(19)) +
scale_x_continuous(breaks=seq(4,26,2)) +
ylim(c(0, 20000)) +
ggtitle('Problem 3: Plot of tumor mass with time')
Notice how the legend is separated. I'd like to merge it for shape and color. When the geoms are the same, the technique of using scale_something_manual works perfectly fine to merge the legends. However, I'm having trouble with it here since I have two different geoms.
The problem is similar to the one described in https://github.com/tidyverse/ggplot2/issues/3648. There is no elegant solution at the moment. Because you haven't included any data, I've presumed that your problem is conceptually similar to the plot below:
library(ggplot2)
ggplot(mpg, aes(displ, hwy)) +
geom_point(aes(shape = "Point", colour = "Point")) +
geom_smooth(aes(linetype = "Line", colour = "Line"),
formula = y ~ x, se = FALSE, method = "loess") +
scale_colour_manual(values = c("red", "black")) +
scale_linetype_manual(values = "solid") +
scale_shape_manual(values = 19)
The way to fix the problem is to get rid of the linetype and shape aesthetics and scales, and instead override aesthetics at the level of the legend.
ggplot(mpg, aes(displ, hwy)) +
geom_point(aes(colour = "Point")) +
geom_smooth(aes(colour = "Line"),
formula = y ~ x, se = FALSE, method = "loess") +
scale_colour_manual(
values = c("red", "black"),
guide = guide_legend(override.aes = list(shape = c(NA, 19),
linetype = c(1, NA)))
)
Created on 2021-09-04 by the reprex package (v2.0.1)

How to add a legend manually for line chart

i need the plan legend
How to add a legend manually for geom_line
ggplot(data = impact_end_Current_yr_m_actual, aes(x = month, y = gender_value)) +
geom_col(aes(fill = gender))+theme_classic()+
geom_line(data = impact_end_Current_yr_m_plan, aes(x=month, y= gender_value, group=1),color="#288D55",size=1.2)+
geom_point(data = impact_end_Current_yr_m_plan, aes(x=month, y=gender_value))+
theme(axis.line.y = element_blank(),axis.ticks = element_blank(),legend.position = "bottom", axis.text.x = element_text(face = "bold", color = "black", size = 10, angle = 0, hjust = 1))+
labs(x="", y="End Beneficiaries (in Num)", fill="")+
scale_fill_manual(values=c("#284a8d", "#00B5CE","#0590eb","#2746c2"))+
scale_y_continuous(labels = function(x) format(x, scientific = FALSE)
The neatest way to do it I think is to add colour = "[label]" into the aes() section of geom_line() then put the manual assigning of a colour into scale_colour_manual() here's an example from mtcars (apologies that it uses stat_summary instead of geom_line but does the same trick):
library(tidyverse)
mtcars %>%
ggplot(aes(gear, mpg, fill = factor(cyl))) +
stat_summary(geom = "bar", fun = mean, position = "dodge") +
stat_summary(geom = "line",
fun = mean,
size = 3,
aes(colour = "Overall mean", group = 1)) +
scale_fill_discrete("") +
scale_colour_manual("", values = "black")
Created on 2020-12-08 by the reprex package (v0.3.0)
The limitation here is that the colour and fill legends are necessarily separate. Removing labels (blank titles in both scale_ calls) doesn't them split them up by legend title.
In your code you would probably want then:
...
ggplot(data = impact_end_Current_yr_m_actual, aes(x = month, y = gender_value)) +
geom_col(aes(fill = gender))+
geom_line(data = impact_end_Current_yr_m_plan,
aes(x=month, y= gender_value, group=1, color="Plan"),
size=1.2)+
scale_color_manual(values = "#288D55") +
...
(but I cant test on your data so not sure if it works)

No combining geom point with geom line in legend

I´m trying to get just one legend with shape that have the same color as the graph but it is just in black color:
type1 <-c("tmax","tmax","tmax","tmin","tmin","tmin","tmax","tmax","tmax","tmin","tmin","tmin")
station1 <-c("Anda","Anda","Anda","Anda","Anda","Anda","Mach","Mach","Mach","Mach","Mach","Mach")
date1 <-c(2001,2002,2003,2001,2002,2003,2002,2003,2004,2002,2003,2004)
meanTemp1<-c(15,16,15.5,5,7,8,13,14,12,9,9,7)
data11 <- data.frame(type1,station1,date1,meanTemp1)
plot1<- ggplot(data11, aes(x=date1, y=meanTemp1,group = station1,colour=station1,shape=station1)) +
geom_line () + guides(colour=FALSE)+
geom_point() +
xlab("year") + ylab("°C") +
labs(shape = "Station")+
facet_wrap(~type1,scales = "free")+
theme(axis.text.x = element_text(angle = 60,hjust = 1))
plot1
How can I get the legend fill with the same color as the graph instead of "black"?
As you rename shape legend in labs, you also need to rename colour legends using the same name in order they get merge.
Instead of using guides(colour = FALSE), you can pass in geom_line, the argument show.legend = FALSE to remove the colored lines in the legend:
plot1<- ggplot(data11, aes(x=date1, y=meanTemp1, group = station1,
colour=station1,
shape=station1)) +
geom_line (show.legend = FALSE) +
geom_point() +
xlab("year") + ylab("°C") +
labs(shape = "Station", colour = "Station")+
facet_wrap(~type1,scales = "free")+
theme(axis.text.x = element_text(angle = 60,hjust = 1))
plot1

ggplot2: doughnuts, how to conditional color fill with if_else

Following guides like ggplot Donut chart I am trying to draw small gauges, doughnuts with a label in the middle, with the intention to put them later on on a map.
If the value reaches a certain threshold I would like the fill of the doughnut to change to red. Is it possible to achieve with if_else (it would be most natural but it does not work).
library(tidyverse)
df <- tibble(ID=c("A","B"),value=c(0.7,0.5)) %>% gather(key = cat,value = val,-ID)
ggplot(df, aes(x = val, fill = cat)) + scale_fill_manual(aes,values = c("red", "yellow"))+
geom_bar(position="fill") + coord_polar(start = 0, theta="y")
ymax <- max(df$val)
ymin <- min(df$val)
p2 = ggplot(df, aes(fill=cat, y=0, ymax=1, ymin=val, xmax=4, xmin=3)) +
geom_rect(colour="black",stat = "identity") +
scale_fill_manual(values = if_else (val > 0.5, "red", "black")) +
geom_text( aes(x=0, y=0, label= scales::percent (1-val)), position = position_dodge(0.9))+
coord_polar(theta="y") +
xlim(c(0, 4)) +
theme_void() +
theme(legend.position="none") +
scale_y_reverse() + facet_wrap(facets = "ID")
Scale fill manual values= if else.... this part does not work, the error says: Error in if_else(val > 0.5, "red", "black") : object 'val' not found. Is it my error, or some other solution exists?
I also realize my code is not optimal, initially gather waited for more variables to be included in the plot, but I failed to stack one variable on top of the other. Now one variable should be enough to indicate the percentage of completion. I realise my code is redundant for the purpose. Can you help me out?
A solution for the color problem is to first create a variable in the data and then use that to map the color in the plot:
df <- tibble(ID=c("A","B"),value=c(0.7,0.5)) %>% gather(key = cat,value = val,-ID) %>%
mutate(color = if_else(val > 0.5, "red", "black"))
p2 = ggplot(df, aes(fill=color, y=0, ymax=1, ymin=val, xmax=4, xmin=3)) +
geom_rect(colour="black",stat = "identity") +
scale_fill_manual(values = c(`red` = "red", `black` = "black")) +
geom_text( aes(x=0, y=0, label= scales::percent (1-val)), position = position_dodge(0.9))+
coord_polar(theta="y") +
xlim(c(0, 4)) +
theme_void() +
theme(legend.position="none") +
scale_y_reverse() + facet_wrap(facets = "ID")
The result would be:

How to add multiple geom_hlines with color equal to grouping variable

I've created a grouped boxplot and added three specific geom_hlines to the plot. However, I want to set the hline colors to fill=factor(Training.Location), rather than trying to match the colors manually with a color palette. Is there a way to do this?
ggplot(aes(x=factor(CumDes),y=Mn_Handle), data=NH_C) +
geom_boxplot( aes(fill=factor(Training.Location))) +
geom_point( aes(color=factor(Training.Location)),
position=position_dodge(width=0.75) ) +
theme(axis.ticks = element_blank(), axis.text.x = element_blank()) +
coord_cartesian(ylim = c(0, 2000)) +
geom_hline(yintercept=432, linetype="dashed", lwd=1.2) +
geom_hline(yintercept=583, linetype="dashed", lwd=1.2) +
geom_hline(yintercept=439, linetype="dashed", lwd=1.2)
This is the sort of thing that seems easiest with a new dataset. I'm not sure how you are calculating the values you are using for the horizontal lines, but often times I want to calculate these from the original dataset and use some sort of aggregation function/package for that.
Here is a modified example from the help page for geom_hline.
Make the dataset to give to geom_hline, including the values for the horizontal lines as well as the grouping variable.
mean_wt = data.frame(cyl = c(4, 6, 8), wt = c(2.28, 3.11, 4.00))
Then just plot with the new dataset for that layer, using whatever aesthetic you wish with the grouping variable.
ggplot(mtcars, aes(x = factor(vs), wt) ) +
geom_boxplot(aes(fill = factor(cyl))) +
geom_point(aes(color = factor(cyl)), position = position_dodge(.75)) +
geom_hline(data = mean_wt, aes(yintercept = wt, color = factor(cyl)) )
Here's a somewhat hackish solution (I had to improvise on the data, feel free to improve)
# install.packages("ggplot2", dependencies = TRUE)
library(ggplot2)
col <- c("#CC6666", "#9999CC", "#66CC99")
ggplot(mtcars, aes(x = factor(cyl), y=mpg)) +
geom_boxplot(aes(fill=gear)) +
geom_point( aes(color=factor(gear)),
position=position_dodge(width=0.75) ) +
scale_colour_manual(values= col) +
theme(axis.ticks = element_blank(), axis.text.x = element_blank()) + coord_cartesian(ylim = c(8, 35)) +
geom_hline(yintercept=12, linetype="dashed", lwd=1.2, color=col[1]) +
geom_hline(yintercept=18, linetype="dashed", lwd=1.2, color=col[2]) +
geom_hline(yintercept=28, linetype="dashed", lwd=1.2, color=col[3])

Resources