Formatting facet pie chart ggplot - r

I have a sample data frame as follows:
set.seed(87)
df = data.frame(
sample = rep(c("PB","PB","BM","BM"),8),
status = rep(c("healthy","myeloma"),16),
family = c(rep("CD4",16),rep("CD8",16)),
phenotype = rep(c("Tn","Tn","Tn","Tn","Tcm","Tcm","Tcm","Tcm","Tem","Tem","Tem","Tem","Temra","Temra","Temra","Temra"),2),
percent = sample(20:30,32,replace=T)
)
I want to plot the data in pie chart format also with faceting in both the x and y axis formatted like this nice diagram I found online:
However I only know how to facet by grouping the two variables (CD4/CD8 and healthy/myeloma) together first with the following code which can't give me the nice separation of the x axis variables into two rows:
df %>%
mutate(group = paste(family,status)) %>%
ggplot(aes(x = "",y=percent,fill = phenotype)) +
geom_bar(width = 1, stat = "identity") +
coord_polar("y", start=0) +
facet_grid(sample~group) +
theme(axis.text.x=element_blank(),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
panel.border = element_blank(),
panel.grid=element_blank(),
axis.ticks = element_blank())
Appreciate any ideas on how to make the whole diagram look more like the one online, thanks!

Maybe this is closer -
library(dplyr)
library(ggplot2)
df %>%
mutate(group = paste(family,status)) %>%
ggplot(aes(x = "",y=percent,fill = phenotype)) +
geom_bar(width = 1, stat = "identity") +
coord_polar("y", start=0) +
facet_grid(sample~group) +
theme_classic() +
theme(axis.text.x=element_blank(),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
panel.border = element_blank(),
panel.grid=element_blank(),
axis.ticks = element_blank(),
strip.background = element_blank(),
strip.text = element_text(size = 15, face = 'bold'),
legend.position="bottom")

Related

Make curved text on coord_polar() upright

