based on the sample dataset below, I Iam trying to make 2 graphs and place them side by side. I have tried using the cowplot package to do so. The final output was really messy.
Is there a way I could plot them side by side displaying only 1 legend, centralized on the bottom (since both graphs contain the same elements)?
df <- data.frame(Year = c(rep(2012,5), rep(2016,5),
rep(2012,5), rep(2016,5),
rep(2012,5), rep(2016,5)),
Category = rep(c('A1','A2','A3','A4','A5'),6),
Group = rep(c('T1','T1','T1','T1','T1',
'T2','T2','T2','T2','T2',
'T3','T3','T3','T3','T3'),2),
Variable = runif(30,0,100))
plot2012 <- ggplot(df, aes(x = Group, y = Variable)) +
geom_bar(aes(fill = Category), stat = 'identity') +
ylim(0,500) +
labs(y = 'Variable') +
theme(legend.position = 'bottom',
legend.title = element_blank(),
axis.title = element_text(size = 10),
legend.text = element_text(size = 10),
axis.text = element_text(size = 10))
plot2016 <- ggplot(df, aes(x = Group, y = Variable)) +
geom_bar(aes(fill = Category), stat = 'identity') +
ylim(0,500) +
labs(y = 'Variable') +
theme(legend.position = 'bottom',
legend.title = element_blank(),
axis.title = element_text(size = 10),
legend.text = element_text(size = 10),
axis.text = element_text(size = 10))
Any other general comments one the formatting/code are welcome
You can add facet_grid to your ggplot call.
ggplot(df, aes(x = Group, y = Variable)) +
geom_bar(aes(fill = Category), stat = 'identity') +
ylim(0,500) +
labs(y = 'Variable') +
# Generate plots as panel based on Year
facet_grid(. ~ Year) +
theme(legend.position = 'bottom',
legend.title = element_blank(),
axis.title = element_text(size = 10),
legend.text = element_text(size = 10),
axis.text = element_text(size = 10))
Related
I used ggpubr::ggarrange to create a multiple plot with a shared y- and x axis. The only issue that I am having is that the first plot, which does have the y axis is smaller than the other 3 plots which brings the whole figure out of proportion.
I am therefore looking for a solution to display only one y lab without bringing the first plot out of proportion to the other 3 plots. Help is highly appreciated as I have been searching for a solution to this problem since quiet some time already.
My approach so far was to remove the y lab from plot (p) 2,3,4 and leave it on p1.
This is my code:
library(ggplot2)
library(ggpubr)
library(dplyr)
p1 <- ggplot(arrange(ploughed1, Horizont), aes(Ferment, RAI_II, fill = factor(Horizont, levels=c("4","3","2","1"))))+
geom_bar(stat = "identity", position = "dodge")+
scale_fill_manual(values = c("#FF9933", "#CC6600","#663300","#000000"))+
guides(fill = guide_legend(reverse = TRUE))+
labs(fill="Horizon")+
ylim(0,200)+
theme_bw()+
facet_wrap(~compost)+
theme(strip.text = element_text(size = 7),
panel.spacing = unit(0.2, "lines"))+
geom_col(position = position_stack(reverse = TRUE))+
labs(x="Ferment", y = "RAI_II=Rooting*Scheme*Active", title = "P- ")
p2 <- ggplot(arrange(ploughed2, Horizont), aes(Ferment, RAI_II, fill = factor(Horizont, levels=c("4","3","2","1"))))+
geom_bar(stat = "identity", position = "dodge")+
scale_fill_manual(values = c("#FF9933", "#CC6600","#663300","#000000"))+
guides(fill = guide_legend(reverse = TRUE))+
labs(fill="Horizon")+
ylim(0,200)+
theme_bw()+
theme(axis.text.y = element_blank(),
panel.spacing = unit(0.2, "lines"),
strip.text = element_text(size = 7))+
facet_wrap(~compost)+
geom_col(position = position_stack(reverse = TRUE))+
labs(x="Ferment", title = "P+ ")+
rremove("ylab")
p3 <- ggplot(arrange(reduced1, Horizont), aes(Ferment, RAI_II, fill = factor(Horizont, levels=c("4","3","2","1"))))+
geom_bar(stat = "identity", position = "dodge")+
scale_fill_manual(values = c("#FF9933", "#CC6600","#663300","#000000"))+
guides(fill = guide_legend(reverse = TRUE))+
labs(fill="Horizon")+
ylim(0,200)+
theme_bw()+
theme(axis.text.y = element_blank(),
panel.spacing = unit(0.2, "lines"),
strip.text = element_text(size = 7))+
facet_wrap(~compost)+
geom_col(position = position_stack(reverse = TRUE))+
labs(x="Ferment", title = "RT- ")+
rremove("ylab")
p4 <- ggplot(arrange(reduced2, Horizont), aes(Ferment, RAI_II, fill = factor(Horizont, levels=c("4","3","2","1"))))+
geom_bar(stat = "identity", position = "dodge")+
scale_fill_manual(values = c("#FF9933", "#CC6600","#663300","#000000"))+
guides(fill = guide_legend(reverse = TRUE))+
labs(fill="Horizon")+
ylim(0,200)+
theme_bw()+
theme(axis.text.y = element_blank(),
panel.spacing = unit(0.2, "lines"),
strip.text = element_text(size = 7))+
facet_wrap(~compost)+
geom_col(position = position_stack(reverse = TRUE))+
labs(x="Ferment", title = "RT+ ")+
rremove("ylab")
ggarrange(p1, p2, p3, p4, nrow=1, common.legend = TRUE)
Output .png
Output image: 1
I also tried to solve it in the ggarrange function, without removing the y lab and text in p2,p3 and p4, which had the same result.
ggarrange(p1, p2+
theme(axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.y = element_blank() ), p3+
theme(axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.y = element_blank() ), p4+
theme(axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.y = element_blank() ) , nrow=1, common.legend = TRUE)
If other packages are an option for you, I would suggest to make use of patchwork. Using some convenience functions to reduce the duplicated code and some random example data to mimic your real data:
library(ggplot2)
library(patchwork)
library(dplyr)
ploughed1 <- data.frame(
Horizont = rep(1:4, 4),
RAI_II = runif(16, 10, 50),
Ferment = rep(c("-", "+"), each = 8),
compost = rep(c("- Compost", "+ Compost"), each = 4)
)
plot_fun <- function(x, title) {
ggplot(arrange(x, Horizont), aes(Ferment, RAI_II, fill = factor(Horizont, levels = c("4", "3", "2", "1")))) +
geom_bar(stat = "identity", position = "dodge") +
scale_fill_manual(values = c("#FF9933", "#CC6600", "#663300", "#000000")) +
guides(fill = guide_legend(reverse = TRUE)) +
ylim(0, 200) +
theme_bw() +
facet_wrap(~compost) +
theme(
strip.text = element_text(size = 7),
panel.spacing = unit(0.2, "lines")
) +
geom_col(position = position_stack(reverse = TRUE)) +
labs(x = "Ferment", y = "RAI_II=Rooting*Scheme*Active", fill = "Horizon", title = title)
}
remove_y <- theme(
axis.text.y = element_blank(),
axis.ticks.y = element_blank(),
axis.title.y = element_blank()
)
p <- list(
plot_fun(ploughed1, "P-"),
plot_fun(ploughed1, "P+") + remove_y,
plot_fun(ploughed1, "RT-") + remove_y,
plot_fun(ploughed1, "RT+") + remove_y
)
wrap_plots(p, nrow = 1) + plot_layout(guides = "collect")
Compared to patchwork where all facets are of the same width in each plot making use of ggpubr:ggarrange squeezes the facets in the first plot because of the y scale:
ggpubr::ggarrange(plotlist = p, nrow = 1, common.legend = TRUE)
I want to plot a dataframe (stats) with the coefficient and error bars, and automatically write the p-values above each point.
stats <- data.frame(Coefficient = c(-0.07,-0.04,-0.15173266),
p_value = c(.0765210755,0.5176050652,0.0001309025),
conf_low = c(-.1544418,-0.1686583,-0.2294873),
conf_high = c(0.007812205,0.084939487,-0.073978033),
Test = c("TestA","TestB","TestC"))
I am trying to make a function to plot the p-values above each Coefficient point. (The coord_flip in the plot below may also be throwing me off.
give.pval <- function(y){
return(c(x = Coefficient, label = stats$p_value))
}
The following ggplot is exactly what I need, except for the stat_summary line which I am doing incorrectly
ggplot(stats, aes(x = Test, y = Coefficient)) +
geom_point(aes(size = 6)) +
geom_errorbar(aes(ymax = conf_high, ymin = conf_low)) +
geom_hline(yintercept=0, linetype="dashed") +
#stat_summary(fun.data = give.pval, geom = "text") +
theme_calc() +
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
axis.text.x = element_text(size = 12, vjust = 0.5), axis.title.x = element_text(size = 16),
axis.text.y = element_text(size = 12), axis.title.y = element_blank(),
legend.position = "none",
plot.title = element_text(hjust = 0.5, size = 24)) +
coord_flip() +
ylab("Coefficient")
I would like the have this plot but with the appropriate p-value above each of the three Coefficient points.
Thanks for any advice.
This could be achieved with a geom_text layer where you map p_value on the label aes and some additional nudging
library(ggplot2)
stats <- data.frame(Coefficient = c(-0.07,-0.04,-0.15173266),
p_value = c(.0765210755,0.5176050652,0.0001309025),
conf_low = c(-.1544418,-0.1686583,-0.2294873),
conf_high = c(0.007812205,0.084939487,-0.073978033),
Test = c("TestA","TestB","TestC"))
ggplot(stats, aes(x = Test, y = Coefficient)) +
geom_point(aes(size = 6)) +
geom_errorbar(aes(ymax = conf_high, ymin = conf_low)) +
geom_hline(yintercept=0, linetype="dashed") +
geom_text(aes(label = p_value), nudge_x = .2) +
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
axis.text.x = element_text(size = 12, vjust = 0.5), axis.title.x = element_text(size = 16),
axis.text.y = element_text(size = 12), axis.title.y = element_blank(),
legend.position = "none",
plot.title = element_text(hjust = 0.5, size = 24)) +
coord_flip() +
ylab("Coefficient")
Is there a way to use a column calculated with dplyr in scale_x_continuous() from ggplot2 in the same pipeline?
p2 <- chat %>%
count(author) %>%
ggplot(aes(x = reorder(author, n), y = n, fill = n)) +
geom_bar(stat = "identity") +
coord_flip() +
theme_classic() +
scale_fill_viridis() +
scale_x_continuous(breaks = seq(0, **max(n)**, by = 250))
theme(
axis.title.x = element_blank(), axis.title.y = element_blank(),
legend.position = "none",
plot.title = element_text(size = 13, face = "bold", hjust = 0.5),
plot.subtitle = element_text(color = '#666664', size = 10, hjust = 0.5))
Basically, I'm counting the number of times a different author (factor column) appears in the dataframe. However, R is not letting me use n (which is then name of the column that count() returns) in scale_x_continuous. But it does within the ggplot() function.
Is there a way to do so? Or am I forced to do something like:
data <- chat %>%
count(author)
p2 <- ggplot(data, aes(x = reorder(author, n), y = n, fill = n)) +
geom_bar(stat = "identity") +
coord_flip() +
theme_classic() +
scale_fill_viridis() +
scale_x_continuous(breaks = seq(0, **max(data$n)**, by = 250))
theme(
axis.title.x = element_blank(), axis.title.y = element_blank(),
legend.position = "none",
plot.title = element_text(size = 13, face = "bold", hjust = 0.5),
plot.subtitle = element_text(color = '#666664', size = 10, hjust = 0.5))
Thanks in advance!
You can use curly braces and dot notation (relevant information in last part of the accepted answer in this question, and here):
library(tidyverse)
library(viridis)
#> Loading required package: viridisLite
p2 <- iris %>%
sample_n(100) %>%
count(Species) %>%
{
ggplot(., aes(x = reorder(Species, n), y = n, fill = n)) +
geom_bar(stat = "identity") +
coord_flip() +
theme_classic() +
scale_fill_viridis() +
scale_y_continuous(breaks = seq(0, max(.$n), by = 20)) +
theme(
axis.title.x = element_blank(), axis.title.y = element_blank(),
legend.position = "none",
plot.title = element_text(size = 13, face = "bold", hjust = 0.5),
plot.subtitle = element_text(color = '#666664', size = 10, hjust = 0.5)
)
}
p2
Created on 2019-11-24 by the reprex package (v0.3.0)
Please note that you did not provide any reproducible example, so I took iris as starting point and did some row sampling to get different frequencies for the Species count. If you update your question with a reproducible example I will update my answer.
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)
I am trying to plot a basic stack bar chart to present number of acceptations and rejections for n simulations. (one column)
How can I control which series gets on the top of the stack together with corresponding value label?
I tried two versions neither had worked. Either colors are wrong or the labels.
Version 1
#version 1
T <- c(1,0)
H0_Testing <- c("Accept","Reject")
Counter <- c(100,900)
Label= c("L","L")
barplotdata<- data.frame(H0_Testing,T,Counter,Label)
fill <- c("#E1B378","#5F9EA0")
chartlabels=c("Accepted1","Rejected1")
title="version 1"
#Ploting
ggplot(barplotdata,aes(x=Label,y=Counter,fill=factor(T))) + geom_bar(stat ="identity",width=.2)+
geom_text(data=barplotdata, aes(label =Counter, y = Counter, size=4), show_guide = F)+
scale_fill_manual(labels=chartlabels, values=fill) +
theme(legend.title = element_blank()) +
theme(plot.title = element_text(size = 10),
axis.title.x = element_text(face="bold",size = 9), axis.title.y = element_text(face="bold",size = 8),
axis.text.x = element_text(size=8),axis.text.y = element_text(size=7),legend.text = element_text(size=7.5))+
ggtitle(title)
Version 2
#version 2
T <- c(0,1)
H0_Testing <- c("Reject","Accept")
Counter <- c(900,100)
Label= c("L","L")
barplotdata<- data.frame(H0_Testing,T,Counter,Label)
fill <- c("#5F9EA0","#E1B378")
chartlabels=c("Rejected2","Accepted2")
title="version 2"
#Ploting
ggplot(barplotdata,aes(x=Label,y=Counter,fill=factor(T))) + geom_bar(stat ="identity",width=.2)+
geom_text(data=barplotdata, aes(label =Counter, y = Counter, size=4), show_guide = F)+
scale_fill_manual(labels=chartlabels, values=fill) +
theme(legend.title = element_blank()) +
theme(plot.title = element_text(size = 10),
axis.title.x = element_text(face="bold",size = 9), axis.title.y = element_text(face="bold",size = 8),
axis.text.x = element_text(size=8),axis.text.y = element_text(size=7),legend.text = element_text(size=7.5))+
ggtitle(title)
New Plot:
T <- c(0,1)
H0_Testing <- c("Reject","Accept")
Counter <- c(900,100)
Label= c("L","L")
barplotdata<- data.frame(H0_Testing,T,Counter,Label)
fill <- c("#5F9EA0","#E1B378")
chartlabels=c("Rejected2","Accepted2")
title="version 2"
ggplot(barplotdata,aes(x=Label,y=Counter,fill=rev(factor(Counter)))) + geom_bar(stat ="identity",width=.2)+
geom_text(data=barplotdata, aes(label =rev(factor(Counter)), size=4), show.legend = F)+
scale_fill_manual(labels=chartlabels, values=fill) +
theme(legend.title = element_blank()) +
theme(plot.title = element_text(size = 10),
axis.title.x = element_text(face="bold",size = 9), axis.title.y = element_text(face="bold",size = 8),
axis.text.x = element_text(size=8),axis.text.y = element_text(size=7),legend.text = element_text(size=7.5))+
ggtitle(title)
ggplot(barplotdata,aes(x=Label,y=Counter,fill=factor(Counter))) + geom_bar(stat ="identity",width=.2)+
geom_text(data=barplotdata, aes(label =rev(factor(Counter)), size=4), show.legend = F)+
scale_fill_manual(labels=c("Accepted2","Rejected2"), values=fill) +
theme(legend.title = element_blank()) +
theme(plot.title = element_text(size = 10),
axis.title.x = element_text(face="bold",size = 9), axis.title.y = element_text(face="bold",size = 8),
axis.text.x = element_text(size=8),axis.text.y = element_text(size=7),legend.text = element_text(size=7.5))+
ggtitle(title)
Finally, if you want to switch the tiles:
ggplot(barplotdata,aes(x=Label,y=rev(Counter),fill=factor(Counter))) + geom_bar(stat ="identity",width=.2)+
geom_text(data=barplotdata, aes(label =rev(factor(Counter)), size=4), show.legend = F)+
scale_fill_manual(labels=c("Rejected2","Accepted2"), values=fill) +
theme(legend.title = element_blank()) +
theme(plot.title = element_text(size = 10),
axis.title.x = element_text(face="bold",size = 9), axis.title.y = element_text(face="bold",size = 8),
axis.text.x = element_text(size=8),axis.text.y = element_text(size=7),legend.text = element_text(size=7.5))+
ggtitle(title)
Note, for this third plot I added y=rev(Counter) in the aesthetics call.
as opposed to (your original plot Version 2):
#Ploting
ggplot(barplotdata,aes(x=Label,y=Counter,fill=factor(T))) + geom_bar(stat ="identity",width=.2)+
geom_text(data=barplotdata, aes(label =Counter, y = Counter, size=4), show.legend = F)+
scale_fill_manual(labels=chartlabels, values=fill) +
theme(legend.title = element_blank()) +
theme(plot.title = element_text(size = 10),
axis.title.x = element_text(face="bold",size = 9), axis.title.y = element_text(face="bold",size = 8),
axis.text.x = element_text(size=8),axis.text.y = element_text(size=7),legend.text = element_text(size=7.5))+
ggtitle(title)
The key difference for the bars is: fill=rev(factor(T) -notice that i reversed the factor level with the rev() command. For the text, notice that I removed y=Counter from geom_text() and changed the label value to rev(factor(Counter)). Also, for the second plot I manually set the legend items.
UPDATE
As per the OP's request in the comments, "I would like to change two more formats, decrease the font of the value labels and get rid of the T below x axis. Do you know how could I do the formatting?"
To decrease the font size, move size out of the aesthetics (you can also get rid of show.legend=F or show_guide=F). To get rid of the axis label you would add theme(axis.ticks = element_blank(), axis.text.x = element_blank())+ylab("Counter") -that removes the letter L and the tick mark which is what I think you meant when you said T. The code for both within the ggplot call is:
ggplot(barplotdata,aes(x=Label,y=rev(Counter),fill=factor(Counter))) + geom_bar(stat ="identity",width=.2)+
geom_text(data=barplotdata, aes(label =rev(factor(Counter))),size=2)+
scale_fill_manual(labels=c("Rejected2","Accepted2"), values=fill) +
theme(legend.title = element_blank()) +
theme(plot.title = element_text(size = 10),
axis.title.x = element_text(face="bold",size = 9), axis.title.y = element_text(face="bold",size = 8),
axis.text.x = element_text(size=8),axis.text.y = element_text(size=7),legend.text = element_text(size=7.5))+
ggtitle(title)+theme(axis.ticks = element_blank(), axis.text.x = element_blank())+ylab("Counter")