Customized Line Break for ggplot - r

I can create quality control charts with the qicharts2 package.
library(tidyverse)
library(qicharts2)
(plot1 <- qic(age,
data = tail(cabg, 100),
chart = 'i',
ylab = 'Years',
xlab = 'Patient #'
)
)
p1 <- plot1$data
Then I can customize the charts.
(plot2 <- ggplot(p1, aes(x, y)) +
geom_ribbon(ymin = p1$lcl, ymax = p1$ucl, fill = "black", alpha = 0.05) +
geom_line(color = "black", size = 1) +
geom_line(aes(x, cl)) +
geom_point(color = "black" , fill = "black", size = 2) +
geom_point(data = p1 %>% filter(sigma.signal == TRUE), color = "red", size = 2) +
ggtitle(label = NULL) +
labs(x = NULL, y = NULL) +
scale_y_continuous(breaks = seq(0, 100, by = 10)) +
coord_cartesian(ylim = c(0, 100)) +
theme_bw() +
theme(
text = element_text(size = 18),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 0.6),
axis.text.y = NULL,
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
strip.text.x = element_text(size = 14, color = "black", angle = 0))
)
Using the part argument, in my qichart, causes it to split at the specified part point(s).
(plot3 <- qic(age,
data = tail(cabg, 100),
chart = 'i',
part = c(70, 85),
ylab = 'Years',
xlab = 'Patient #'
)
)
p3 <- plot3$data
What do I need to add to my customized ggplot2 syntax, below, to get it to part in the same manner? What I've got does everything, EXCEPT, it doesn't part like in the syntax directly above.
(plot4 <- ggplot(p3, aes(x, y)) +
geom_ribbon(ymin = p3$lcl, ymax = p3$ucl, fill = "black", alpha = 0.05) +
geom_line(color = "black", size = 1) +
geom_line(aes(x, cl)) +
geom_point(color = "black" , fill = "black", size = 2) +
geom_point(data = p3 %>% filter(sigma.signal == TRUE), color = "red", size = 2) +
ggtitle(label = NULL) +
labs(x = NULL, y = NULL) +
scale_y_continuous(breaks = seq(0, 100, by = 10)) +
coord_cartesian(ylim = c(0, 100)) +
theme_bw() +
theme(
text = element_text(size = 18),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 0.6),
axis.text.y = NULL,
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
strip.text.x = element_text(size = 14, color = "black", angle = 0))
)

Is the following plot what you are looking for?
If so, what I used is group= in the aesthetics of geom_ribbon and geom_line
(plot4 <- ggplot(p3, aes(x, y)) +
geom_ribbon(aes(group=cut(p3$x,c(0,70,85,max(p3$x)))),ymin = p3$lcl, ymax = p3$ucl, fill = "black", alpha = 0.05) +
geom_line(color = "black", size = 1, aes(group=cut(p3$x,c(0,70,85,max(p3$x))))) +
geom_line(aes(x, cl, group=cut(p3$x,c(0,70,85,max(p3$x))))) +
geom_point(color = "black" , fill = "black", size = 2) +
geom_point(data = p3 %>% filter(sigma.signal == TRUE), color = "red", size = 2) +
ggtitle(label = NULL) +
labs(x = NULL, y = NULL) +
scale_y_continuous(breaks = seq(0, 100, by = 10)) +
coord_cartesian(ylim = c(0, 100)) +
theme_bw() +
theme(
text = element_text(size = 18),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 0.6),
axis.text.y = NULL,
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
strip.text.x = element_text(size = 14, color = "black", angle = 0)))

Related

In ggplot2, how can I use multi-row x-axis labels with facet_wraps?