suppose I have this dataset
data3 <- data.frame(
id = c(1:10),
marker = paste("Marker", seq(1, 10, 1)),
value = paste(rep(c(0,1), times = 2, length.out = 10))
) %>%
mutate(id = row_number(), angle = 90 - 360 * (id - 0.5) / n())
I want to make a chart like this:
[
Image taken from Royam et al, 2019
I have tried using coord_polar() with codes as follow:
ggplot(data = data3, aes(x = factor(id), y = 2, fill = factor(value), label = marker)) +
geom_bar(stat = 'identity', position = 'dodge') +
geom_text(hjust = 1.5, angle = data3$angle) +
coord_polar() +
scale_fill_manual(values = alpha(c('green', 'red'), 0.3), breaks = c(0, 1), labels = c('Upregulated', 'Downregulated')) +
guides(fill = 'none') +
theme(
axis.text.y = element_blank(),
axis.title.y = element_blank(),
axis.text.x = element_blank(),
axis.title.x = element_blank(),
axis.ticks = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor.y = element_blank(),
panel.border = element_blank(),
panel.background = element_blank()
)
Which returns this figure:
How can I make the labels kept upright? Additionally, am I going to the right direction in creating the sample plot? Is there any other command in ggplot2 which may create such a figure?
Thank you very much in advance

Combining and resizing barplot and ggplot

I have two plots I would like to combine. My data looks like this:
Year<-rep(2001:2005, each = 5)
name<-c("John","Ellen","Mark","Randy","Luisa")
Name<-c(rep(name,5))
Value<-sample(seq(0,25,by=1),25)
mydata<-data.frame(Year,Name,Value)
This is the first barplot:
tot<-aggregate(mydata$Value,list(mydata$Year),FUN=sum)
tot_y<-tot$x
tot_x<-tot$Group.1
tot_barplot <- ggplot(tot, aes(x=tot_x,y=tot_y)) +
geom_bar(stat = "identity",fill="#73D055FF") +
scale_y_continuous(limits = c(0, 125), breaks = seq(0, 125, by = 25)) +
#xlab("Pathways") +
#ylab("N° of species") +
theme(axis.line = element_blank(),
axis.text.x=element_blank(),
axis.text.y=element_text(size=14,margin=margin(l=10),colour="black"),
axis.ticks = element_blank(),
axis.title=element_blank(),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank())
tot_barplot
And this is the second plot:
p <- ggplot(mydata, aes(x=Year, y=Name, size = Value)) +
geom_point(aes(fill = Value,
alpha = I(as.numeric(Value > 0))), shape=21, colour = "black") +
scale_fill_viridis_c(option = "D", direction = -1,limits = c(1, 25), breaks=seq(1, 25, 5))+
scale_size_area(guide = "none") +
ylab("Name") +
theme(axis.line = element_blank(),
axis.text.x=element_text(size=11,margin=margin(b=10),colour="black"),
axis.text.y=element_text(size=13,margin=margin(l=10),colour="black",
face="italic"),
axis.ticks = element_blank(),
axis.title=element_text(size=18,face="bold"),
panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
panel.background = element_blank(),
legend.text = element_text(size=14),
legend.title = element_text(size=18))
p
I combine them like this:
grid.arrange(arrangeGrob(tot_barplot,p,nrow=2))
Now I would like to re-size the barplot to fit it better to the second plot (imagine that the original data produce a wider barplot where the bars start above the Name and end above the legend Value). I would like the bars of the barplot to be exactly centred above the line of points and the Year, but I am not very familiar with ggplot aesthetics.
Any suggestion would be appreciated. Thanks!

Dividing a chart in two parts

I have the code of two graphs that I want to separate into two. I would like to see half of these results on one graph and the other half on another since the current plot contains too much information. Here is the code for my charts:
Medellin7 <- Medellin4 %>%
filter(Medellin4$AÑO_T %in% c("2019"))
Medellin7
Medellin8 <- Medellin7 %>%
filter(Medellin7$MES_TURNO %in% c("06"))
Medellin8
ATENCIONFUNCIONARIO <- Medellin8 %>%
group_by(NOMBRE_SERVICIO, NOMBRE, NOMBRE_SERVICIO) %>%
summarize(TIEMPO = mean(TIEMPO)) %>%
ungroup() %>%
mutate(NOMBRE_SERVICIO = factor(NOMBRE_SERVICIO, levels = unique(NOMBRE_SERVICIO)),
NOMBRE = as.factor(NOMBRE))
# First Chart
grafico5 <- ggplot(data = ATENCIONFUNCIONARIO,
aes(x = NOMBRE_SERVICIO, y = TIEMPO, group = NOMBRE, colour = NOMBRE)) +
xlab("SERVICIO") + ylab("CANTIDAD") +
ggtitle("TIEMPO PROMEDIO ATENCIÓN FUNCIONARIO")+
theme(axis.text.x=element_text(angle=90,hjust=1)) +
theme(plot.title = element_text(hjust = 0.5))+
theme(panel.border = element_blank(), panel.grid.major = element_blank(),
panel.grid.minor = element_blank(), axis.line = element_line(colour = "white"))+
geom_line(lwd=1)
grafico5
Second Chart:
FUNCIONARIO <- Medellin1 %>%
group_by(AÑO_T, NOMBRE) %>%
summarise(TIEMPO = length(TIEMPO))
FUNCIONARIO <- FUNCIONARIO\[order(FUNCIONARIO$NOMBRE, decreasing = TRUE),\]
M<- ggplot(FUNCIONARIO, aes(factor(NOMBRE), TIEMPO, fill = factor(AÑO_T))) +
geom_bar(stat="identity", position="dodge")+
theme(axis.text.x=element_text(angle=90,hjust=1))+
xlab("MES")+
ylab("CANTIDAD")+
labs(fill="AÑO")+
ggtitle("DEMANDA MES")+
theme(plot.title = element_text(hjust = 0.5))+
theme(panel.border = element_blank(), panel.grid.major = element_blank(),
panel.grid.minor = element_blank(), axis.line = element_line(colour = "gray"))]
Splitting the plot into two identical plots seems like a strange choice. One alternative would be to use facet_wrap using Nombre as the facet variable. This would give you a clear look at each line in the chart. Your code would look something like this:
grafico5 <- ggplot(data = ATENCIONFUNCIONARIO,
aes(x = NOMBRE_SERVICIO, y = TIEMPO)) +
xlab("SERVICIO") + ylab("CANTIDAD") +
ggtitle("TIEMPO PROMEDIO ATENCIÓN FUNCIONARIO")+
theme(axis.text.x=element_text(angle=90,hjust=1)) +
theme(plot.title = element_text(hjust = 0.5))+
theme(panel.border = element_blank(), panel.grid.major = element_blank(),
panel.grid.minor = element_blank(), axis.line = element_line(colour = "white"))+
geom_line(lwd=1) +
facet_wrap(~Nombre)
Here's a reproducible example:
data(iris)
library(ggplot2)
ggplot(iris, aes(x=Sepal.Width, y=Sepal.Length)) +
geom_line() +
facet_wrap(~Species)
Which gives you:

