I am new to R and trying to find a simple way to change the labels of the legend for combined boxplots created with ggplot and patchwork.
I am comparing the proportions of 5 different types of cells in 2 groups (controls and asthmatic). I created boxplot for each cell type, and combined them with patchwork.
plot_mac <- ggplot(asthma_desc, aes(x=control_case, y=BAL_mac_LP, color=control_case)) +
geom_boxplot(width=0.5,lwd=0.5) +
geom_jitter(width=0.15) +
labs(y = "Macrophages %") +
stat_compare_means(label = "p.signif", label.x.npc = "center", label.y = 80, hide.ns = T)
then I do the same for 4 different types of cells.
patchwork <- plot_mac + plot_lym + plot_neu + plot_mast + plot_eos + plot_layout(guides = 'collect')
patchwork & theme_minimal() & scale_color_manual(values=c("black", "red")) &
theme(axis.title.x = element_blank(), axis.ticks.x=element_blank(), axis.text.x=element_blank(), text=element_text(size=7)) &
ylim(0,100)
I get the following plot
I would like to change the legend "control_case" to "Group", "1" to "control, "2" to "case". I could not make it work with labs(), scale_x_discrete() nor with theme().
Another option is to add a new column to your dataframe named Group.
Here is an example with mock mtcars dataset:
library(tidyverse)
library(ggpubr)
library(patchwork)
mtcars1 <- mtcars %>%
mutate(Group = case_when( am==0 ~"control",
am==1~"case",
TRUE ~ NA_character_))
p1 <- ggplot(mtcars1, aes(x=Group, y=mpg, color=Group)) +
geom_boxplot(width=0.5,lwd=0.5) +
geom_jitter(width=0.15) +
labs(y = "Macrophages %") +
stat_compare_means(label = "p.signif", label.x.npc = "center", label.y = 80, hide.ns = T)
p2 <- ggplot(mtcars1, aes(x=Group, y=wt, color=Group)) +
geom_boxplot(width=0.5,lwd=0.5) +
geom_jitter(width=0.15) +
labs(y = "Macrophages %") +
stat_compare_means(label = "p.signif", label.x.npc = "center", label.y = 80, hide.ns = T)
p3 <- ggplot(mtcars1, aes(x=Group, y=hp, color=Group)) +
geom_boxplot(width=0.5,lwd=0.5) +
geom_jitter(width=0.15) +
labs(y = "Macrophages %") +
stat_compare_means(label = "p.signif", label.x.npc = "center", label.y = 80, hide.ns = T)
patchwork <- p1 + p2 + p3 + plot_layout(guides = 'collect')
patchwork & theme_minimal() & scale_color_manual(values=c("black", "red")) &
theme(axis.title.x = element_blank(), axis.ticks.x=element_blank(), axis.text.x=element_blank(), text=element_text(size=7)) &
ylim(0,100)
Related
I'd like to be able to change the colour palette in ggplot2 boxplots, according to another variable data_origin.
This makes my boxplots, complete with legend:
library(hrbrthemes)
library(ggplot2)
library(reshape2)
library(tidyverse)
data_origin <- "airborne"
mytitle <- "something more than this"
legend_title <- "some words"
melted <- reshape2::melt(iris)
bp1 <- ggplot(melted, aes(x = variable, y = value, fill = Species)) +
geom_boxplot() +
theme_ipsum() +
scale_fill_brewer(palette = "Greens") +
theme(
legend.position = "bottom",
plot.title = element_text(size = 10)) +
theme(axis.text.x = element_blank()) +
ggtitle(mytitle) +
xlab("") +
ylab("") +
facet_wrap(~variable, scale = "free")
bp1
This however drops the legend completely and ignores the if else:
bp1 <- ggplot(melted, aes(x = variable, y = value, fill = Species)) +
geom_boxplot() +
theme_ipsum() +
scale_fill_brewer(legend_title, if (data_origin == "airborne" ) {palette = "Blues"} else {palette = "Greens"}) +
theme(
legend.position = "bottom",
# legend.title = legend_title,
plot.title = element_text(size = 10)) +
theme(axis.text.x = element_blank()) +
ggtitle(mytitle) +
xlab("") +
ylab("") +
facet_wrap(~variable, scale = "free")
bp1
Besides what #stefan suggested, there are two ways in which you can do this (that I know of). The first is using ifelse() (I moved the relevant part to the end):
data_origin <- "airborne"
bp1 <- ggplot(melted, aes(x = variable, y = value, fill = Species)) +
geom_boxplot() +
theme_ipsum() +
theme(
legend.position = "bottom",
# legend.title = legend_title,
plot.title = element_text(size = 10)) +
theme(axis.text.x = element_blank()) +
ggtitle(mytitle) +
xlab("") +
ylab("") +
facet_wrap(~variable, scale = "free") +
scale_fill_brewer(legend_title, palette = ifelse(
data_origin == "airborne",
"Blues",
"Greens"
))
bp1
The other one is to build the plot up in two steps:
data_origin <- "not airborne"
bp1 <- ggplot(melted, aes(x = variable, y = value, fill = Species)) +
geom_boxplot() +
theme_ipsum() +
theme(
legend.position = "bottom",
# legend.title = legend_title,
plot.title = element_text(size = 10)) +
theme(axis.text.x = element_blank()) +
ggtitle(mytitle) +
xlab("") +
ylab("") +
facet_wrap(~variable, scale = "free")
if (data_origin == "airborne") {
bp2 <- bp1 +
scale_fill_brewer(legend_title, palette = "Blues")
} else {
bp2 <- bp1 +
scale_fill_brewer(legend_title, palette = "Greens")
}
bp2
Created on 2021-08-01 by the reprex package (v2.0.0)
I have a stacked bar graph and ggplot has automatically generated a color legend that I want to remove. I have tried show.legend=FALSE, theme(legend.position="none"), and guides(colour=FALSE) and none of those solutions have removed the legend. I'll include the code below.
ggplot(unique_per_day, aes(fill=Entity.Name,y=prop, x=Entity.Type, width = org.count, label=Entity.Name), show.legend=FALSE) +
geom_bar(position="fill", stat="identity", colour= "black") +
facet_grid(~Entity.Type, scales="free_x", space="free_x" ) +
theme(legend.position="none", panel.spacing.x = unit(0, "npc")) +
guides(colour=FALSE) +
geom_text(size = 2.4, position = position_stack(vjust = 0.5)) +
theme_void()
It would be easier to troubleshoot if you provided an example dataset (e.g. dput(unique_per_day)), but my guess is that you need to remove the "fill" aesthetic, instead of the "color" aesthetic, e.g.
ggplot(unique_per_day, aes(fill=Entity.Name,y=prop, x=Entity.Type, width = org.count, label=Entity.Name)) +
geom_bar(position="fill", stat="identity", colour= "black", show.legend=FALSE) +
facet_grid(~Entity.Type, scales="free_x", space="free_x" ) +
guides(fill = FALSE) +
geom_text(size = 2.4, position = position_stack(vjust = 0.5)) +
theme_void() +
theme(legend.position="none", panel.spacing.x = unit(0, "npc"))
Edit
Here is an example using the "palmerpenguins" example dataset:
With the original code:
library(tidyverse)
library(palmerpenguins)
penguins %>%
na.omit() %>%
filter(island == "Dream") %>%
ggplot(aes(x = species, y = 1, fill = sex)) +
geom_bar(position = "fill", stat = "identity", colour = "black") +
facet_grid(~ island, scales = "free_x", space = "free_x") +
theme(legend.position = "none", panel.spacing.x = unit(0, "npc")) +
guides(colour = FALSE) +
theme_void()
With "theme_void" moved above "theme":
penguins %>%
na.omit() %>%
filter(island == "Dream") %>%
ggplot(aes(x = species, y = 1, fill = sex)) +
geom_bar(position = "fill", stat = "identity", colour = "black") +
facet_grid(~ island, scales = "free_x", space = "free_x") +
theme_void() +
theme(legend.position="none", panel.spacing.x = unit(0, "npc"))
Consider this plot:
library(scales)
library(ggplot2)
df.m <- data.frame(Var1=c("A","B"), Var2=c("B", "A"), Similarity=c(97.5,92.5),
Rank=c("In", "Out"))
p <- ggplot(df.m, aes(Var1, Var2, fill=Similarity, col=Rank)) +
geom_tile() +
theme_bw()+
theme(legend.position="bottom")+
xlab("") +
ylab("") +
scale_fill_gradient2(low = muted("red"),
mid = "white", high = muted("blue")) +
scale_color_manual(values=c("black", "gold"))
The titles of the legends do not align. When i add guides, this happens:
p + guides(color=guide_legend(override.aes = list(fill="white")),
fill=guide_legend(title.hjust=0.5))
The titles now align, but the continous-nature of the fill-legend is lost.
What can i do?
You can add legend.box.just = "center"
ggplot(df.m, aes(Var1, Var2, fill = Similarity, colour = Rank)) +
geom_tile() +
theme_bw() +
theme(legend.position = "bottom", legend.box.just = "center")
I'm working in a Impulse-Response function plot (from a Vector AutoRegressive Model) with GGplot2 + grid.arrange. Below i give you my actual plot and the original one from the vars package. I really would like any hint to improve the final result
Would be nice, at least place both plots closer.
This is not a full question topic, but an improvement asking
here the full code
library(vars)
# Define lags
lag = VARselect(my_data, lag.max=12)
# Estimating var
my_var = VAR(my_data, min(lag$selection), type='both')
# Set the Impulse-Response data
impulse <- irf(my_var)
# Prepare plot data
number_ticks <- function(n) {function(limits) pretty(limits, n)}
lags <- c(1:11)
irf1<-data.frame(impulse$irf$PIB[,1],impulse$Lower$PIB[,1],
impulse$Upper$PIB[,1], lags)
irf2<-data.frame(impulse$irf$PIB[,2],impulse$Lower$PIB[,2],
impulse$Upper$PIB[,2])
# creating plots
PIB_PIB <- ggplot(data = irf1,aes(lags,impulse.irf.PIB...1.)) +
geom_line(aes(y = impulse.Upper.PIB...1.), colour = 'lightblue2') +
geom_line(aes(y = impulse.Lower.PIB...1.), colour = 'lightblue')+
geom_line(aes(y = impulse.irf.PIB...1.))+
geom_ribbon(aes(x=lags, ymax=impulse.Upper.PIB...1., ymin=impulse.Lower.PIB...1.), fill="lightblue", alpha=.1) +
xlab("") + ylab("PIB") + ggtitle("Orthogonal Impulse Response from PIB") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank()) +
geom_line(colour = 'black')
PIB_CON <- ggplot(data = irf2,aes(lags,impulse.irf.PIB...2.)) +
geom_line(aes(y = impulse.Upper.PIB...2.), colour = 'lightblue2') +
geom_line(aes(y = impulse.Lower.PIB...2.), colour = 'lightblue')+
geom_line(aes(y = impulse.irf.PIB...2.))+
geom_ribbon(aes(x=lags, ymax=impulse.Upper.PIB...2., ymin=impulse.Lower.PIB...2.), fill="lightblue", alpha=.1) +
scale_x_continuous(breaks=number_ticks(10)) +
xlab("") + ylab("CONSUMO") + ggtitle("") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank()) +
geom_line(colour = 'black')
# Generating plot
grid.arrange(PIB_PIB, PIB_CON, nrow=2)
Actual Output
Desired Style [when you call plot(irf(my_var))
Got something very close to desired model.
here the changed plots:
PIB_PIB <- ggplot(data = irf1,aes(lags,impulse.irf.PIB...1.)) +
geom_line(aes(y = impulse.Upper.PIB...1.), colour = 'lightblue2') +
geom_line(aes(y = impulse.Lower.PIB...1.), colour = 'lightblue')+
geom_line(aes(y = impulse.irf.PIB...1.))+
geom_ribbon(aes(x=lags, ymax=impulse.Upper.PIB...1., ymin=impulse.Lower.PIB...1.), fill="lightblue", alpha=.1) +
xlab("") + ylab("PIB") + ggtitle("Orthogonal Impulse Response from PIB") +
theme(axis.title.x=element_blank(),
axis.text.x=element_blank(),
axis.ticks.x=element_blank(),
plot.margin = unit(c(2,10,2,10), "mm"))+
scale_x_continuous(breaks=number_ticks(10)) +
geom_line(colour = 'black')
PIB_CON <- ggplot(data = irf2,aes(lags,impulse.irf.PIB...2.)) +
geom_line(aes(y = impulse.Upper.PIB...2.), colour = 'lightblue2') +
geom_line(aes(y = impulse.Lower.PIB...2.), colour = 'lightblue')+
geom_line(aes(y = impulse.irf.PIB...2.))+
geom_ribbon(aes(x=lags, ymax=impulse.Upper.PIB...2., ymin=impulse.Lower.PIB...2.), fill="lightblue", alpha=.1) +
xlab("") + ylab("CONSUMO") + ggtitle("") +
theme(axis.title.x=element_blank(),
# axis.text.x=element_blank(),
# axis.ticks.x=element_blank(),
plot.margin = unit(c(-10,10,4,10), "mm"))+
scale_x_continuous(breaks=number_ticks(10)) +
geom_line(colour = 'black')
grid.arrange(PIB_PIB, PIB_CON, nrow=2)
I have the following reproducible code which gets me the plot listed below:
require(ggplot2)
set.seed(123)
ChickWt <- data.frame(ChickWeight, AR = sample(c("p=0", "p=1", "hat(p)"), size = 578, replace = T))
exprvec <- expression( p==hat(p), p==0, p==1)
p1 <- ggplot(ChickWt, aes(x=Time, y=weight, colour=Diet, Group = Chick, linetype = AR)) + geom_line()
p1 <- p1 + scale_linetype_manual(values=c(2,4,1), labels = exprvec,name="AR order") + theme_bw() + theme(legend.justification=c(1,-0.2), legend.position=c(0.3,0.2), legend.text=element_text(size=10), legend.title=element_text(size=10), axis.title.x=element_text(size=10), axis.title.y=element_text(size = 10), legend.key = element_blank(), legend.background = element_rect(color="black",size = 0.1)) + ylim(c(0,400)) + guides(fill=guide_legend(ncol=2))
but I would like the legend on Diet and AR order in two separate columns. How do I get this to work? Clearly, the guides(fill=guide_legend(ncol=2)) has no effect, perhaps because these are two separate legends.
Thanks for suggestions!
The reason that guides(fill=guide_legend(ncol=2)) does not work is because it only refers to the fill-legend and not to the linetype-legend. You can position the legends next to each other by using legend.box = "horizontal":
ggplot(ChickWt, aes(x=Time, y=weight, colour=Diet, Group = Chick, linetype = AR)) +
geom_line() +
scale_linetype_manual(values=c(2,4,1), labels = exprvec,name="AR order") +
theme_bw() +
theme(legend.justification=c(1,-0.2),
legend.position=c(0.3,0.2),
legend.text=element_text(size=10),
legend.title=element_text(size=10),
axis.title.x=element_text(size=10),
axis.title.y=element_text(size = 10),
legend.key = element_blank(),
legend.background = element_rect(color="black",size = 0.1),
legend.box = "horizontal") +
ylim(c(0,400))
which gives: