ggplot2: missing legend and how to add? - r

I want to plot a bar and line chart from a dataframe. Code below,
library("ggplot2")
numb <- c(1,2,3,4,5,6,7,8,9)
mydist <- c(53.846154,15.384615,15.384615,7.692308,7.692308,0,0,0,0)
basedist <- c(30.103,17.609126,12.493874,9.691001,7.918125,6.694679,5.799195,5.115252,4.575749)
df <- data.frame(numb, mydist, basedist)
ggplot(data=df,aes(x=numb)) +
geom_bar(stat="identity", aes(y=mydist), colour="green", fill="green") +
geom_line(aes(y=basedist,group=1, colour="base distribution")) +
geom_point(aes(y=basedist), colour="red") +
ggtitle("My Chart") +
labs(x="numb", y="percentage") +
scale_x_discrete(limits=c("1","2","3","4","5","6","7","8","9")) +
scale_y_continuous(breaks=seq(0,100,10)) +
theme(axis.title.x = element_text(size=10, colour ="#666666")) +
theme(axis.title.y = element_text(size=10, color="#666666")) +
theme(plot.title = element_text(size=16, face="bold", hjust=0, color="#666666")) +
theme(axis.text = element_text(size=12)) +
theme(legend.title = element_text(colour="white", size = 16, face='bold'))
Result is not I wanted because there is no legend for the bars
I reproduced the chart I need with the same data set in Excel below,
What do I need to change in my code to get the chart I need?
Thanks,
Lobbie

Here is a brief example. In general, I would recommend you reformat ggplot() assignment to make debugging easier. i.e. gp <- gp +
gp <- ggplot(data=df, aes(x=numb))
gp <- gp + geom_bar( aes(y = mydist, fill = "green"), stat="identity", color="green")
gp <- gp + geom_line( aes( y = basedist, group = 1, colour = "base distribution"))
gp <- gp + scale_fill_manual(values = "green", labels = "my distribution")
gp <- gp + geom_point(aes(y=basedist), colour="red")
gp <- gp + ggtitle("My Chart")
gp <- gp + labs(x="numb", y="percentage")
gp <- gp + scale_x_discrete(limits=c("1","2","3","4","5","6","7","8","9"))
gp <- gp + scale_y_continuous(breaks=seq(0,100,10))
gp <- gp + theme(axis.title.x = element_text(size=10, colour ="#666666"))
gp <- gp + theme(axis.title.y = element_text(size=10, color="#666666"))
gp <- gp + theme(plot.title = element_text(size=16, face="bold", hjust=0, color="#666666"))
gp <- gp + theme(axis.text = element_text(size=12))
gp <- gp + theme(legend.title = element_text(colour="white", size = 16, face='bold'))
gp <- gp + theme(legend.key = element_blank(), legend.title=element_blank(), legend.box ="vertical")
gp

Without changing much of the original code, you only need to put your fill into aes mapping, then add the scale to set the colour values and labels:
ggplot(data=df,aes(x=numb)) +
geom_bar(stat="identity", aes(y=mydist, fill="green"), colour="green") +
geom_line(aes(y=basedist,group=1, colour="base distribution")) +
geom_point(aes(y=basedist), colour="red") +
ggtitle("My Chart") +
labs(x="numb", y="percentage") +
scale_x_discrete(limits=c("1","2","3","4","5","6","7","8","9")) +
scale_y_continuous(breaks=seq(0,100,10)) +
scale_fill_manual(values = "green", labels = "my distribution") +
theme(axis.title.x = element_text(size=10, colour ="#666666")) +
theme(axis.title.y = element_text(size=10, color="#666666")) +
theme(plot.title = element_text(size=16, face="bold", hjust=0, color="#666666")) +
theme(axis.text = element_text(size=12)) +
theme(legend.title = element_text(colour="white", size = 16, face='bold'))

Related

use if else within ggplot chunk to change colour palette

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)

How to turn axis labels into shapes?

I'm trying to add boxes to replace the Y axis labels, such as in this figure.
I'm using ggplot but any other R package would work too.
input <- data.frame(
Pre.Subtype=c("Basal sq.", "Basal Sq.", "Basal sq.", "Neuronal", "Luminal", "Luminal", "Luminal"),
Post.Subtype=c("Basal sq.", "No tumor", "Luminal inf.", "Basal sq.", "Luminal", "Luminal pap.", "No tumor"),
Number.of.Patients=c(2,3,4,5,2,4,4), Percentage=c(34,23,23,53,20,34,56))
ggplot(data=input, aes(x=Pre.Subtype, y=Percentage, fill=Post.Subtype)) +
geom_bar(position = 'dodge', stat='identity') +
theme_classic() +
theme( axis.text.y = element_text(face="bold", size=12, colour="black"), axis.title=element_text(size=16,face="bold")) +
theme(legend.text=element_text(size=12), legend.title = element_text(size=14, face="bold")) +
labs(x= "Pre", y="Percentage", title="Post") +
geom_text(aes(label=Number.of.Patients), position=position_dodge(width=0.9), vjust=0.5, hjust=-0.3) +
scale_fill_manual(values=c("#fed976", "#7fcdbb", "#4d004b", "grey"), name="") +
theme(text = element_text(size=20), axis.text.x = element_text(size=13, face="bold", colour="black")) +
theme(plot.title = element_text(hjust = 0.5, face="bold", size=16), axis.ticks.y = element_blank()) +
coord_flip()
You can set clip = "off" in coord_flip as well as ensuring the y limit doesn't drop below zero:
... + coord_flip(ylim = c(0,50), clip = "off") + ...
Now you can draw a geom_rect outside of the plot area:
... + geom_rect(aes(xmin = 0.55, xmax = 0.85, ymin = -10, ymax = -7),
fill = "blue", size = 2, colour = "darkblue")
Which looks something like this:
Or use a geom_label:
geom_label(aes(label = "2", x = 0.55, y = -7), fill = "blue", size = 5, colour = "white")
Like this:
Of course, you'll need to add multiple geoms to get this effect for each category.
For a more automated way to do this, I suggest generating two separate plots, and combining them using ggarrange as shown below.
I have also fixed an issue where different bars were showing up in different widths in your original code.
library(tidyverse)
library(ggpubr)
input <- data.frame(
Pre.Subtype=c("Basal sq.", "Basal Sq.", "Basal sq.", "Neuronal", "Luminal", "Luminal", "Luminal"),
Post.Subtype=c("Basal sq.", "No tumor", "Luminal inf.", "Basal sq.", "Luminal", "Luminal pap.", "No tumor"),
Number.of.Patients=c(2,3,4,5,2,4,4), Percentage=c(34,23,23,53,20,34,56))
p1 <- ggplot(data=input, aes(x=Pre.Subtype, y=Percentage, fill=Post.Subtype)) +
#geom_bar(position = 'dodge', stat='identity') +
geom_col(position = position_dodge2(width = 0.9, preserve = "single")) +
theme_classic() +
theme( axis.text.y = element_blank(), axis.title.y = element_blank(), axis.title.x=element_text(size=16,face="bold")) +
theme(legend.text=element_text(size=12), legend.title = element_text(size=14, face="bold")) +
labs(x= "Pre", y="Percentage", title="Post") +
geom_text(aes(label=Number.of.Patients), position=position_dodge(width=0.9), vjust=0.5, hjust=-0.3) +
scale_fill_manual(values=c("#fed976", "#7fcdbb", "#4d004b", "grey", "red"), name="") +
theme(text = element_text(size=20), axis.text.x = element_text(size=13, face="bold", colour="black")) +
theme(plot.title = element_text(hjust = 0.5, face="bold", size=16), axis.ticks.y = element_blank()) +
scale_y_continuous(expand = c(0,0)) +
coord_flip()
p2 <- ggplot(data=input, aes(x=Pre.Subtype, y=Percentage)) +
theme_void() +
scale_y_continuous(expand = c(0,0)) +
geom_label(data = (input %>% group_by(Pre.Subtype) %>%
summarise_at(c('Number.of.Patients'),sum)), aes(label=Number.of.Patients, y = -0.1), fill = 'blue', color = 'white') +
coord_flip() + labs(title = 'Pre') + theme(plot.title = element_text(hjust = 0.5)) + theme(plot.margin = unit(c(0,-1,0,0), "cm"))
ggarrange(p2,p1, widths = c(0.1,0.9), align = "h")
This will give you the picture below.

