Using for loop to build 10 plots using ggplot() - R - r

I'm trying to build 10 different plots showing consumption choices (organic, non-organic) using ggplot(). I would like to use a loop to build these plots, instead of building them one by one, here is the original code when I tried to build it one by one:
a <- with(data, table(Banana_Choice))
p1 <- ggplot(as.data.frame(a), aes(factor(Banana_Choice), Freq)) +
geom_col(position = 'dodge') + geom_bar(fill = "#69b4a2", stat = "identity") + theme_gray(base_size = 14)+
geom_text(aes(label = a), vjust= -0.3) + xlab("Banana") + ylab("Frequency (count)")+
theme(axis.ticks = element_blank(),
text=element_text(size=11))+ylim(0,100)
p1
b <- with(data, table(Apple_Choice))
p2 <- ggplot(as.data.frame(b), aes(factor(Apple_Choice), Freq)) +
geom_col(position = 'dodge') + geom_bar(fill = "#69b4a2", stat = "identity") + theme_gray(base_size = 14)+
geom_text(aes(label = b), vjust= -0.3) + xlab("Apple") + ylab("Frequency (count)")+
theme(axis.ticks = element_blank(),
text=element_text(size=11))+ylim(0,100)
p2
c <- with(data, table(Tomato_Choice))
p3 <- ggplot(as.data.frame(c), aes(factor(Tomato_Choice), Freq)) +
geom_col(position = 'dodge') + geom_bar(fill = "#69b4a2", stat = "identity") + theme_gray(base_size = 14)+
geom_text(aes(label = c), vjust= -0.3) + xlab("Tomato") + ylab("Frequency (count)")+
theme(axis.ticks = element_blank(),
text=element_text(size=11))+ylim(0,100)
p3
d <- with(data, table(Cucumber_Choice))
p4 <- ggplot(as.data.frame(d), aes(factor(Cucumber_Choice), Freq)) +
geom_col(position = 'dodge') + geom_bar(fill = "#69b4a2", stat = "identity") + theme_gray(base_size = 14)+
geom_text(aes(label = d), vjust= -0.3) + xlab("Cucumber") + ylab("Frequency (count)")+
theme(axis.ticks = element_blank(),
text=element_text(size=11))+ylim(0,100)
p4
e <- with(data, table(Broccoli_Choice))
p5 <- ggplot(as.data.frame(e), aes(factor(Broccoli_Choice), Freq)) +
geom_col(position = 'dodge') + geom_bar(fill = "#69b4a2", stat = "identity") + theme_gray(base_size = 14)+
geom_text(aes(label = e), vjust= -0.3) + xlab("Broccoli") + ylab("Frequency (count)")+
theme(axis.ticks = element_blank(),
text=element_text(size=11))+ylim(0,100)
p5
f <- with(data, table(Milk_Choice))
p6 <- ggplot(as.data.frame(f), aes(factor(Milk_Choice), Freq)) +
geom_col(position = 'dodge') + geom_bar(fill = "#69b4a2", stat = "identity") + theme_gray(base_size = 14)+
geom_text(aes(label = f), vjust= -0.3) + xlab("Milk") + ylab("Frequency (count)")+
theme(axis.ticks = element_blank(),
text=element_text(size=11))+ylim(0,100)
p6
g <- with(data, table(Cheese_Choice))
p7 <- ggplot(as.data.frame(g), aes(factor(Cheese_Choice), Freq)) +
geom_col(position = 'dodge') + geom_bar(fill = "#69b4a2", stat = "identity") + theme_gray(base_size = 14)+
geom_text(aes(label = g), vjust= -0.3) + xlab("Cheese") + ylab("Frequency (count)")+
theme(axis.ticks = element_blank(),
text=element_text(size=11))+ylim(0,100)
p7
h <- with(data, table(Wine_Choice))
p8 <- ggplot(as.data.frame(h), aes(factor(Wine_Choice), Freq)) +
geom_col(position = 'dodge') + geom_bar(fill = "#69b4a2", stat = "identity") + theme_gray(base_size = 14)+
geom_text(aes(label = h), vjust= -0.3) + xlab("Wine") + ylab("Frequency (count)")+
theme(axis.ticks = element_blank(),
text=element_text(size=11))+ylim(0,100)
p8
i <- with(data, table(MilkChoco_Choice))
p9 <- ggplot(as.data.frame(i), aes(factor(MilkChoco_Choice), Freq)) +
geom_col(position = 'dodge') + geom_bar(fill = "#69b4a2", stat = "identity") + theme_gray(base_size = 14)+
geom_text(aes(label = i), vjust= -0.3) + xlab("Milk Chocolate") + ylab("Frequency (count)")+
theme(axis.ticks = element_blank(),
text=element_text(size=11))+ylim(0,100)
p9
j <- with(data, table(DarkChoco_Choice))
p10 <- ggplot(as.data.frame(j), aes(factor(DarkChoco_Choice), Freq)) +
geom_col(position = 'dodge') + geom_bar(fill = "#69b4a2", stat = "identity") + theme_gray(base_size = 14)+
geom_text(aes(label = j), vjust= -0.3) + xlab("Dark Chocolate") + ylab("Frequency (count)")+
theme(axis.ticks = element_blank(),
text=element_text(size=11))+ylim(0,100)
p10
As you can see, this is very slow. How do I build these plots using a for loop?

you can try making your data into a longer format using tidyr::pivot_longer(), and then use facet_wrap() to generate all the plots at once.

Related

How to make different patterns and colors in different category of data using ggplot in R?

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))

How to erase x label(11-28~12-02) in R ggplot

E = ggplot(km_data_person, aes(x = date, y = km,fill = "")) +
theme_minimal() +
geom_bar(stat = "identity") +
scale_fill_brewer(palette ="Paired") +
xlab("") +
ylab("") +
theme(axis.text.y = element_text(size = 18)) +
theme(legend.text = element_text(size = 20)) +
theme(axis.text.x = element_text(size = 11)) +
geom_line(data = km_data_all,
aes(date, 기관평균, color = "기관평균"),
linetype = "solid",
size = 1, group = 1) +
scale_color_manual(values = c('기관평균' = '#0066CC')) +
labs(color = '') +
theme(legend.position = "bottom") +
guides(fill = guide_legend(title = "")) +
guides(fill = "none")
The following graph is drawn from the above R code.
If I want to erase the x label how should the code change to?
E = ggplot(km_data_person,aes(x=date, y=km,fill="")) +
theme_minimal()+
geom_bar(stat="identity") +
geom_line(data=km_data_all,
aes(date,기관평균,color="기관평균"),
linetype = "solid",
size=1,
group=1)+
scale_fill_brewer(palette ="Paired")+
xlab("") +
ylab("")+
theme(axis.text.y = element_text(size = 18),
legend.text=element_text(size=20),
axis.text.x = element_blank(),
legend.position = "bottom")+
scale_color_manual(values = c('기관평균' = '#0066CC')) + labs(color = '') +
guides(fill="none")

How to change y axis from count to prop?

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)

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)

ggplot2 How to align graphs with equal y scale as percentage

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

Resources