I have multi-row x-axis labels such that the first row is month and the second row is year. However, I run into check_aesthetics() errors when I try to use the multi-row axis labels with facet_wrap().
Example Data:
library(data.table)
library(dplyr)
library(ggplot2)
df1 <- data.frame(matrix(ncol = 3, nrow = 12))
colnames(df1)[1:3] <- c("Date", "Group", "Value")
df1$Date <- rep(seq.Date(as.Date("2020-03-14"),as.Date("2020-08-20"),"1 month"),2)
df1$Group <- sort(rep(c("A","B"),6))
df1$Value <- rnorm(12,50,10)
df1 <- df1 %>%
mutate(Month = month(Date),
Year = year(Date),
date = zoo::as.yearmon(paste(Year, Month), "%Y %m"))
df2 <- data.frame(matrix(ncol = 3, nrow = 12))
colnames(df2)[1:3] <- c("Date", "Group", "Value")
df2$Date <- rep(seq.Date(as.Date("2021-03-14"),as.Date("2021-08-20"),"1 month"),2)
df2$Group <- sort(rep(c("A","B"),6))
df2$Value <- rnorm(12,50,10)
df2 <- df2 %>%
mutate(Month = month(Date),
Year = year(Date),
date = zoo::as.yearmon(paste(Year, Month), "%Y %m"))
df3 <- rbind(df1,df2)
cols <- c("A" = "#ca0020", "B" = "#0571b0")
Figure without facet_wrap() showing the multi-row x-axis
ggplot(data = df3, aes(x = factor(date), y = Value, color = Group, group = paste(Year,Group))) +
geom_line() +
geom_point(size = 3, aes(fill = Group), color = "black", shape = 21) +
scale_fill_manual(values = cols) +
scale_color_manual(values = cols) +
scale_x_discrete(labels=substr(df3$date,1,3))+
labs(x = "") +
theme_bw() +
theme(plot.margin = unit(c(1, 1, 2, 1), "lines"),
panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
axis.text.y = element_text(size = 14, color = "black"),
legend.title = element_blank(),
legend.direction = "horizontal",
legend.margin = margin(),
legend.background = element_blank(),
legend.position = c(0.1,0.93),
panel.border = element_blank()) +
guides(fill = guide_legend(nrow = 2)) +
coord_cartesian(clip = 'off', ylim = c(0, 100)) +
annotation_custom(grid::rectGrob(gp = grid::gpar(fill = NA))) +
annotate(geom = "text", x = c(3.5,9.5), y = -15, label = unique(df3$Year), size = 6) +
annotate('rect',
xmin = 6.35,
xmax = 6.65,
ymin = -10, ymax = 0, fill = 'white') +
annotate('segment',
x = c(6.35, 6.65),
xend = c(6.35, 6.65), y = -10, yend = 0)
Now when I try to add the facet_wrap()...
ggplot(data = df3, aes(x = factor(date), y = Value, color = Group, group = paste(Year,Group))) +
geom_line() +
geom_point(size = 3, aes(fill = Group), color = "black", shape = 21) +
scale_fill_manual(values = cols) +
scale_color_manual(values = cols) +
scale_x_discrete(labels=substr(df3$date,1,3))+
labs(x = "") +
theme_bw() +
theme(plot.margin = unit(c(1, 1, 2, 1), "lines"),
panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
axis.text.y = element_text(size = 14, color = "black"),
legend.title = element_blank(),
legend.direction = "horizontal",
legend.margin = margin(),
legend.background = element_blank(),
legend.position = c(0.1,0.93),
panel.border = element_blank()) +
guides(fill = guide_legend(nrow = 2)) +
coord_cartesian(clip = 'off', ylim = c(0, 100)) +
annotation_custom(grid::rectGrob(gp = grid::gpar(fill = NA))) +
annotate(geom = "text", x = c(3.5,9.5), y = -15, label = unique(df3$Year), size = 6) +
annotate('rect',
xmin = 6.35,
xmax = 6.65,
ymin = -10, ymax = 0, fill = 'white') +
annotate('segment',
x = c(6.35, 6.65),
xend = c(6.35, 6.65), y = -10, yend = 0) +
facet_wrap(~Group)
...it throws the error Error in `check_aesthetics()`: ! Aesthetics must be either length 1 or the same as the data (4): label.
The error resides within annotate(geom = "text", x = c(3.5,9.5), y = -15, label = unique(df3$Year), size = 6) + but I can't figure out how to fix it. I have tried changing the label = and the x = but no luck. The ideal figure would have two plots, each with multi-row x-axis labels where, similar to the example figure above, the top row is month and the second row is year. Any thoughts on how to achieve this?
If you don't mind moving the year value to the strip you could use ggh4x package.
library(dplyr)
library(ggplot2)
library(lubridate)
library(ggh4x)
ggplot(data = df3, aes(x = factor(date), y = Value, color = Group, group = paste(Year,Group))) +
geom_line() +
geom_point(size = 3, aes(fill = Group), color = "black", shape = 21) +
scale_fill_manual(values = cols) +
scale_color_manual(values = cols) +
scale_x_discrete(labels=substr(df3$date,1,3))+
labs(x = NULL) +
theme_bw() +
theme(plot.margin = unit(c(1, 1, 2, 1), "lines"),
panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
axis.text.y = element_text(size = 14, color = "black"),
legend.title = element_blank(),
legend.direction = "horizontal",
legend.margin = margin(),
legend.background = element_blank(),
legend.position = c(0.1,0.90),
panel.border = element_blank()) +
guides(fill = guide_legend(nrow = 2)) +
coord_cartesian(clip = 'off', ylim = c(0, 100)) +
facet_nested(~Group + Year, scales = "free_x")
Created on 2022-10-12 with reprex v2.0.2
One kind of hacky way to do this is to just make two text annotations
ggplot(data = df3, aes(x = factor(date), y = Value, color = Group, group = paste(Year,Group))) +
geom_line() +
geom_point(size = 3, aes(fill = Group), color = "black", shape = 21) +
scale_fill_manual(values = cols) +
scale_color_manual(values = cols) +
scale_x_discrete(labels=substr(df3$date,1,3))+
labs(x = "") +
theme_bw() +
theme(plot.margin = unit(c(1, 1, 2, 1), "lines"),
panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black", angle = 90, vjust = 0.5, hjust = 1),
axis.text.y = element_text(size = 14, color = "black"),
legend.title = element_blank(),
legend.direction = "horizontal",
legend.margin = margin(),
legend.background = element_blank(),
legend.position = c(0.1,0.93),
panel.border = element_blank()) +
guides(fill = guide_legend(nrow = 2)) +
coord_cartesian(clip = 'off', ylim = c(0, 100)) +
annotation_custom(grid::rectGrob(gp = grid::gpar(fill = NA))) +
annotate(geom = "text", x = c(3.5), y = -15, label = 2020, size = 6) +
annotate(geom = "text", x = c(9.5), y = -15, label = 2021, size = 6) +
annotate('rect',
xmin = 6.35,
xmax = 6.65,
ymin = -10, ymax = 0, fill = 'white') +
annotate('segment',
x = c(6.35, 6.65),
xend = c(6.35, 6.65), y = -10, yend = 0) +
facet_wrap(~Group)