Individual axis limits with scale(expand) and scale=free in facetted ggplots

library(ggplot2)
df <- data.frame(Treatment=c("A", "B","A","B"), Value=c(3,4, 20,2), SE=c(1,1,5,1), Type=c("c1","c1","c2","c2"))
p1 <- ggplot(df, aes(Treatment, Value,fill=Treatment)) +
geom_bar(stat="identity", col="Black") +
geom_errorbar(aes(ymax = Value + SE, ymin=Value), col="black") +
facet_wrap(~Type, scale="free_y") +
theme(panel.background = element_blank(),
panel.border = element_rect(colour = "black", fill=NA),
strip.background = element_blank())
p1
I want to remove the white space between bar and x-axis:
p1 + scale_y_continuous(expand = c(0,0))
This also removes white space between the geom and the maximum of the y-axis. One way to prevent this is to control the limits of the y-axis
p1 + scale_y_continuous(expand = c(0,0), limits=c(0,26))
But now panel c1 has lots of white space, as limits apparently overrides scale="free", which is especially irrating when the panels are arranged in columns.
So, i need to have the expand-argument and scale="free" active at the same time. Is it possible?
You may want to use a geom_blank():
Please be considerate and try not to confound the user! This type of transformation can be dangerous!
library(ggplot2)
df <- data.frame(Treatment=c("A", "B","A","B"), Value=c(3,4, 20,2), SE=c(1,1,5,1), Type=c("c1","c1","c2","c2"))
ggplot(df, aes(Treatment, Value,fill=Treatment)) +
geom_bar(stat="identity", col="Black") +
geom_errorbar(aes(ymax = Value + SE, ymin=Value), col="black") +
geom_blank(aes(y=Value + SE + 1)) +
facet_wrap(~Type, scale="free_y") +
theme(panel.background = element_blank(),
panel.border = element_rect(colour = "black", fill=NA),
strip.background = element_blank()) +
scale_y_continuous(expand = c(0,0))
Or:
ggplot(df, aes(Treatment, Value,fill=Treatment)) +
geom_bar(stat="identity", col="Black") +
geom_errorbar(aes(ymax = Value + SE, ymin=Value), col="black") +
geom_blank(aes(y=Value + 2 * SE)) +
facet_wrap(~Type, scale="free_y") +
theme(panel.background = element_blank(),
panel.border = element_rect(colour = "black", fill=NA),
strip.background = element_blank()) +
scale_y_continuous(expand = c(0,0))
Created on 2018-05-17 by the reprex package (v0.2.0).

ggplot no grid visual on top of imported image

I'm trying to plot some data on top of an imported image using ggplot2. However I can not get a visual grid in the plot..
Here is a simplified example to illustrate my issue:
library(ggplot2)
library(scales)
library(jpeg)
library(scales)
library(grid)
#picture from internet
myurl <- "http://upload.wikimedia.org/wikipedia/commons/9/95/Apollonian_spheres.jpg"
z <- tempfile()
download.file(myurl,z,mode="wb")
pic <- readJPEG(z)
file.remove(z) # cleanup
x <- sample(1:10, replace=T, 10)
y <- c("a","b","c","d","e","f","g","h","i", "j")
df <- data.frame(y,x)
p <-ggplot(df, aes(y, x, fill=y)) +
annotation_custom(rasterGrob(pic, width=unit(1,"npc"), height=unit(1,"npc")),
-Inf, Inf, -Inf, Inf) +
geom_bar(stat = "identity", fill="darkorange",width=0.8, alpha=0.75 )+
#geom_text(aes(label=data2$Attributes), vjust=1.5,colour="black")
coord_flip() + ggtitle("Something")+ theme_classic() +
labs(y = "yyy", x = "xxx") + guides(fill = guide_legend(reverse=TRUE))+
theme(axis.text.y = element_blank()) + theme(plot.title = element_text(size=20))+
theme(axis.title.x = element_text(size = 16))+ theme(axis.title.y = element_text(size = 16))+
theme(legend.text = element_text( size = 14)) + theme(legend.title = element_text( size = 16))+
theme(panel.grid.major = element_line(colour = "white", linetype = "dotted"))
p
#without picture works fine
p <-ggplot(df, aes(y, x, fill=y)) +
geom_bar(stat = "identity", fill="darkorange",width=0.8, alpha=0.75 )+
#geom_text(aes(label=data2$Attributes), vjust=1.5,colour="black")
coord_flip() + ggtitle("Something")+ theme_classic() +
labs(y = "yyy", x = "xxx") + guides(fill = guide_legend(reverse=TRUE))+
theme(axis.text.y = element_blank()) + theme(plot.title = element_text(size=20))+
theme(axis.title.x = element_text(size = 16))+ theme(axis.title.y = element_text(size = 16))+
theme(legend.text = element_text( size = 14)) + theme(legend.title = element_text( size = 16))+
theme(panel.grid.major = element_line(colour = "black", linetype = "dotted"))
p
Any ideas?

