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)
Related
I'm likely not using the correct terminology, but the issue is that when creating a dotplot that uses pointrange and multiple groups, the groups as defined in the legend is indistinguishable because the pointrange covers the color of each group (see red rectangle in figure). Is there anyway to either remove the pointrange in the legend (or another solution).
p <- ggplot(ToothGrowth, aes(x=dose, y=len, fill = dose)) + geom_dotplot(binaxis='y', stackdir='center', dotsize = .5, alpha = .25)
p + stat_summary(fun.data=mean_sdl,fun.args = list(mult=1),geom="pointrange", color="black", size = 1)
Thanks for your time.
Try this. You can enable show.legend = F in the last part of your code so that the element will not appear in the legend. Here the code (No output showed as no data was shared):
library(ggplot2)
#Code
p <- ggplot(ToothGrowth, aes(x=dose, y=len, fill = dose)) +
geom_dotplot(binaxis='y', stackdir='center',
dotsize = .5, alpha = .25)
p + stat_summary(fun.data=mean_sdl,fun.args = list(mult=1),
geom="pointrange", color="black", size = 1,show.legend = F)
Or you can use the guides(fill = FALSE) function or scale_fill_discrete(guide = FALSE)
p + guides(fill = FALSE)
or
p + scale_fill_discrete(guide = FALSE)
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
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).
This is my data.
Mod <- as.factor(c(rep("GLM",5),rep("MLP",5),rep("RF",5),rep("SVML",5),rep("SVMR",5)))
Manifold <- as.factor(rep(c("LLE","Iso","PCA","MDS","kPCA"),5))
ROC <- runif(25,0,1)
Sens <- runif(25,0,1)
Spec <- runif(25,0,1)
df <- data.frame("Mod"= Mod, "Manifold"= Manifold, "ROC" = ROC, "Sens" = sens, "Spec" = spec)
And I am making this graph
resul3 <- ggplot(df, aes(x = Mod, y = ROC, fill= Manifold)) +
geom_bar(stat = "identity", position = "dodge", color = "black") +
ylab("ROC & Specificity") +
xlab("Classifiers") +
theme_bw() +
ggtitle("Classifiers' ROC per Feature Extraction Plasma") +
geom_point(aes(y=Spec), color = "black", position=position_dodge(.9)) +
scale_fill_manual(name = "Feature \nExtraction", values = c("#FFEFCA",
"#EDA16A" ,"#C83741", "#6C283D", "#62BF94"))
first graph
And what I want is another legend with tittle "Specificity" and a single black point. I dont want the point to be inside the Manifolds legend.
Something like this but without the points inside the manifold squares
Changing the geom_point line, adding a scale_color_manual and using the override as seen in #drmariod's answer will result in this plot:
ggplot(df, aes(x = Mod, y = ROC, fill= Manifold)) +
geom_bar(stat = "identity", position = "dodge", color = "black") +
ylab("ROC & Specificity") +
xlab("Classifiers") +
theme_bw() +
ggtitle("Classifiers' ROC per Feature Extraction Plasma") +
geom_point(aes(y=Spec, color = "Specificity"), position=position_dodge(.9)) +
scale_fill_manual(name = "Feature \nExtraction", values = c("#FFEFCA",
"#EDA16A" ,"#C83741", "#6C283D", "#62BF94")) +
scale_color_manual(name = NULL, values = c("Specificity" = "black")) +
guides(fill = guide_legend(override.aes = list(shape = NA)))
You can overwrite the aesthetics for shape and set it to NA like this
ggplot(df, aes(x = Mod, y = ROC, fill= Manifold)) +
geom_bar(stat = "identity", position = "dodge", color = "black") +
ylab("ROC & Specificity") +
xlab("Classifiers") +
theme_bw() +
ggtitle("Classifiers' ROC per Feature Extraction Plasma") +
geom_point(aes(y=Spec), color = "black", position=position_dodge(.9)) +
scale_fill_manual(name = "Feature \nExtraction", values = c("#FFEFCA",
"#EDA16A" ,"#C83741", "#6C283D", "#62BF94")) +
guides(fill = guide_legend(override.aes = list(shape = NA)))
I want to plot the distribution of a variable by Class and add vertical lines denoting the means of the subsets defined by each Class and having them colored by Class. While I succeed to color the distributions by Class, the vertical lines appear gray. For a reproducible example see below:
library(data.table)
library(ggplot2)
library(ggthemes)
data(mtcars)
setDT(mtcars)
mtcars[, am := factor(am, levels = c(1, 0))]
mean_data <- mtcars[, .(mu = mean(hp)), by = am]
ggplot(mtcars, aes(x = hp, fill = am , color = am)) +
geom_histogram(aes(y=..density..), position="identity",alpha = 0.4) + guides(color = FALSE) +
geom_density (alpha = 0.5)+
geom_vline(data = mean_data, xintercept = mean_data$mu, aes(color = as.factor(mean_data$am)), size = 2, alpha = 0.5) +
ggtitle("Hp by am") + scale_fill_discrete(labels=c("am" , "no am")) +
labs(fill = "Transmission") + theme_economist()
This code renders the following plot:
Your advice will be appreciated.
You need to include the xintercept mapping in your aes call, so that ggplot properly maps all the aesthetics:
ggplot(mtcars, aes(x = hp, fill = am , color = am)) +
geom_histogram(aes(y=..density..), position="identity",alpha = 0.4) + guides(color = FALSE) +
geom_density (alpha = 0.5)+
geom_vline(data = mean_data, aes(xintercept = mu, color = as.factor(am)), size = 2, alpha = 0.5) +
ggtitle("Hp by am") + scale_fill_discrete(labels=c("am" , "no am")) +
labs(fill = "Transmission") + theme_economist()
Anything you put in a geom call that's not in aes gets treated as a one-off value, and doesn't get all the mapped aesthetics applied to it.