Related
I have modified the colors of my x axis labels according to their group.
For that, I have used the following pseudocode:
library(ggsci)
library(ggplot2)
x_cols = pal_jco()(length(unique(melted_df$Group)))
names(x_cols) = unique(melted_df$Group)
ggplot(melted_df, ... + theme(axis.text.x = element_text(colour = x_cols))
I would like to add a legend to the plot (if possible, outside the plot), that explains the colouring of the x axis labels.
melted_df dataframe looks like this:
Here the full code:
#Generate color mapping
x_cols = pal_jco()(length(unique(melted_df$Group)))
names(x_cols) = unique(melted_df$Group)
melted_df$mycolors = sapply(as.character(melted_df$Group), function(x) x_cols[x])
#Plot
ggplot(melted_df, aes(fill=variable, y=value, x=fct_inorder(id))) +
geom_bar(position="stack", stat = "identity") + ggtitle("Barplot") +
theme_bw() +
xlab("samples") + ylab("Counts") +
theme(axis.title.y=element_text(size=10), axis.title.x=element_text(size=10),
plot.title = element_text(face = "bold", size = (15), hjust = 0.5),
axis.text.x = element_text(distinct(samples_melt[c("id", "mycolors")])$mycolors)) +
guides(fill=guide_legend(title="Columns"))
In the absence of a reproducible example, here is how you might do it with the built-in iris data set:
library(ggplot2)
ggplot(iris, aes(Species, Sepal.Length)) +
stat_summary(fun = mean, geom = "col", aes(fill = Species)) +
geom_point(aes(color = Species), alpha = 0, key_glyph = draw_key_text) +
theme_bw(base_size = 20) +
labs(color = "") +
guides(color = guide_legend(override.aes = list(alpha = 1, size = 8))) +
theme(axis.text.x = element_text(color = scales::hue_pal()(3), face = 2))
I addressed the issue using Legend() constructor, provided by ComplexHeatmap library.
I first used the code provided above under the EDIT section, and then I added the following code in order to draw an additional legend explaining the x-axis colouring.
lgd = Legend(labels = names(x_cols), title = "Group", labels_gp = gpar(fontsize = 8), nrow = 1, legend_gp = gpar(fill = x_cols))
draw(lgd, x = unit(1.8, "cm"), y = unit(0.3, "cm"), just = c("left", "bottom"))
My data looks like this:
month=c("Jan","Feb","Mar","Apr","May","Jun")
rate=c(70,80,90,85,88,76)
dd=data.frame(month,rate)
dd$type="Rate"
dd$month=factor(dd$month)
I tried to create the plot like this:
ggplot(dd,aes(x=month,y=rate,color=type)) +
geom_point(aes(x=month,y=rate, group=1), size=2) +
geom_text(aes(label = paste(format(rate, digits = 4, format = "f"), "%")),
color="black",vjust = -0.5, size = 3.5) +
geom_line(aes(x = month, y = rate, group=1), size=1) +
geom_hline(aes(yintercept=85), linetype='dashed',colour="#F8766D", show.legend=T) +
labs(y="", x="") +
scale_colour_manual(values = c("#00BFC4")) +
scale_fill_discrete(limits = c("Target")) +
theme(legend.position="bottom") +
theme(legend.title = element_blank())
As you can see, the legend of Rate and Target are overlapping together (there is red dash line in the green line), I'd like to know how to create the legend for Target and Rate in the correct way. Thanks!
One option to achieve your desired result would be to map on aesthetics and make use of scale_xxx_manual instead of setting the color, linetypes, ... via arguments:
month=c("Jan","Feb","Mar","Apr","May","Jun")
rate=c(70,80,90,85,88,76)
dd=data.frame(month,rate)
dd$type="Rate"
dd$month=factor(dd$month)
library(ggplot2)
ggplot(dd,aes(x=month,y=rate, color="Rate", linetype = "Rate")) +
geom_point(aes(x=month,y=rate, shape = "Rate"), size=2) +
geom_text(aes(label = paste(format(rate, digits = 4, format = "f"), "%")),
color="black",vjust = -0.5, size = 3.5) +
geom_line(aes(x = month, y = rate, group=1, size = "Rate")) +
geom_hline(aes(yintercept=85, color = "Target", linetype = "Target", size = "Target")) +
labs(y = NULL, x= NULL, color = NULL, linetype = NULL, shape = NULL, size = NULL) +
scale_colour_manual(values = c(Rate = "#00BFC4", Target = "#F8766D")) +
scale_linetype_manual(values = c(Rate = "solid", Target = "dashed")) +
scale_shape_manual(values = c(Rate = 16, Target = NA)) +
scale_size_manual(values = c(Rate = 1, Target = .5)) +
theme(legend.position="bottom")
I have made a barplot similar to the one below using ggplot2.
I cannot get the percentages on top of the bars to be centered and not overlapping of other bars and numbers. Sample code is below.
library(tidyverse)
cat1=c("cat1","cat1","cat1","cat1","cat1","cat1","cat1","cat1","cat1","cat1","cat1","cat1",
"cat2","cat2","cat2","cat2","cat2","cat2","cat2","cat2","cat2","cat2","cat2","cat2",
"cat3","cat3","cat3","cat3","cat3","cat3","cat3","cat3","cat3","cat3","cat3","cat3",
"cat4","cat4","cat4","cat4","cat4","cat4","cat4","cat4","cat4","cat4","cat4","cat4")
cat2=c("c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11","c12",
"c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11","c12",
"c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11","c12",
"c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11","c12")
count1=round(rnorm(48,10))
fakeperc=rnorm(48,9)
df1=cbind(count1,fakeperc)
df2=cbind(cat1,cat2)
finaldf=as.data.frame(cbind(df1,df2))
finaldf$cat1=as.factor(finaldf$cat1)
finaldf$fakeperc=as.numeric(finaldf$fakeperc)
#finaldf$cat1=factor(finaldf$cat1,levels = c("cat1","cat2","cat3","cat4"))
finaldf$cat2 = factor(finaldf$cat2,
levels = c("c1","c2","c3","c4","c5","c6","c7","c8","c9","c10","c11","c12"))
a=ggplot(data=finaldf,aes(x=cat1, y=count1,
fill=cat2,group=cat2)) +
geom_bar(stat='identity',color='black',width=.65,position=position_dodge(width=.9))+
scale_y_discrete(limits=0:50,breaks=c(0,10,20,30,40,50))+
scale_fill_brewer(palette="Set3") +
theme_classic() +
geom_text(data = finaldf,
aes(x=cat1,y=count1,group=cat2,
label=format(paste(round(fakeperc),"%",sep = ""))),inherit.aes = F,
color='black',position=position_dodge(.9),vjust=-.5,size=3)
a
When trying to add either nudge_y or nudge_x to the geom_text call, nothing happens. I suspect this is because there is already a position_dodge call. I am open any and all solutions to make these percentages non-overlapping and legible.
What do you think of this?
# I think you meant count1 to be numeric
finaldf$count1 <- as.numeric(finaldf$count1)
ggplot(data = finaldf,
aes(x = cat1,
y = count1,
fill = cat2,
group = cat2)) +
geom_col(color = 'black',
width = 0.65,
position = position_dodge(width = 0.9)) +
geom_text(data = finaldf,
aes(x = cat1,
y = count1,
group = cat2,
label = scales::percent(fakeperc/100, accuracy = 0.01)),
inherit.aes = FALSE,
color = 'black',
position = position_dodge(0.9),
hjust = -0.1,
size = 3) +
scale_y_continuous(limits = c(0,50), breaks = c(0,10,20,30,40,50)) +
scale_fill_brewer(palette = "Set3") +
theme_classic() +
coord_flip()
I cleaned up a bit the code (according to my taste)
I changed scale_y_numeric to scale_y_continuous (since count1 should be numeric)
I used coord_flip() to make it more readable
I used scales::percent to write percentage numbers
(don't know why you set up limits from 0 to 50 but I left them as I suppposed they were intended)
If you don't want to use coor_flip:
finaldf$count1 <- as.numeric(finaldf$count1)
ggplot(data = finaldf,
aes(x = cat1,
y = count1,
fill = cat2,
group = cat2)) +
geom_col(color = 'black',
width = 0.65,
position = position_dodge(width = 0.9)) +
geom_text(data = finaldf,
aes(x = cat1,
y = count1,
group = cat2,
label = scales::percent(fakeperc/100, accuracy = 0.01)),
inherit.aes = FALSE,
color = 'black',
position = position_dodge(0.9),
hjust = -0.1,
angle = 90,
size = 3) +
scale_y_continuous(limits = c(0,50), breaks = c(0,10,20,30,40,50)) +
scale_fill_brewer(palette = "Set3") +
theme_classic()
Is this what you are looking for:
library(ggplot2)
#Code
ggplot(data=finaldf,aes(x=cat2, y=count1,
fill=cat2,group=cat2)) +
geom_bar(stat='identity',color='black',
position=position_dodge(width=1))+
scale_fill_brewer(palette="Set3") +
theme_bw() +
geom_text(aes(x=cat2,y=count1,group=cat2,
label=format(paste(round(fakeperc),"%",sep = ""))),inherit.aes = F,
color='black',position=position_dodge(1),
size=3,vjust=-0.5)+
facet_wrap(.~cat1,scales = 'free_x',nrow = 1,strip.position = 'bottom')+
theme(axis.text.x = element_blank(),
axis.ticks.x = element_blank(),
legend.position = 'top',
strip.background = element_blank(),
panel.spacing = unit(2, "lines"),
panel.grid = element_blank())+
guides(fill = guide_legend(nrow = 1))
Output:
I am attempting to combine a legend for two plots with a shared blue line and unique bar colors (read and yellow). When plotting the code below only two of the three colored id's show up in the combined legend (red and blue) but I want the third color to show up as well in the combined legend.
For example
red as beaver temp1
yellow as beaver temp2
blue as line
Here the line is a stand in for what I am using for a moving average. I don't think facet wrapping this will work as there are additional variable parameters in my code (i.e. scale_y_continuous that have different secondary axis scales) but below is a reproducible example of the basic idea.
library(datasets)
library(ggplot2)
library(cowplot)
data(beavers)
colour <- c("bevTemp1" = "red", "line" = "blue", "bevTemp2" = "yellow" )
bev1 <- ggplot(beaver1, aes(x=time, y = temp)) +
geom_bar(stat = "identity", aes(colour = "bevTemp1"), fill = "red")+
coord_cartesian(ylim = c(35, 38)) +
geom_line(size = 1.5, aes(color = "line"))+
scale_color_manual(values = colour,
guide = guide_legend(override.aes = list(
border=c(NA, NA),
fill=c("red","blue"))))+
theme(legend.title = element_blank(), legend.position = "none")
bev2<- ggplot(beaver2, aes(x=time, y = temp)) +
geom_bar(stat = "identity", aes(colour = "bevTemp2"), fill = "yellow")+
coord_cartesian(ylim = c(35, 38)) +
geom_line(size = 1.5, aes(color = "line"))+
scale_color_manual(values = colour,
guide = guide_legend(override.aes = list(
border=c(NA, NA),
fill=c("yellow","blue"))))+
theme(legend.title = element_blank(), legend.position = "none")
cowplot::plot_grid(
cowplot::plot_grid(
bev1 ,
bev2,
align = 'h'),
cowplot::get_legend(bev1 + theme(legend.position = "bottom")),
nrow = 2, rel_heights = c(4, 1))
Suggestions...
You could build a dummy plot just to get the desired legend and add it to the final plot. I would also suggest using the line legend for the geom_line.
library(ggplot2)
# Create dummy data
df <- data.frame(class = c("bevTemp1","bevTemp2"),
x = 1:2,
y = 2:3)
# Create dummy plot just to extract the desired legend
p1<- ggplot(df, aes(x=x,y=y)) +
geom_col(aes(fill = class))+
geom_line(aes(col = "line"), size = 1.5)+
scale_fill_manual(values = c("red","yellow")) +
scale_color_manual(values = "blue")+
theme(legend.title = element_blank())
cowplot::plot_grid(
cowplot::plot_grid(
bev1 ,
bev2,
align = 'h'),
# Add the legend of the dummy plot
cowplot::get_legend(p1 + theme(legend.position = "bottom")),
nrow = 2, rel_heights = c(4, 1))
get_legend just retrieves the legend from the plot passed to this function, here bev1. So you need to also show bev2Temp in the legend of plot 1. You can add an additional id column to your dataset, make it a factor variable but in both datasets include bevTemp1/bevTemp2 as levels. In ggplot in scale_fill_manual, if you set drop = FALSE, all levels are shown:
library(datasets)
library(ggplot2)
library(cowplot)
data(beavers)
colour <- c("bevTemp1" = "red", "bevTemp2" = "yellow")
beaver1$id <- "bevTemp1"
beaver1$id <- factor(beaver1$id, levels = c("bevTemp1", "bevTemp2"))
beaver2$id <- "bevTemp2"
beaver2$id <- factor(beaver2$id, levels = c("bevTemp1", "bevTemp2"))
bev1 <- ggplot(beaver1, aes(x=time, y = temp, fill = id)) +
geom_bar(stat = "identity")+
coord_cartesian(ylim = c(35, 38)) +
geom_line(size = 1.5, aes(color = "line"))+
theme(legend.title = element_blank(), legend.position = "none") +
scale_fill_manual(values = c("bevTemp1" = "red", "bevTemp2" = "yellow"),
drop = FALSE) +
scale_colour_manual(values = c("line" = "blue"))
bev2<- ggplot(beaver2, aes(x=time, y = temp, fill = id)) +
geom_bar(stat = "identity")+
coord_cartesian(ylim = c(35, 38)) +
geom_line(size = 1.5, aes(color = "line"))+
theme(legend.title = element_blank(), legend.position = "none") +
scale_fill_manual(values = c("bevTemp1" = "red", "bevTemp2" = "yellow"),
drop = FALSE) +
scale_colour_manual(values = c("line" = "blue"))
cowplot::plot_grid(
cowplot::plot_grid(
bev1 ,
bev2,
align = 'h'),
cowplot::get_legend(bev1 + theme(legend.position = "bottom")),
nrow = 2, rel_heights = c(4, 1))
I have been writing some code for a class, and I have got stuck in how to remove the x and y labels from the boxplot. I am planning to place it within a 1st graph, so they are redundant.
If anyone also knows how to add a line at 0 to my line graph, that would be amazing aswell!
Code:
#load data up
library(readxl)
TempData <- read_excel("R Data/TempData.xlsx")
View(TempData)
#initiliase relevant packages #ggplot2 for creating data visulation and viridis to allow for colour gradients
library(ggplot2)
library(viridis)
#plot line graph
g1 <- ggplot(TempData, aes(x = Year, y = GAT, color = GAT)) +
geom_line(size = 1.5) +
geom_smooth(method=loess, se=TRUE, col = "black") +
scale_colour_gradient2(low = "green", mid = "yellow" , high = "red", midpoint=median(TempData$GAT)) +
labs(title = "Global Average Temperature", subtitle = "From 1850 to 2018") +
xlab("Year") + ylab ("Average Temperature") +
theme(plot.title = element_text(face = "bold", hjust = 0.5, size = 16)) +
theme(plot.subtitle = element_text(face = "italic", hjust = 0.5, size = 10, colour = "Orange")) +
theme_light()
plot(g1)
#plot boxplot
g2 <- ggplot(TempData, aes(x="Year", y=TempData$GAT)) + geom_boxplot(outlier.colour = "red", outlier.fill = "red",outlier.shape = 21, outlier.size = 1)
labs(x=" ", y=" ") +
stat_summary(fun.y = mean, geom = "point", size = 2.5, colour = "orange") +
theme_light()
plot(g2)
#arrange two graphs to boxplot sits in top corner of line graph
g1 + annotation_custom(ggplotGrob(g2), xmin = 1840, xmax = 1930, ymin = 0.20, ymax = 0.88)
you could use theme in the following way:
... + theme(axis.title.x=element_blank(), axis.title.y=element_blank())
This will remove the x,y labels of the plot