I would like to combine 3 ggplot histograms. To do so, I am using gridExtra package. Because all plots are in one row I want to remove y titles and scales from 2 plots counting from right.
I wrote same code as always but it didn't work. Do you guys know what might be a problem? My code:
plot1 <- ggplot(testing, aes(x=residualtotal))+
geom_histogram(aes(y = ..density..), binwidth = 100) +
geom_density(aes(y = ..density..*(2)))+
xlab("Residuals Model 1 [MW]")+
theme(panel.background=element_rect(fill = "white") )+
theme_minimal()
plot2 <- ggplot(testing, aes(x=residualtotal1))+
geom_histogram(aes(y = ..density..), binwidth = 100) +
geom_density(aes(y = ..density..*(2)))+
xlab("Residuals Model 2 [MW]")+
theme(axis.text.y = element_blank(), axis.title.y = element_blank(), axis.ticks.y = element_blank(), panel.background=element_rect(fill = "white") )+
theme_minimal()
plot3 <- ggplot(testing, aes(x=residualtotal2))+
geom_histogram(aes(y = ..density..), binwidth = 100) +
geom_density(aes(y = ..density..*(2)))+
xlab("Residuals Model 3 [MW]")+
theme(axis.text.y = element_blank(), axis.title.y = element_blank(), axis.ticks.y = element_blank(), panel.background=element_rect(fill = "white") )+
theme_minimal()
grid.arrange(plot1, plot2, plot3, ncol = 3, nrow=1)
Sample of my dataset.
Load residualtotal1 prognosis2 residualtotal2 residualtotal
89 20524 -347.6772 20888.75 -364.7539 -287.82698
99 13780 -133.8496 13889.52 -109.5207 -6.60009
100 13598 -155.9950 13728.77 -130.7729 -27.18835
103 13984 -348.4080 14310.12 -326.1226 -213.68816
129 14237 -3141.5591 17375.82 -3138.8188 -3077.32236
130 14883 -3142.0134 18026.02 -3143.0183 -3090.52193
An alternate approach:
library(tidyverse)
res_trans <- c(`residualtotal`="Residuals Model 1 [MW]",
`residualtotal1`="Residuals Model 2 [MW]",
`residualtotal2`="Residuals Model 3 [MW]")
select(testing, starts_with("resid")) %>%
gather(which_resid, value) %>%
mutate(label=res_trans[which_resid]) %>%
ggplot(aes(x=value, group=label)) +
geom_histogram(aes(y = ..density..), binwidth = 100) +
geom_density(aes(y = ..density..*(2))) +
facet_wrap(~label, ncol=3) +
labs(x=NULL, y=NULL) +
theme_minimal() +
theme(panel.background=element_rect(fill = "white"))
I think what you are looking for is + ylab(NULL) and to move theme() to after theme_minimal(). I've also added a widths specification to grid.arrange, since the width of the leftmost figure needs to be wider to give space to the y title.
Your code would then be
plot1 <- ggplot(testing, aes(x=residualtotal))+
geom_histogram(aes(y = ..density..), binwidth = 100) +
geom_density(aes(y = ..density..*(2)))+
xlab("Residuals Model 1 [MW]")+
theme_minimal()
plot2 <- ggplot(testing, aes(x=residualtotal1))+
geom_histogram(aes(y = ..density..), binwidth = 100) +
geom_density(aes(y = ..density..*(2)))+
xlab("Residuals Model 2 [MW]")+
ylab(NULL) +
theme_minimal() +
theme(axis.text.y = element_blank())
plot3 <- ggplot(testing, aes(x=residualtotal2))+
geom_histogram(aes(y = ..density..), binwidth = 100) +
geom_density(aes(y = ..density..*(2)))+
xlab("Residuals Model 3 [MW]")+
ylab(NULL) +
theme_minimal() +
theme(axis.text.y = element_blank())
grid.arrange(plot1, plot2, plot3, ncol = 3, nrow=1, widths = c(1.35, 1, 1))
Related
I was able to use patchwork to align two xaxis, but when I add ggbreak::scale_break(), it no longer aligns. What am I doing wrong here? Code of alignment issues follows. UnComment out scale_break() lines to see difference.
library(scales)
library(ggplot2)
library(ggbreak)
library(patchwork)
y <- as_tibble(c(rnorm(400,100,25),250) )
n= nrow(y)
cor = n/100
a.mean = mean(y$value)
a.median= quantile(y$value,0.5)
a.sd = sd(y$value)
binwidth = 5
upper.limit <- 260
plt1 <-ggplot(y, aes(x="", y = value) ) +
geom_boxplot(fill = "lightblue", color = "black", outlier.shape=NA) +
stat_boxplot(geom='errorbar',coef=NULL) +
stat_summary(fun=mean, geom="point", shape=23, size=7.6, color="black", fill = "blue") +
coord_flip() +
theme_classic() +
theme(panel.border = element_rect(color="black", fill = NA, size = 1),
axis.text = element_text(size=14)) +
xlab("") +
ylab("Value ($)") +
#scale_y_break(c(200,240 ) ) +
scale_y_continuous(breaks=pretty(c(0,upper.limit), n=10), limits=c(0,upper.limit) ) +
theme(axis.text.y=element_blank(),
axis.ticks.y=element_blank(),
axis.text.x.top=element_blank(),
axis.ticks.x.top=element_blank() )
plt2 <- ggplot(y, aes(x = value) ) +
geom_histogram(aes(y = (..count..)/sum(..count..)*100 ),
position = "identity", binwidth = 5,
fill = "lightblue", color = "black") +
stat_function(fun = function(x)
dnorm(x, mean = a.mean, sd = a.sd) * n * binwidth / cor,
color="darkblue", size =1) +
ylab("Percentage") +
xlab("") +
#scale_x_break(c(200,240 ) ) +
scale_x_continuous(breaks=pretty(c(0,upper.limit), n=10), limits=c(0,upper.limit) ) +
scale_y_continuous(breaks=seq(0,15, by=2.5)) +
theme(panel.border = element_rect(color="black", fill = NA, size = 1),
plot.title = element_text(hjust = 0.5),
text=element_text(size=20),
axis.text = element_text(size=14),
axis.text.x.top=element_blank(),
axis.ticks.x.top=element_blank() )
Fig01_01 <- plt2 / plt1 + plot_layout(nrow = 2, heights = c(10, 2) )
Fig01_01
One solution might be to manually/invisibly add in the y-axis labels and ticks for the bottom plot as exactly the same size as the upper plot. ggbreak does additionally seem to add in an immovable margin around the whole plotting area, so you may have some extra white space between plots doing it this way:
library(scales)
library(tidyverse)
library(ggbreak)
library(patchwork)
y <- as_tibble(c(rnorm(400,100,25),250) )
n= nrow(y)
cor = n/100
a.mean = mean(y$value)
a.median= quantile(y$value,0.5)
a.sd = sd(y$value)
binwidth = 5
upper.limit <- 260
plt1 <-ggplot(y, aes(x=1, y = value) ) +
geom_boxplot(fill = "lightblue", color = "black", outlier.shape=NA) +
stat_boxplot(geom='errorbar',coef=NULL) +
stat_summary(fun=mean, geom="point", shape=23, size=7.6, color="black", fill = "blue") +
coord_flip() +
theme_classic() +
theme(panel.border = element_rect(color="black", fill = NA, size = 1),
axis.text = element_text(size=14)) +
xlab(" ") +
ylab("Value ($)") +
scale_y_break(c(200,240 ) ) +
scale_y_continuous(breaks=pretty(c(0,upper.limit), n=10), limits=c(0,upper.limit) ) +
theme(axis.text.y=element_text(colour = "white", size = 14),
axis.ticks.y=element_line(colour = "white"),
axis.text.x.top=element_blank(),
axis.title.y=element_text(size=20),
axis.ticks.x.top=element_blank() )
plt2 <- ggplot(y, aes(x = value) ) +
geom_histogram(aes(y = (..count..)/sum(..count..)*100 ),
position = "identity", binwidth = 5,
fill = "lightblue", color = "black") +
stat_function(fun = function(x)
dnorm(x, mean = a.mean, sd = a.sd) * n * binwidth / cor,
color="darkblue", size =1) +
ylab("Percentage") +
xlab("") +
scale_x_break(c(200,240 ) ) +
scale_x_continuous(breaks=pretty(c(0,upper.limit), n=10), limits=c(0,upper.limit) ) +
scale_y_continuous(breaks=seq(0,15, by=2.5)) +
theme(panel.border = element_rect(color="black", fill = NA, size = 1),
plot.title = element_text(hjust = 0.5),
text=element_text(size=20),
axis.text = element_text(size=14),
axis.text.x.top=element_blank(),
axis.ticks.x.top=element_blank() )
Fig01_01 <- plt2 / plt1 + plot_layout(nrow = 2, heights = c(6, 2) )
Fig01_01
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)
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).
I am trying to create a barplot with two x-axis (grouped x-axis):
# read data
tmp <- read.table(text = "label CNV_x CNV_Type
17p -1 Loss
9p -1 Loss
16q 1 Gain
10p 1 Gain
8q 1 Gain
13q 1 Gain", header = T)
tmp$CNV_Type <- relevel(tmp$CNV_Type, ref = 'Loss')
# plot
ggplot(tmp, aes(x = label, y = CNV_x)) +
geom_bar(stat = 'identity') +
theme_bw() +
geom_hline(yintercept = 0) +
coord_flip() +
facet_wrap(~CNV_Type, strip.position = "bottom", scales = "free_x") +
theme(panel.spacing = unit(0, "lines"),
strip.background = element_blank(),
strip.placement = "outside",
panel.border = element_rect(colour = NA))
This creates a plot like this:
This plot shows 0.00 twice on x-axis and I can't figure out a way to remove the spacing between the two vertical lines separating the strips (one is Gain and other is Loss).
Any help would be much appreciated. Thanks!
UPDATE: I added scale_y_continuous(expand = c(0, 0)) as suggested below:
ggplot(tmp, aes(x = label, y = CNV_x)) +
geom_bar(stat = 'identity') +
theme_bw() +
geom_hline(yintercept = 0) +
scale_y_continuous(expand = c(0, 0)) +
coord_flip() +
facet_wrap(~CNV_Type, strip.position = "bottom", scales = "free_x") +
theme(panel.spacing = unit(0, "lines"),
strip.background = element_blank(),
strip.placement = "outside",
panel.border = element_rect(colour = NA))
This creates a plot like this:
The only issue now is there is no spacing between the bars and the left and right margins of the plot - not sure why that happened.
I would not use facets here. A couple of options. You could indicate the type by colour:
tmp %>%
ggplot(aes(label, CNV_x)) +
geom_col(aes(fill = CNV_Type)) +
geom_hline(yintercept = 0) +
coord_flip() +
scale_fill_manual(values = c("darkorange", "skyblue3"))
And/or add the labels for type to the plot using annotate. That requires some manual fiddling with x, y and expand to get it right:
tmp %>%
ggplot(aes(label, CNV_x)) +
geom_col() +
geom_hline(yintercept = 0) +
coord_flip() +
annotate("text",
label = c("Loss", "Gain"),
x = c(7, 7),
y = c(-0.5, 0.5)) +
scale_x_discrete(expand = c(0.1, 0.1))
I'm sure this is simple but I can't figure it out.
I have the following chart:
library(data.table)
library(magrittr)
library(ggplot2)
cambodia <-
data.table(Period = c("Funan", "Chenla/Zhenla","Khmer Empire","Dark Ages of Cambodia"),
StartDate = c(-500,550,802,1431),
EndDate = c(550,802,1431,1863),
Color = c("lightblue","lightgreen","lightyellow","pink")) %>%
extract(order(-StartDate)) %>%
extract(, Period := factor(Period,levels = Period))
ggplot() +
geom_segment(data=cambodia, aes(x=StartDate, xend=EndDate, y=Period, yend=Period, color=Color),
linetype=1, size=2) +
scale_colour_brewer(palette = "Pastel1")+
xlab("Date")+
ylab("Ruler")+
theme_bw() +
theme(panel.grid.minor = element_blank(), panel.grid.major = element_blank()) +
theme(aspect.ratio = .2) +
theme(legend.position="none")
But I would like the labels to be off the axis and on the page. Either to the left or on top of the middle of the line. E.g.
Most of the examples of geom_text give me gobbledeegook. I can't seem to apply them to the factor data I have here. Do you know how to do this?
Thank you
Having the labels on the end of the segments might distort the visual mapping of segment length and location to year-range. You could put the labels in the middle of the segments instead.
library(data.table)
library(magrittr)
library(ggplot2)
library(stringr)
cambodia <-
data.table(Period = c("Funan", "Chenla/Zhenla","Khmer Empire","Dark Ages of Cambodia"),
StartDate = c(-500,550,802,1431),
EndDate = c(550,802,1431,1863),
Color = c("lightblue","lightgreen","lightyellow","pink")) %>%
extract(order(-StartDate)) %>%
extract(, Period := factor(Period,levels = Period))
ggplot(cambodia, aes(x=StartDate, xend=EndDate, y=Period, colour=Period)) +
geom_segment(aes(xend=EndDate, yend=Period), linetype=1, size=2) +
geom_label(aes(label=str_wrap(Period,12), x=(StartDate + EndDate)/2), size=3) +
scale_colour_brewer(palette = "Set1") +
xlab("Date")+ ylab("Ruler")+
theme_bw() +
theme(panel.grid.minor = element_blank(), panel.grid.major = element_blank(),
aspect.ratio = .2,
legend.position="none",
axis.text.y=element_blank(),
axis.ticks.y=element_blank())
Or what about going minimal:
ggplot(cambodia, aes(x=StartDate, y=1)) +
geom_rect(aes(xmin=StartDate, xmax=EndDate, ymin=0.97, ymax=1.03, fill=Period),
show.legend=FALSE, colour="white", size=0.5) +
geom_label(aes(label=str_wrap(Period,12), x=(StartDate + EndDate)/2), size=3.5) +
geom_text(aes(label=StartDate, y=0.96), size=3.5) +
geom_text(aes(label=ifelse(EndDate==max(EndDate), EndDate,""), x=EndDate, y=0.96), size=3.5) +
scale_colour_brewer(palette = "Set1") +
scale_y_continuous(limits=c(0.95,1.05)) +
theme_void()
ggplot() +
geom_segment(data=cambodia, aes(x=StartDate, xend=EndDate, y=Period, yend=Period, color=Color),
linetype=1, size=2) +
geom_label(data=cambodia, aes(x=StartDate, y=Period, label = Period),
nudge_x = c(-300, -200, -200, -100)) +
scale_colour_brewer(palette = "Pastel1")+
xlab("Date")+
ylab("")+
theme_bw() +
theme(legend.position="none") +
theme(aspect.ratio = .2) +
theme(panel.grid.minor = element_blank(), panel.grid.major = element_blank(),
axis.line.y = element_blank(), axis.text.y = element_blank(),
axis.ticks.y = element_blank())
You need to use element_blank() to remove the y axis elements and then use nudge_x argument in geom_label to offset the labels appropriately.