geom_text labelling bars incorrectly

I am trying to create a graph in R with ggplot. The graph is fine until I try to add labels with geom_text.
Data:
year <-c(2016,2017,2016,2017,2016,2017,2016,2017,2016,2017,2016,2017,2016,2017)
age <- c("0-15","0-15","16-25","16-25","26-35","26-35","36-45","36-45","46-55","46-55","56-65","56-65","66+","66+")
deaths <- c(10,4,40,33,38,28,23,22,18,22,13,16,44,33)
age_group <- factor(age)
fyear <- factor(year)
ideaths <- data.frame(fyear,age_group,deaths)
This is the code I have so far
ggplot(data = ideaths,mapping = aes(x = age_group, y=deaths,
fill=fyear)) +
geom_bar(position = "dodge", stat="identity", width=0.5) +
geom_text(label=deaths,vjust=-0.5) + ggtitle("Figure 8.") +
scale_fill_manual(values=c("#7F7F7F","#94D451")) +
scale_y_continuous(breaks=seq(0,55,5)) + theme_light() +
theme(panel.border = element_blank(), panel.grid.major.x =
element_blank(), panel.grid.minor.y =
element_blank(),panel.grid.major.y = element_line( size=.1,
color="grey"), axis.title = element_blank(), legend.position
= "bottom", legend.title=element_blank(), plot.title
=element_text(size=10))
Which gives me this graph:
I searched for how to align the labels with the bars and found position=position_dodge(width=0.9)
However, this puts the label over the wrong bar for me.
If anyone has any idea of how to fix this, or what is causing it in the first place it would be greatly appreciated!
You need to put label = deaths inside aes() so ggplot knows that it needs to use the deaths column inside ideaths data frame not the standalone deaths vector
library(ggplot2)
ggplot(data = ideaths, aes(x = age_group, y = deaths, fill = fyear)) +
geom_col(position = position_dodge(width = 0.9)) +
geom_text(aes(x = age_group, y = deaths + 3, label = deaths),
position = position_dodge(width = 0.9)) +
ggtitle("Figure 8.") +
scale_fill_manual(values = c("#7F7F7F", "#94D451")) +
scale_y_continuous(breaks = seq(0, 55, 5)) +
theme_light() +
theme(
panel.border = element_blank(),
panel.grid.major.x = element_blank(),
panel.grid.minor.y = element_blank(),
panel.grid.major.y = element_line(size = .1, color = "grey"),
axis.title = element_blank(), legend.position = "bottom",
legend.title = element_blank(), plot.title = element_text(size = 10)
)
Created on 2018-11-19 by the reprex package (v0.2.1.9000)

How to fix "Error: Aesthetics must be either length 1 or the same as the data (28): yintercept"?