how to put legend as a label in the middle of line in ggplot2

here is my data and code for chart line:
df<- data.frame(direct= 10:85, indirect= 55:130, age=15:90)
ggplot(data=df)+
geom_line(mapping=aes(y=direct,x= age,color="direct"),linetype="solid" ) +
geom_line(mapping=aes(y=indirect,x= age,color="indirect"),linetype="dashed") +
scale_color_manual(values = c(
'direct' = 'black',
'indirect' = 'black')) +
labs(color = NULL)+
scale_x_continuous(breaks = seq(15, 90, by = 5))+
labs(y= "Time Spent (in minutes)")+
guides(color = guide_legend(override.aes = list(linetype = c("solid","dashed"))))+
theme_classic()+
theme(plot.title = element_text(hjust = 0.5, size=9, face="bold"),legend.position=c(.90,.90))
I want to put legend in the middle of my each line as the picture:
You can add annotate to your lines. You can use the following code:
library(tidyverse)
df<- data.frame(direct= 10:85, indirect= 55:130, age=15:90)
ggplot(data=df)+
geom_line(mapping=aes(y=direct,x= age,color="direct"),linetype="dashed" ) +
geom_line(mapping=aes(y=indirect,x= age,color="indirect"),linetype="solid") +
scale_color_manual(values = c(
'direct' = 'black',
'indirect' = 'black')) +
labs(color = NULL)+
scale_x_continuous(breaks = seq(15, 90, by = 5))+
labs(y= "Time Spent (in minutes)")+
guides(color = guide_legend(override.aes = list(linetype = c("solid","dashed"))))+
theme_classic()+
theme(plot.title = element_text(hjust = 0.5, size=9, face="bold"), legend.position = "none") +
annotate('text', x=50, y=55, label = "direct")+
annotate('text', x=50, y=100, label = "indirect")
Output:
Not 100% what you desired. But one option would be the geomtextpath package which allows to easily add direct labels to lines or ...
library(ggplot2)
library(geomtextpath)
df <- data.frame(direct = 10:85, indirect = 55:130, age = 15:90)
ggplot(data = df) +
geom_textline(mapping = aes(y = direct, x = age, color = "direct",
label = "direct"), linetype = "solid", offset = unit(5, "pt"), gap = FALSE) +
geom_textline(mapping = aes(y = indirect, x = age, color = "indirect",
label = "indirect"), linetype = "dashed", offset = unit(5, "pt"), gap = FALSE) +
scale_color_manual(values = c(
"direct" = "black",
"indirect" = "black"
)) +
labs(color = NULL) +
scale_x_continuous(breaks = seq(15, 90, by = 5)) +
labs(y = "Time Spent (in minutes)") +
guides(color = guide_legend(override.aes = list(linetype = c("solid", "dashed")))) +
theme_classic() +
theme(plot.title = element_text(hjust = 0.5, size = 9, face = "bold"), legend.position = c(.90, .90)) +
guides(color = "none")