How to specify different palettes and line size within a single ggplot2 plot

I'm displaying four distributions within the same ggplot2 graph with the following code (data downloadable there: https://www.dropbox.com/s/l5j7ckmm5s9lo8j/1.csv?dl=0):
require(reshape2)
library(ggplot2)
library(RColorBrewer)
fileName = "./1.csv" # downloadable there: https://www.dropbox.com/s/l5j7ckmm5s9lo8j/1.csv?dl=0
mydata = read.csv(fileName,sep=",", header=TRUE)
dataM = melt(mydata,c("bins"))
ggplot(data=dataM, aes(x=bins, y=value, colour=variable)) +
xlab("bins") + ylab("freq") + geom_line(size = .5, alpha = .9) +
scale_colour_brewer(type = "qual", palette = 7) +
geom_line(size = .5, alpha = .9) +
theme_bw() +
theme(plot.background = element_blank()
,panel.grid.minor = element_blank()
,axis.line = element_blank()
,legend.key = element_blank()
,legend.title = element_blank()) +
scale_y_continuous(expand=c(0,0)) +
scale_x_continuous(expand=c(0,0))
How to change this graph so that B, E and W appear according to a specific palette (say: scale_colour_brewer) with a width of .5, while R appears in scale_colour_brewer(type = "qual", palette = 7) with a width of 1?
You can call subsets of your data in seperate geom_line's:
ggplot() +
geom_line(data=dataM[dataM$variable!="R",], aes(x=bins, y=value, colour=variable), size = .5, alpha = .9) +
geom_line(data=dataM[dataM$variable=="R",], aes(x=bins, y=value, colour=variable), size = 1.5, alpha = .9) +
scale_colour_brewer(type = "qual", palette = 7) +
theme_bw() +
theme(plot.background = element_blank(), panel.grid.minor = element_blank(), axis.line = element_blank(),
legend.key = element_blank(), legend.title = element_blank()) +
scale_y_continuous("freq", expand=c(0,0)) +
scale_x_continuous("bins", expand=c(0,0))
this gives:
Another solution (as suggested by #baptiste) is setting the size and colour scales manually:
ggplot(data=dataM, aes(x=bins, y=value, colour=variable, size = variable)) +
geom_line(alpha = .9) +
scale_colour_manual(breaks=c("B","E","W","R"), values=c("green","orange","blue","pink")) +
scale_size_manual(breaks=c("B","E","W","R"), values=c(0.5,0.5,0.5,1.5)) +
theme_bw() +
theme(plot.background = element_blank(), panel.grid.minor = element_blank(), axis.line = element_blank(),
legend.key = element_blank(), legend.title = element_blank()) +
scale_y_continuous("freq", expand=c(0,0)) +
scale_x_continuous("bins", expand=c(0,0))
this gives more or less the same result:
ggplot(aes(x=bins, y=value, colour=variable)) +
geom_line(data=dataM[dataM$variable!="R",]) +
geom_line(data=dataM[dataM$variable=="R",])

Resources