I'd like to make a forest plot for my project. Since it is not a typical forest plot built-in any R package, I found the first figure of this page is helpful to my goal, a side table accompanied with the forest plot:
https://mcfromnz.wordpress.com/2012/11/06/forest-plots-in-r-ggplot-with-side-table/
The code which produces that particular figure is pasted below (the original link:https://github.com/nzcoops/blog_code/blob/master/forest_plot.Rmd)
The problem that I ran into is in the "data_table" step. An error pop up when I type the following in R:
data_table
Error: Aesthetics must be either length 1 or the same as the data (28): yintercept
I guess the issue came from geom_hlinein data_table.
After some online search and some try-and-error, I still cannot get rid of that error message and wonder if I can get some help here. Thanks in advance for your help.
--Code that particular produce the first figure:
library(ggplot2)
library(gridExtra)
dat <- data.frame(group = factor(c("A","B","C","D","E","F","G"), levels=c("F","E","D","C","B","A","G")),
cen = c(3.1,2.0,1.6,3.2,3.6,7.6,NA),
low = c(2,0.9,0.8,1.5,2,4.2,NA),
high = c(6,4,2,6,5,14.5,NA))
theme_set(theme_bw())
theme_update(
axis.line = element_line(colour = "black"),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.border = element_blank(),
panel.background = element_blank(),
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
plot.margin = unit(c(0,0,0,0), "lines"))
p <- ggplot(dat,aes(cen,group)) +
geom_point(size=5, shape=18) +
geom_errorbarh(aes(xmax = high, xmin = low), height = 0.15) +
geom_vline(xintercept = 1, linetype = "longdash") +
scale_x_continuous(breaks = seq(0,14,1), labels = seq(0,14,1)) +
labs(x="Adjusted Odds Ratio", y="")
data_table <- ggplot(lab, aes(x = V05, y = V0, label = format(V1, nsmall = 1))) +
geom_text(size = 4, hjust=0, vjust=0.5) + theme_bw() +
geom_hline(aes(yintercept=c(6.5,7.5))) +
theme(panel.grid.major = element_blank(),
legend.position = "none",
panel.border = element_blank(),
axis.text.x = element_text(colour="white"),#element_blank(),
axis.text.y = element_blank(),
axis.ticks = element_line(colour="white"),#element_blank(),
plot.margin = unit(c(0,0,0,0), "lines")) +
labs(x="",y="") +
coord_cartesian(xlim=c(1,4.5))
lab <- data.frame(V0 = factor(c("A","B","C","D","E","F","G","A","B","C","D","E","F","G","A","B","C","D","E","F","G","A","B","C","D","E","F","G"),, levels=c("G","F","E","D","C","B","A")),
V05 = rep(c(1,2,3,4),each=7),
V1 = c("Occuption","Active","","Inactive","","Inactive","","Recreation","Inactive","","Active","","Inactive","","Gender","Men","Women","Men","Women","Men","Women","OR",3.1,2.0,1.6,3.2,3.6,7.6))
data_table <- ggplot(lab, aes(x = V05, y = V0, label = format(V1, nsmall = 1))) +
geom_text(size = 4, hjust=0, vjust=0.5) + theme_bw() +
geom_hline(aes(yintercept=c(6.5,7.5))) +
theme(panel.grid.major = element_blank(),
legend.position = "none",
panel.border = element_blank(),
axis.text.x = element_text(colour="white"),#element_blank(),
axis.text.y = element_blank(),
axis.ticks = element_line(colour="white"),#element_blank(),
plot.margin = unit(c(0,0,0,0), "lines")) +
labs(x="",y="") +
coord_cartesian(xlim=c(1,4.5))
The easiest fix would be separating geom_hline into 2 different calls
data_table <- ggplot(lab, aes(x = V05, y = V0, label = format(V1, nsmall = 1))) +
geom_text(size = 4, hjust=0, vjust=0.5) + theme_bw() +
geom_hline(aes(yintercept=c(6.5))) +
geom_hline(aes(yintercept=c(7.5))) +
theme(panel.grid.major = element_blank(),
legend.position = "none",
panel.border = element_blank(),
axis.text.x = element_text(colour="white"),#element_blank(),
axis.text.y = element_blank(),
axis.ticks = element_line(colour="white"),#element_blank(),
plot.margin = unit(c(0,0,0,0), "lines")) +
labs(x="",y="") +
coord_cartesian(xlim=c(1,4.5))
data_table
Created on 2018-03-31 by the reprex package (v0.2.0).
You don't need to use aes() with geom_hline (only use aes() if you want a horizontal line for every row of your data.) You can just do:
geom_hline(yintercept = c(6.5, 7.5))
This is explained in the help, see ?geom_hline for more details.

Resources