Changing x axis on my plot to fit in one more value: xlim, scale_x_continuous not working

I created a cleveland dot plot for my data, but it stops a bit shorter than the last data point.
I would like it to end on 7000. I tried to use xlim(1000,7000) and scale_x_continuous(breaks = seq(1000, 7000, by = 1000) but it doesnt work. My code:
ggplot(tidydf, aes(Genome_size, `Trio_number`, color = Group)) +
geom_point() + geom_line(aes(group = Trio_number), color = 'grey30') +
scale_y_continuous(breaks = seq(0, 20, by = 1)) + scale_x_continuous(breaks = seq(1000,
7000, by = 1000) +
ylab("Trio number") + xlab("Genome size (kb)") + theme_dotplot + theme(legend.position =
"bottom") + scale_color_brewer(palette = "Set2") + theme(legend.title=element_blank()) +
guides(colour = guide_legend(override.aes = list(size=4))) +
theme(legend.key=element_rect(fill='grey96')) +
theme(plot.background = element_rect(fill = 'grey96')) + theme(legend.title =
element_text(size=10)) + theme(text=element_text(size=12, family="Gujarati Sangam MN"))
+ theme(axis.title.x = element_text(vjust = 0, size = 12), axis.title.y =
element_text(vjust = 2, size = 12)) + theme(axis.text = element_text(color = "black",
size = 9))
Reproducible data:
library(ggplot2)
library(scales)
set.seed(8675309)
tidydf <- data.frame(
Genome_size = sample(1000:7000, 30, replace = T),
Trio_number = sample(1:20, 30, replace = T),
Group = sample(c('Free-living', 'Gut', 'Pathogen'), 30, replace = T)
)
p <-
ggplot(tidydf, aes(Genome_size, `Trio_number`, color = Group)) +
geom_point() +
scale_y_continuous(breaks = seq(0, 20, by = 1)) +
ylab("Trio number") + xlab("Genome size (kb)") +
theme_light() +
scale_x_continuous(labels = comma) +
scale_color_brewer(palette = "Accent") +
guides(colour = guide_legend(override.aes = list(size=4))) +
theme(
legend.position = "bottom",
legend.key=element_rect(fill='gray96'),
plot.background = element_rect(fill = 'gray96'),
legend.title =element_text(size=10),
text=element_text(size=12),
axis.title.x = element_text(vjust = 0, size = 11),
axis.title.y = element_text(vjust = 2, size = 11),
axis.text = element_text(color = "black", size = 9),
# to make the theme look more similar to OP example
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank()
)
p
Thanks!
I think it would work by adding both limits = c(1000, 7000) and breaks = seq(1000, 7000, by = 1000) inside the scale_x_continuous call:
library(ggplot2)
library(scales)
set.seed(8675309)
tidydf <- data.frame(
Genome_size = sample(1200:6800, 30, replace = T),
Trio_number = sample(1:20, 30, replace = T),
Group = sample(c('Free-living', 'Gut', 'Pathogen'), 30, replace = T)
)
ggplot(tidydf, aes(Genome_size, `Trio_number`, color = Group)) +
geom_point() +
geom_line(aes(group = Trio_number), color = 'grey30') +
scale_y_continuous(breaks = seq(0, 20, by = 1)) +
ylab("Trio number") + xlab("Genome size (kb)") +
theme_light() +
scale_x_continuous(labels = comma,
limits = c(1000, 7000),
breaks = seq(1000, 7000, by = 1000)) +
scale_color_brewer(palette = "Accent") +
guides(colour = guide_legend(override.aes = list(size=4))) +
theme(
legend.position = "bottom",
legend.key=element_rect(fill='gray96'),
plot.background = element_rect(fill = 'gray96'),
legend.title =element_text(size=10),
text=element_text(size=12),
axis.title.x = element_text(vjust = 0, size = 11),
axis.title.y = element_text(vjust = 2, size = 11),
axis.text = element_text(color = "black", size = 9),
# to make the theme look more similar to OP example
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank()
)
Created on 2021-03-22 by the reprex package (v1.0.0)

Add vertical text in the top margin of ggplot

I have the following code for a plot
ggplot(na.omit(total), aes(x = day_after, y = use, group=t, na.rm=TRUE)) +
geom_line(aes(linetype=t, color=t, na.rm=TRUE))+
geom_point(aes(color=t, na.rm = TRUE)) +
scale_color_manual(values=c("gray48", "indianred4"), labels=c("Treatment","Control")) +
labs(x= "Days after beginning of deactivation period", y= "") +
theme(panel.grid.minor = element_blank(),
panel.background = element_blank()) +
theme(panel.grid.major.x = element_blank(),
panel.grid.major.y = element_line( size=.1, color="grey"))+
theme(legend.key=element_blank()) +
guides(linetype = FALSE) +
annotate('segment',x = 0,xend = 0,y = 0,yend = 60,size = 3,colour = "grey",
alpha = 0.4) +
annotate('segment',x = 7,xend = 7,y = 0,yend = 60,size = 3,colour = "grey",
alpha = 0.4) +
annotate('segment',x = 39,xend = 39,y = 0,yend = 60,size = 3,colour = "grey",
alpha = 0.4)
new_plot <- plot + theme(legend.title=element_blank(), legend.text = element_text(size=10),
legend.position = "right")
What I want to do is to add vertical text on the top the plot at multiple given (x,y) values, outside the plot.
Annotate_custom works but it does not have the option to rotate the text. Basically I tried + annotation_custom(text_end,xmin=42,xmax=42,ymin=62,ymax=62)
Which would be amazing, only i cannot have an option like angle=90.
Any help ??
You can use annotation_custom, as long as you turn clipping off. You can use a custom grid::textGrob to specify rotation.
I don't have your data, but an example using the built-in mtcars dataset should suffice for illustration.
library(ggplot2)
ggplot(mtcars, aes(disp, mpg)) +
geom_point() +
geom_vline(xintercept = c(200, 400), size = 10, alpha = 0.05) +
coord_cartesian(clip = "off") +
theme_bw() +
theme(plot.margin = margin(80, 20, 20, 20),
panel.border = element_blank()) +
annotation_custom(grid::textGrob("label 1", rot = 90),
xmin = 200, xmax = 200, ymin = 40) +
annotation_custom(grid::textGrob("label 2", rot = 90),
xmin = 400, xmax = 400, ymin = 40)

Align labels in a geom_boxplot

I am having some troubles with the following piece of code:
ggplot(data = sb11.20194, aes(y = PROMLECTURACRITICA, x = año)) +
geom_boxplot(fill = "#3AAA35", color = "#3AAA35",outlier.color = "#95C11F",
outlier.size = 5) +
ylab("Puntajes promedio de Lectura Crítica") +
stat_boxplot(geom = "errorbar", colour = "#006633",
width = 0.6) +
stat_summary(geom = "crossbar", width=1.5, fatten=0,
color="white",
fun.data = function(x){ return(c(y=median(x),
ymin=median(x),
ymax=median(x))) }) +
theme(
panel.background = element_rect(fill = "white", colour = rgb(198,
198,
198,
maxColorValue = 255),
size = 1, linetype = "solid"),
panel.grid.minor = element_line(size = 0.1, linetype = 'dashed',
colour = rgb(198,198,198,
maxColorValue = 255)),
axis.ticks.x = element_blank(),
axis.text.x = element_blank(),
axis.title.x = element_blank(),
axis.text.y = element_text(family = "Montserrat"),
axis.title.y = element_text(family = "Montserrat")
) + geom_text(data = num, aes(label = num, y = num),
color = "#575756", hjust = -8,
family = "Montserrat")
which gives the following plot:
I would like to align the labels. Does anyone know how I might do this?
You didn't provide a sample data set, so I made some on my own. You can use two arguments in geom_text: nudge_x and hjust. You can use nudge_x in the way you're currently using hjust in your code. Then, we can use hjust to align the labels.
library(tidyverse)
set.seed(123)
# generate sample data and calculate quantiles
dat <- tibble(x = rnorm(1000))
dat_summary <- tibble(quants = quantile(dat$x))
ggplot(dat, aes(x = 1, y = x))+
geom_boxplot() +
geom_text(data = dat_summary, aes(x = 1.5, y = quants,
label = round(quants, 2)),
hjust = 'outward', nudge_x = 0.1)

Resources