With ggplot2 and GGally, I created this bar chart with proportions:
ggplot(mtcars, aes(x = factor(cyl), by = 1)) +
geom_bar(fill = "steelblue", stat = "prop") +
geom_text(aes(label = scales::percent(after_stat(prop), accuracy = 1)), stat = "prop", nudge_y = 0.5) +
theme_minimal() +
theme(aspect.ratio = 1.5)
However, on the y axis, I would like to change that to reflect the percentages on the bars. I would like to avoid hard coding the values like ylim = "40", but let it use the values in the chart.
Try this:
ggplot(mtcars, aes(x = cyl)) +
geom_bar(aes(y = ..prop..), fill = "steelblue", stat = "count") +
geom_text(aes(label = scales::percent(..prop..), y = ..prop.. ), stat= "count", vjust = -.5) +
ylim(0, 0.5) +
ylab("") +
theme_minimal() +
theme(aspect.ratio = 1.5)
Edit: if you want a factor on x axis try
ggplot(mtcars, aes(x = factor(cyl))) +
geom_bar(aes(y = (..count..)/sum(..count..)), fill = "steelblue", stat = "count") +
geom_text(aes(label = scales::percent(round((..count..)/sum(..count..), 2)),
y = ((..count..)/sum(..count..))), stat = "count", vjust = -.25) +
ylim(0, 0.5) +
ylab("") +
theme_minimal() +
theme(aspect.ratio = 1.5)
Edit2: with the GGally package you can use:
ggplot(mtcars, aes(x = factor(cyl), by = 1)) +
geom_bar(aes(y = ..prop..), fill = "steelblue", stat = "prop") +
geom_text(aes(label = scales::percent(..prop..), y = ..prop.. ), stat = "prop", vjust = -.5) +
ylim(0, 0.5) +
ylab("") +
theme_minimal() +
theme(aspect.ratio = 1.5)
Related
I would like to make my data have different colors for species and different patterns for sex. However, I can only set to make it different colors according to the sex. Here is my data,
data
This is how I run my script,
#making bar plot
library(readr)
library(ggplot2)
# loading and checking the data
data_summary <- read_csv("trial.csv")
print(data_summary)
# coloured barplot
ggplot(data_summary, aes(x = factor(species), y = mean, fill = sex)) +
geom_bar(stat = "identity", position = "dodge", show.legend = FALSE) +
geom_errorbar(aes(ymin=mean-sd, ymax=mean+sd), position = position_dodge(0.9), width = 0.2, show.legend = FALSE) +
labs(x="", y="") + theme_bw() +
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()) +
theme(legend.position = c(0.1, 0.75)) + ylim(0, 80) +
scale_fill_manual(values=c("#870A30","#D3D3D3"))
This can be done using fill = interaction(..,..):
library(ggplot2)
ggplot(data_summary, aes(x = factor(species), y = mean, fill = interaction(species,sex))) +
geom_bar(stat = "identity", position = "dodge", show.legend = FALSE) +
geom_errorbar(aes(ymin=mean-sd, ymax=mean+sd), position = position_dodge(0.9), width = 0.2, show.legend = FALSE) +
labs(x="", y="") +
theme_bw() +
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()) +
theme(legend.position = c(0.1, 0.75)) + ylim(0, 80) +
scale_fill_manual(values= c("#870A30", '#009E73', '#CC79A7', "#D3D3D3"))
An option could be using ggplot_build and add a vector of four colors (you change this to what you want) to the fill column of the bars layer like this:
library(ggplot2)
p <- ggplot(data_summary, aes(x = factor(species), y = mean, fill = sex)) +
geom_bar(stat = "identity", position = "dodge", show.legend = FALSE) +
geom_errorbar(aes(ymin=mean-sd, ymax=mean+sd), position = position_dodge(0.9), width = 0.2, show.legend = FALSE) +
labs(x="", y="") + theme_bw() +
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()) +
theme(legend.position = c(0.1, 0.75)) + ylim(0, 80) +
scale_fill_manual(values=c("#870A30","#D3D3D3"))
q <- ggplot_build(p)
q$data[[1]]$fill <- c("#870A30","#D3D3D3", '#009E73', '#CC79A7')
q <- ggplot_gtable(q)
plot(q)
Created on 2023-01-02 with reprex v2.0.2
You can use ggpattern to get different patterns per sex and different colors per species:
library(ggplot2)
library(ggpattern)
ggplot(data_summary, aes(x = species, y = mean, fill = species, group = sex)) +
geom_col_pattern(position = "dodge", aes(pattern = sex),
pattern_fill = "white", pattern_color = "white",
pattern_angle = 45, show.legend = FALSE) +
geom_errorbar(aes(ymin=mean-sd, ymax=mean+sd), position = position_dodge(0.9),
width = 0.2, show.legend = FALSE) +
labs(x = NULL, y = NULL) +
theme_classic() +
theme(panel.border = element_rect(linewidth = 0.5, fill = NA)) +
ylim(0, 80) +
scale_fill_manual(values = c("#870A30" ,"#D3D3D3"))
There is a nice package called ggpattern which offers hatching for geoms. Unfortunately it is not available for the R version I am using.
But I would like to offer different alpha values for the fill color.
The alpha itself can defined like scale_alpha_manual(values = c(.5,1)).
library(ggplot2)
data_summary <- read.table(text = "
species,sex,mean,sd,tukey
species_a,female,67,4.17,a
species_b,male,62.2,4.8,a
species_b,female,61.3,6.43,a
species_a,male,49.7,16.2,a
", header = T, sep = ','
)
# coloured barplot
ggplot(data_summary, aes(x = factor(species), y = mean, fill = sex, alpha = species)) +
geom_bar(stat = "identity", position = "dodge", show.legend = FALSE) +
geom_errorbar(aes(ymin=mean-sd, ymax=mean+sd), position = position_dodge(0.9), width = 0.2, show.legend = FALSE) +
labs(x="", y="") + theme_bw() +
theme(panel.grid.major = element_blank(), panel.grid.minor = element_blank()) +
theme(legend.position = c(0.1, 0.75)) + ylim(0, 80) +
scale_fill_manual(values=c("#870A30","#D3D3D3")) +
scale_alpha_manual(values = c(.5,1))
ggplot(aes(x=MALE, y=AMOUNT, fill=MALE)) + geom_bar(stat="summary", fun="mean") +
ylab("Avg Amount") + theme(axis.title.x = element_blank())
How can I add the y value to the top of the bars given I've already created stat='summary' & fun='mean' when I created the graph?
To add the y value as label on top of your bars you can do:
geom_text(aes(label = after_stat(y)), stat = "summary", fun = "mean", vjust = -.1)
Using mtcars as example data and with some additional formatting of the label:
library(ggplot2)
ggplot(mtcars, aes(x = factor(cyl), y = mpg, fill = factor(cyl))) +
geom_bar(stat = "summary", fun = "mean") +
geom_text(aes(label = after_stat(sprintf("%.1f", y))), stat = "summary", fun = "mean", vjust = -.1) +
ylab("Avg Amount") +
theme(axis.title.x = element_blank())
I have the following code:
ggplot(pred_grid,
aes(x = x,
y = y)) +
geom_smooth(
aes(
ymin = lwr2, ymax = upr2,
fill = group, colour = group), stat = "identity") +
theme_gray(base_size = 17) +
scale_x_continuous(labels = scales::comma) +
scale_y_continuous(labels = scales::comma)
I then attempted to add dashed lines to signify the confidence intervals using the following code.
ggplot(pred_grid,
aes(x = x,
y = y)) +
geom_smooth(
aes(
ymin = lwr2, ymax = upr2,
fill = brand, colour = brand), stat = "identity") +
geom_line(aes(y = lwr2), linetype = "dashed") +
geom_line(aes( y = upr2), linetype = "dashed") +
theme_gray(base_size = 17) +
scale_x_continuous(labels = scales::comma) +
scale_y_continuous(labels = scales::comma)
However, the chart comes back looking like this.
What am I doing wrong?
I am trying to make the y axis of the second plot over 2 lines. Using '\n' for the first plot worked fine but using it on the second makes the text in odd places (maybe because of the italics).
p1 <- ggplot(data = new_data) +
geom_line(mapping = aes(x = Date,
y = Proportion,
group = Species,
colour = Species)) +
scale_colour_manual(values=c(Golden_Trevally="goldenrod2",
Red_Snapper="firebrick2",
Sharksucker_Remora="darkolivegreen3",
Juvenile_Remora="aquamarine2")) +
xlab("Date (2014-2018)") +
ylab("Total Presence \n Per Month ") +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)) +
theme(legend.position="top") +
labs(colour = "Hitchhiker Species")
new_data_counts <- new_data %>% select(Date, Count)
new_data_counts <- new_data_counts[!duplicated(new_data_counts),]
p2 <- ggplot(data = new_data_counts) +
geom_bar(mapping = aes(x = Date, y = Count), stat = 'identity') +
xlab("Date (2014-2018)") +
ylab("Total Number of "~italic(\nM.alfredi)~" Encounters") +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))
grid.arrange(p1,p2)
You can try this:
geom_line(mapping = aes(x = Date,
y = Proportion,
group = Species,
colour = Species)) +
scale_colour_manual(values=c(Golden_Trevally="goldenrod2",
Red_Snapper="firebrick2",
Sharksucker_Remora="darkolivegreen3",
Juvenile_Remora="aquamarine2")) +
xlab("Date (2014-2018)") +
ylab("Total Presence \n Per Month ") +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)) +
theme(legend.position="top") +
labs(colour = "Hitchhiker Species")
new_data_counts <- new_data %>% select(Date, Count)
new_data_counts <- new_data_counts[!duplicated(new_data_counts),]
p2 <- ggplot(data = new_data_counts) +
geom_bar(mapping = aes(x = Date, y = Count), stat = 'identity') +
labs(x="Date (2014-2018)",
y=expression(atop(paste("Total Number of"), paste(italic("M.alfredi"), " Encounters")))) +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))
grid.arrange(p1,p2)
You need space between \n and M.alfredi in p2. Since there is no reproducible example, here is my suggestion for the second plot,
p2 <- ggplot(data = new_data_counts) +
geom_bar(mapping = aes(x = Date, y = Count), stat = 'identity') +
xlab("Date (2014-2018)") +
ylab("Total Number of "~italic(\n M.alfredi)~" Encounters") +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))
It should solve your problem.
I'm trying to obtain 2 aligned bar plots with percentage scales of 2 different factors. The y scales calculated as percent are different. I would like to have the same y scales for both plots, for example from 0 to 40% in both. I've tried ylim() which doesn't work on the percentage scale. Example below
library(ggplot2)
library(scales)
data("diamonds")
First bar-plot for cut
p<- ggplot(diamonds, aes(x = cut)) +
geom_bar(aes(y = (..count..)/sum(..count..), fill=cut)) +
scale_y_continuous(labels = percent) +
geom_text(aes(y = ((..count..)/sum(..count..)), label =
scales::percent((..count..)/sum(..count..))),
stat = "count", vjust = -0.25) +
ggtitle("Cut") + theme(plot.title = element_text(hjust = 0.5, size=14,
face="bold")) +
xlab("Cut") +
ylab("Percent") +
theme(legend.position="bottom")
Second bar-plot for clarity
p1<- ggplot(diamonds, aes(x = clarity)) +
geom_bar(aes(y = (..count..)/sum(..count..), fill=clarity)) +
scale_y_continuous(labels = percent) +
geom_text(aes(y = ((..count..)/sum(..count..)), label =
scales::percent((..count..)/sum(..count..))),
stat = "count", vjust = -0.25) +
ggtitle("Clarity") + theme(plot.title = element_text(hjust = 0.5, size=14,
face="bold")) +
xlab("Clarity") +
ylab("Percent") +
theme(legend.position="bottom")
Arranging bar-plot with different scales
grid.arrange(p,p1, ncol = 2)
different scales but I would like for example both at 40% top
If scales weren't percentages I would do this:
p<- ggplot(diamonds, aes(x = cut)) +
geom_bar(aes(y = (..count..)/sum(..count..), fill=cut)) +
scale_y_continuous(labels = percent) +
geom_text(aes(y = ((..count..)/sum(..count..)), label = scales::percent((..count..)/sum(..count..))),
stat = "count", vjust = -0.25) +
ggtitle("Cut") + theme(plot.title = element_text(hjust = 0.5, size=14, face="bold")) +
xlab("Cut") +
ylab("Percent") +
ylim(0, 40)
theme(legend.position="bottom")
But here, of course, it doesn't work and returns this:
Ok I found a way, here the code for Cut for a % scale limited to 60%
p<- ggplot(diamonds, aes(x = cut)) +
geom_bar(aes(y = (..count..)/sum(..count..), fill=cut)) +
geom_text(aes(y = ((..count..)/sum(..count..)), label = scales::percent((..count..)/sum(..count..))),
stat = "count", vjust = -0.25) +
ggtitle("Diamonds Cut") + theme(plot.title = element_text(hjust = 0.5, size=14, face="bold")) +
scale_y_continuous(labels = scales::percent, limits=c(0,0.6)) + labs(y="Percent")
xlab("Cut") +
theme(legend.position="bottom")
p