I'm looking for a way to plot axis like on picture below, using ggplot2. (maybe some tips in theme or scale_x_continuous?)
I mean a symmetrical sequence of labels, which goes from 100 to 100 in this example with the center at 20 (not a horizontal orientation for the axis).
Reproducible example:
library(ggplot2)
required(grid)
ggplot(data = i, aes(x = wd, y = co2)) +
ggtitle("CO2")+
geom_point(size=4, colour = "red")+
geom_linerange(aes(ymax =ci2, ymin=ci1), colour = "red", size = 2)+
coord_polar()+
geom_hline(yintercept = seq(365, 405, by = 5), colour = "grey", size = 0.2) +
geom_vline(xintercept = seq(0, 360, by = 22.5), colour = "grey", size = 0.2) +
scale_x_continuous(limits = c(0, 360), expand = c(0, 0),
breaks = seq(0, 359.99, by = 22.5),
labels=c("N","NNE","NE","ENE","E","ESE","SE","SSE",
"S","SSW","SW","WSW","W","WNW","NW","NNW")) +
scale_y_continuous(limits = c(365, 405), breaks = seq(365, 405, by = 10)) +
theme_bw() +
theme(panel.border = element_blank(),
panel.grid = element_blank(),
legend.key = element_blank(),
axis.ticks = element_line(colour = "grey"),
axis.ticks.length = unit(-1, "lines"),
axis.ticks.margin = unit(1.3,"lines"),
axis.text = element_text(size=24),
axis.text.y = element_text(size=24),
axis.title = element_blank(),
axis.line=element_line(),
axis.line.x=element_blank(),
axis.line.y = element_line(colour = "grey"),
plot.title = element_text(hjust = 0, size = 20))
Data:
i <- structure(list(wd = c(0, 112.5, 135, 180, 202.5, 22.5, 225, 247.5,
270, 292.5, 337.5, 45, 67.5, 90), co2 = c(389.82, 376.82, 386.06,
392.04, 392.55, 387.97, 391.45, 389.87, 390.12, 389.68, 391.39,
390.1, 386.89, 383.05), ci1 = c(388.37, 367.67, 378.98, 381.76,
388.63, 386.65, 388.32, 388.5, 389.03, 387.25, 389.05, 388.65,
385.64, 381.1), ci2 = c(391.26, 385.98, 393.15, 402.31, 396.46,
389.28, 394.58, 391.23, 391.21, 392.12, 393.73, 391.55, 388.15,
385.01)), row.names = c(NA, -14L), class = "data.frame")
Assuming the original plot was named p, and there is already an axis label / tick at the symmetric centre (otherwise this use case won't make sense), the following grob hack should work:
gp <- ggplotGrob(p)
# flip labels
new.labels <- gp$grobs[[which(gp$layout$name == "axis-l")]]$children[[2]]$grobs[[1]]$children[[1]]
new.labels$label <- c(rev(new.labels$label[-1]), new.labels$label)
new.labels$x <- unit.c(rep(new.labels$x[1], length(new.labels$x) - 1),
new.labels$x)
new.labels$y <- unit.c(rev(2*new.labels$y[1] - new.labels$y[-1]),
new.labels$y)
# flip ticks
new.ticks <- gp$grobs[[which(gp$layout$name == "axis-l")]]$children[[2]]$grobs[[2]]
new.ticks$x <- unit.c(rep(new.ticks$x[1:2], length(new.ticks$x)/2 - 1),
new.ticks$x)
new.ticks$y <- new.labels$y[rep(seq_along(new.labels$y), each = 2)]
new.ticks$id.lengths <- rep(new.ticks$id.lengths[1], length(new.ticks$y))
# assign flipped labels / ticks back to plot
new.labels -> gp$grobs[[which(gp$layout$name == "axis-l")]]$children[[2]]$grobs[[1]]$children[[1]]
new.ticks -> gp$grobs[[which(gp$layout$name == "axis-l")]]$children[[2]]$grobs[[2]]
# show plot
grid::grid.draw(gp)
(Note: compared to the question, p is defined here with fewer theme specifications, for simplicity)
p <- ggplot(data = i, aes(x = wd, y = co2)) +
ggtitle("CO2")+
geom_point(size=4, colour = "red")+
geom_linerange(aes(ymax =ci2, ymin=ci1), colour = "red", size = 2)+
coord_polar()+
geom_hline(yintercept = seq(365, 405, by = 5),
colour = "grey", size = 0.2) +
geom_vline(xintercept = seq(0, 360, by = 22.5),
colour = "grey", size = 0.2) +
scale_x_continuous(limits = c(0, 360), expand = c(0, 0),
breaks = seq(0, 359.99, by = 22.5),
labels=c("N","NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW")) +
scale_y_continuous(limits = c(365, 405),
breaks = seq(365, 405, by = 10)) +
theme_void() +
theme(axis.ticks = element_line(colour = "grey"),
axis.ticks.length = unit(-0.5, "lines"),
axis.text = element_text(size=12,
margin = unit(rep(1, 4), "lines")),
axis.line.y = element_line(colour = "grey"))
Related
I'm learning to use ggplot to make graphs for my research and I'm having some trouble setting legends for them.
Initially I thought about just using the aes() function inside geom_point and geom_line to get the aesthetics I'm looking for. However, I realized the legends weren't being generated by doing it this way. Code and exemple below.
#Stablish the variables as vectors
MexxJan_hydrogen <- c(0, 1.38, 3.19, 8.30)
MexyJan_hydrogen <- c(0, 1.25, 2.78, 6.23)
MexzJan_hydrogen <- c(0, 2.46, 5.68, 12.18)
MexwJan_hydrogen <- c(0, 7.56, 9.20, 10.19)
time_hydrogen <- c(0, 60, 120, 180)
#Create the data frame
hydrogen_data <- data.frame(time_hydrogen, MexxJan_hydrogen, MexyJan_hydrogen, MexzJan_hydrogen, MexwJan_hydrogen)
view(hydrogen_data)
#Code the plot
hydrogen_plot <- ggplot(data = hydrogen_data) +
geom_line(aes(x = time_hydrogen, y = MexxJan_hydrogen), color = "palegreen3", lwd = 1) +
geom_line(aes(x = time_hydrogen, y = MexyJan_hydrogen), color = "tan1", lwd = 1) +
geom_line(aes(x = time_hydrogen, y = MexzJan_hydrogen), color = "tomato2", lwd = 1) +
geom_line(aes(x = time_hydrogen, y = MexwJan_hydrogen), color = "cadetblue", lwd = 1) +
geom_point(aes(x = time_hydrogen, y = MexxJan_hydrogen), color = "palegreen3", shape = 15, size = 5) +
geom_point(aes(x = time_hydrogen, y = MexyJan_hydrogen), color = "tan1", shape = 16, size = 5) +
geom_point(aes(x = time_hydrogen, y = MexzJan_hydrogen), color = "tomato2", shape = 17, size = 5) +
geom_point(aes(x = time_hydrogen, y = MexwJan_hydrogen), color = "cadetblue", shape = 18, size = 5) +
theme_bw() +
theme(axis.text = element_text(family = "Arial", size = 15, color = "black"),
axis.title.x = element_text(family = "Arial", size = 16, margin = margin(t = 15)),
axis.title.y = element_text(family = "Arial", size = 16, margin = margin(r = 15)),axis.line = element_line(color = "black"),
plot.background = element_rect(fill = "transparent", color = NA),
panel.border = element_rect(color = "black"),
panel.background = element_rect(fill = "transparent"),
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor.y = element_blank(),
axis.ticks.length = unit(0.20, units = "cm"),
legend.background = element_rect(fill = "transparent"),
legend.key = element_rect(fill = "transparent", colour = NA),
legend.position = "top",
legend.key.width = unit(0, unit = "cm"),
legend.key.height = unit(0, unit = "cm"),
legend.title = element_blank(),
legend.text = element_text(size = 13.5),
legend.spacing.x = unit(0.1, "cm"),
legend.text.align = unit(0.05, unit = "cm")) +
labs(x = "Time (min)", y = "Gas Evolution (µmol.g"^-1~")") +
coord_cartesian(ylim = c(0,15), xlim = c(0,180)) +
scale_y_continuous(expand = expansion(mult = c(0.02, 0.02)),
n.breaks = 5) +
scale_x_continuous(expand = expansion(mult = c(0.02, 0.02)),
breaks = c(0, 60, 120, 180))
I then found that I could use the function scale_colors_manual to get the desired colors and show the legend. Also, using scale_colors_manual I managed to change the legend text to a shorter option. Code and exemple below.
#Stablish the variables as vectors
MexxJan_hydrogen <- c(0, 1.38, 3.19, 8.30)
MexyJan_hydrogen <- c(0, 1.25, 2.78, 6.23)
MexzJan_hydrogen <- c(0, 2.46, 5.68, 12.18)
MexwJan_hydrogen <- c(0, 7.56, 9.20, 10.19)
time_hydrogen <- c(0, 60, 120, 180)
#Create the data frame
hydrogen_data <- data.frame(time_hydrogen, MexxJan_hydrogen, MexyJan_hydrogen, MexzJan_hydrogen, MexwJan_hydrogen)
view(hydrogen_data)
hydrogen_plot <- ggplot(data = hydrogen_data) +
geom_line(aes(x = time_hydrogen, y = MexxJan_hydrogen, color = "MexxJan_hydrogen"), lwd = 1) +
geom_line(aes(x = time_hydrogen, y = MexyJan_hydrogen, color = "MexyJan_hydrogen"), lwd = 1) +
geom_line(aes(x = time_hydrogen, y = MexzJan_hydrogen, color = "MexzJan_hydrogen"), lwd = 1) +
geom_line(aes(x = time_hydrogen, y = MexwJan_hydrogen, color = "MexwJan_hydrogen"), lwd = 1) +
geom_point(aes(x = time_hydrogen, y = MexxJan_hydrogen, color = "MexxJan_hydrogen"), shape = 15, size = 5) +
geom_point(aes(x = time_hydrogen, y = MexyJan_hydrogen, color = "MexyJan_hydrogen"), shape = 16, size = 5) +
geom_point(aes(x = time_hydrogen, y = MexzJan_hydrogen, color = "MexzJan_hydrogen"), shape = 17, size = 5) +
geom_point(aes(x = time_hydrogen, y = MexwJan_hydrogen, color = "MexwJan_hydrogen"), shape = 18, size = 5) +
theme_bw() +
theme(axis.text = element_text(family = "Arial", size = 15, color = "black"),
axis.title.x = element_text(family = "Arial", size = 16, margin = margin(t = 15)),
axis.title.y = element_text(family = "Arial", size = 16, margin = margin(r = 15)),axis.line = element_line(color = "black"),
plot.background = element_rect(fill = "transparent", color = NA),
panel.border = element_rect(color = "black"),
panel.background = element_rect(fill = "transparent"),
panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.major.y = element_blank(),
panel.grid.minor.y = element_blank(),
axis.ticks.length = unit(0.20, units = "cm"),
legend.background = element_rect(fill = "transparent"),
legend.key = element_rect(fill = "transparent", colour = NA),
legend.position = "top",
legend.key.width = unit(0, unit = "cm"),
legend.key.height = unit(0, unit = "cm"),
legend.title = element_blank(),
legend.text = element_text(size = 13.5),
legend.spacing.x = unit(0.1, "cm"),
legend.text.align = unit(0.05, unit = "cm")) +
labs(x = "Time (min)", y = "Gas Evolution (µmol.g"^-1~")") +
coord_cartesian(ylim = c(0,15), xlim = c(0,180)) + #Limit the size of the plot
scale_y_continuous(expand = expansion(mult = c(0.02, 0.02)),
n.breaks = 5) +
scale_x_continuous(expand = expansion(mult = c(0.02, 0.02)),
breaks = c(0, 60, 120, 180)) +
scale_color_manual(labels = c("15Me-NT", "15Me-nNT", "15Me-NNT", "15Me-nnt"),
values = c("MexxJan_hydrogen" = "palegreen3", "MexyJan_hydrogen" = "tan1", "MexzJan_hydrogen" = "cadetblue", "MexwJan_hydrogen" = "tomato2"))
In this case, I got the colors and the legend. However, as you can see in the image, the legend keys look like a bunch of geometric forms stacked. I couldn't find a way to solve this. Tried using scale_shape_manual but I couldn't get the code right.
May you help me getting this plot some beautiful aesthetics? hehehe
Thank you. Stay safe.
To fix your issue you have to move shape inside aes similar to what you have done for color and afterwards set your shapes via scale_shape_manual. However, you could simplify your approach considerably by first reshaping your data to long or tidy data format. Doing so allows to add your lines and points which just one geom_point and geom_line:
library(tidyr)
library(ggplot2)
hydrogen_data_long <- hydrogen_data %>%
tidyr::pivot_longer(-time_hydrogen, names_to = "hydrogren")
ggplot(hydrogen_data_long, aes(x = time_hydrogen, y = value, color = hydrogren)) +
geom_line(lwd = 1) +
geom_point(aes(shape = hydrogren), size = 5) +
scale_shape_manual(
labels = c("15Me-NT", "15Me-nNT", "15Me-NNT", "15Me-nnt"),
values = c(
"MexxJan_hydrogen" = 15, "MexyJan_hydrogen" = 16,
"MexzJan_hydrogen" = 17, "MexwJan_hydrogen" = 18
)
) +
scale_color_manual(
labels = c("15Me-NT", "15Me-nNT", "15Me-NNT", "15Me-nnt"),
values = c(
"MexxJan_hydrogen" = "palegreen3", "MexyJan_hydrogen" = "tan1",
"MexzJan_hydrogen" = "cadetblue", "MexwJan_hydrogen" = "tomato2"
)
) +
theme_bw() +
theme(
axis.text = element_text(family = "Arial", size = 15, color = "black"),
axis.title.x = element_text(family = "Arial", size = 16, margin = margin(t = 15)),
axis.title.y = element_text(family = "Arial", size = 16, margin = margin(r = 15)),
axis.line = element_line(color = "black"),
plot.background = element_rect(fill = "transparent", color = NA),
panel.border = element_rect(color = "black"),
panel.background = element_rect(fill = "transparent"),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
axis.ticks.length = unit(0.20, units = "cm"),
legend.background = element_rect(fill = "transparent"),
legend.key = element_rect(fill = "transparent", colour = NA),
legend.position = "top",
legend.key.width = unit(0, unit = "cm"),
legend.key.height = unit(0, unit = "cm"),
legend.title = element_blank(),
legend.text = element_text(size = 13.5),
legend.spacing.x = unit(0.1, "cm"),
legend.text.align = unit(0.05, unit = "cm")
) +
labs(x = "Time (min)", y = "Gas Evolution (µmol.g"^-1 ~ ")") +
coord_cartesian(ylim = c(0, 15), xlim = c(0, 180)) + # Limit the size of the plot
scale_y_continuous(
expand = expansion(mult = c(0.02, 0.02)),
n.breaks = 5
) +
scale_x_continuous(
expand = expansion(mult = c(0.02, 0.02)),
breaks = c(0, 60, 120, 180)
)
You are making life harder for yourself by passing your data frame in the wrong format. If you pivot to long format, you only need a single geom_line and geom_point. It's also far easier to map your colors and shapes, which will automatically appear in the legend.
Also, try to choose a default theme that's closer to the look you want to achieve to cut down on the number of tweaks you have to make via theme. One of the key things you'll learn in R, as in other languages, is that cutting down code to a minimum makes it easier to change or debug your code later on.
library(tidyverse)
hydrogen_data %>%
pivot_longer(-time_hydrogen) %>%
ggplot(aes(time_hydrogen, value, color = name, shape = name)) +
geom_line(lwd = 1) +
geom_point(size = 5) +
scale_color_manual(values = c("tomato2", "palegreen", "tan1", "cadetblue"),
labels = paste0("15Me-", c("NT", "nNT", "NNT", "nnt"))) +
scale_shape_manual(values = c(18, 15, 16, 17),
labels = paste0("15Me-", c("NT", "nNT", "NNT", "nnt"))) +
scale_y_continuous(expression(Gas~Evolution~(µmol.g^-1)),
expand = expansion(mult = c(0.02, 0.02)), n.breaks = 5) +
scale_x_continuous("Time (min)", expand = expansion(mult = c(0.02, 0.02)),
breaks = c(0, 60, 120, 180)) +
theme_classic(base_size = 16) +
theme(axis.text = element_text(family = "Arial", size = 15, color = "black"),
plot.background = element_blank(),
panel.border = element_rect(color = "black", fill = NA),
panel.background = element_blank(),
axis.ticks.length = unit(0.20, units = "cm"),
legend.background = element_blank(),
legend.position = "top",
legend.title = element_blank()) +
coord_cartesian(ylim = c(0, 15), xlim = c(0, 180))
I was hoping to receive some guidance on how to reduce the space between labels specified in scale_x_continuous and the x axis. The empty space I would like to remove is indicated in the text in red in the following diagram.
Thank you for your help - it is much appreciated!
I have attached the code to reproduce this plot.
i <- structure(list(wd = c(0, 112.5, 135, 180, 202.5, 22.5, 225, 247.5,
270, 292.5, 337.5, 45, 67.5, 90), co2 = c(389.82, 376.82, 386.06,
392.04, 392.55, 387.97, 391.45, 389.87, 390.12, 389.68, 391.39,
390.1, 386.89, 383.05), ci1 = c(388.37, 367.67, 378.98, 381.76,
388.63, 386.65, 388.32, 388.5, 389.03, 387.25, 389.05, 388.65,
385.64, 381.1), ci2 = c(391.26, 385.98, 393.15, 402.31, 396.46,
389.28, 394.58, 391.23, 391.21, 392.12, 393.73, 391.55, 388.15,
385.01)), row.names = c(NA, -14L), class = "data.frame")
library(ggplot2)
ggplot(data = i, aes(x = wd, y = co2)) +
geom_point(size=4, colour = "red")+
geom_linerange(aes(ymax =ci2, ymin=ci1), colour = "red", size = 2)+
coord_polar()+
geom_hline(yintercept = seq(365, 405, by = 5), colour = "grey", size = 0.2) +
geom_vline(xintercept = seq(0, 360, by = 22.5), colour = "grey", size = 0.2) +
scale_x_continuous(limits = c(0, 360), expand = c(0, 0),
breaks = seq(0, 359.99, by = 22.5),
labels=c("N","NNE","NE","ENE","E","ESE","SE","SSE",
"S","SSW","SW","WSW","W","WNW","NW","NNW"),position = "top") +
scale_y_continuous(limits = c(365, 405), breaks = seq(365, 405, by = 10)) +
theme_bw() +
theme(panel.border = element_blank(),
panel.grid = element_blank(),
legend.key = element_blank(),
axis.ticks = element_line(colour = "grey"),
axis.ticks.length = unit(-1, "lines"),
axis.ticks.margin = unit(1.3,"lines"),
axis.text = element_text(size=24),
axis.text.x = element_text(vjust = -10),
axis.text.y = element_text(size=24),
axis.title = element_blank(),
axis.line=element_line(),
axis.line.x=element_blank(),
axis.line.y = element_line(colour = "grey"),
plot.title = element_text(hjust = 0, size = 20))
This is pretty easy to do with coord_curvedpolar from geomtextpath. The vjust argument will work as expected, pushing or pulling the text away from or towards the center of the plot. Here is axis.text.x = element_text(vjust = 2)
library(ggplot2)
library(geomtextpath)
ggplot(data = i, aes(x = wd, y = co2)) +
geom_point(size=4, colour = "red")+
geom_linerange(aes(ymax =ci2, ymin=ci1), colour = "red", size = 2)+
coord_curvedpolar()+
geom_hline(yintercept = seq(365, 405, by = 5), colour = "grey", size = 0.2) +
geom_vline(xintercept = seq(0, 360, by = 22.5), colour = "grey", size = 0.2) +
scale_x_continuous(limits = c(0, 360), expand = c(0, 0),
breaks = seq(0, 359.99, by = 22.5),
labels=c("N","NNE","NE","ENE","E","ESE","SE","SSE",
"S","SSW","SW","WSW","W","WNW","NW","NNW"),position = "top") +
scale_y_continuous(limits = c(365, 405), breaks = seq(365, 405, by = 10)) +
theme_bw() +
theme(panel.border = element_blank(),
panel.grid = element_blank(),
legend.key = element_blank(),
axis.ticks = element_line(colour = "grey"),
axis.ticks.length = unit(-1, "lines"),
axis.text = element_text(size = 12),
axis.text.x = element_text(vjust = 2),
axis.text.y = element_text(size = 12),
axis.title = element_blank(),
axis.line=element_line(),
axis.line.x=element_blank(),
axis.line.y = element_line(colour = "grey"),
plot.title = element_text(hjust = 0, size = 20))
The same plot with axis.text.x = element_text(vjust = 5)
The same plot with axis.text.x = element_text(vjust = -1)
I am trying to move the legend text and legend boxes further apart (horizontally) on a box and jitter plot. The complicating factor is the coord_flip I used to make the boxplot horizontal. In theme I tried using both legend.spacing.x and legend.spacing.y but neither had any effect on the distance between legend text and legend boxes.
Here is the graph with fake data. More complex than necessary I know but I need to be able to make it work with all the complications.
library(dplyr)
library(ggplot2)
set.seed(01234)
# make some data
totDays <- data.frame(id = 1:80,
group = rep(c("Placebo", "Drug"), each = 40),
total84 = c(pmin(abs(round(rnorm(40, 55, 30))),84), pmin(abs(round(rnorm(40, 38, 30))),84)))
# get some descriptives
(groupDF <- totDays %>% group_by(group) %>%
dplyr::summarise(m = mean(total84, na.rm = T),
sd = sd(total84, na.rm = T),
count = n()) %>%
mutate(se = sd/sqrt(count)))
# now for the box and scatter plot
(g <- ggplot(totDays, aes(group, total84, colour = group)) +
geom_jitter(size = 1, width = 0.1) + # so points aren't overlaid, width controls how much jitter
geom_point(stat = "summary", fun.y = "mean", shape = 3, size = 3, colour = "black") + # crosses for mean
geom_boxplot(alpha = 0, width = 0.5, lwd = 1, size = 0.5) +
scale_color_manual(values = c("#00AFBB", "#E7B800")) +
scale_y_continuous(breaks = seq(0,84,14), minor_breaks = seq(0, 84, 14)) + # changes minor break line
coord_flip() +
labs(y = "Score") +
geom_hline(yintercept = c(groupDF$m), linetype = "dotted") +
geom_segment(x = 2.38, xend = 2.38, y = groupDF$m[2] + .1, yend = groupDF$m[1] - .1, size = .7, arrow = arrow(end = "both", type = "open", length = unit(0.15, "cm")), colour = "#696969") +
annotate("text", x = 2.46, y = mean(groupDF$m), label = paste0("italic(p) == ", 0.02), parse = T) +
theme_bw() +
theme(axis.title.y = element_blank(),
axis.ticks.y = element_blank(),
axis.text.y = element_blank(),
axis.text.x = element_text(size = 13),
axis.title.x = element_text(size = 13, face = "bold", margin = margin(t = 0, r = 0, b = 10, l = 0), vjust = -2), # note the use of margin to move the title away from the axis text
legend.title = element_blank(),
legend.position = "top",
legend.spacing.y = unit(.1, "cm"),
legend.box.spacing = unit(.1, "cm"), # adjusts distance of box from x-axis
legend.key.size = unit(1, "cm"),
legend.text = element_text(size = 13, face = "bold"),
strip.text = element_text(size = 13, face = "bold"),
panel.grid.major.y = element_blank(),
panel.grid.major.x = element_line(size=.4, color="#F7F7F7")))
Use either stringr::str_pad() or theme(legend.spacing.x = ...) or both
g <- ggplot(totDays, aes(group, total84, colour = group)) +
geom_jitter(size = 1, width = 0.1) + # so points aren't overlaid, width controls how much jitter
geom_point(stat = "summary", fun.y = "mean", shape = 3, size = 3, colour = "black") + # crosses for mean
geom_boxplot(alpha = 0, width = 0.5, lwd = 1, size = 0.5) +
scale_color_manual(values = c("#00AFBB", "#E7B800"),
### added
labels = stringr::str_pad(c("Drug", "Placebo"), 10, "right")) +
scale_y_continuous(breaks = seq(0,84,14), minor_breaks = seq(0, 84, 14)) + # changes minor break line
coord_flip() +
labs(y = "Score") +
geom_hline(yintercept = c(groupDF$m), linetype = "dotted") +
geom_segment(x = 2.38, xend = 2.38, y = groupDF$m[2] + .1, yend = groupDF$m[1] - .1, size = .7,
arrow = arrow(end = "both", type = "open", length = unit(0.15, "cm")), colour = "#696969") +
annotate("text", x = 2.46, y = mean(groupDF$m), label = paste0("italic(p) == ", 0.02), parse = T) +
theme_bw() +
theme(axis.title.y = element_blank(),
axis.ticks.y = element_blank(),
axis.text.y = element_blank(),
axis.text.x = element_text(size = 13),
axis.title.x = element_text(size = 13, face = "bold",
margin = margin(t = 0, r = 0, b = 10, l = 0), vjust = -2),
legend.title = element_blank(),
legend.position = "top",
### added
legend.spacing.x = unit(0.25, 'cm'),
legend.spacing.y = unit(.1, "cm"),
legend.box.spacing = unit(.1, "cm"), # adjusts distance of box from x-axis
legend.key.size = unit(1, "cm"),
legend.text = element_text(size = 13, face = "bold"),
strip.text = element_text(size = 13, face = "bold"),
panel.grid.major.y = element_blank(),
panel.grid.major.x = element_line(size=.4, color="#F7F7F7"))
Created on 2019-03-11 by the reprex package (v0.2.1.9000)
I am trying to generate a barplot with dual Y-axis and error bars. I have successfully generated a plot with error bars for one variable but I don't know how to add error bars for another one. My code looks like this. Thanks.
library(ggplot2)
#Data generation
Year <- c(2014, 2015, 2016)
Response <- c(1000, 1100, 1200)
Rate <- c(0.75, 0.42, 0.80)
sd1<- c(75, 100, 180)
sd2<- c(75, 100, 180)
df <- data.frame(Year, Response, Rate,sd1,sd2)
df
# The errorbars overlapped, so use position_dodge to move them horizontally
pd <- position_dodge(0.7) # move them .05 to the left and right
png("test.png", units="in", family="Times", width=2, height=2.5, res=300) #pointsize is font size| increase image size to see the key
ggplot(df) +
geom_bar(aes(x=Year, y=Response),stat="identity", fill="tan1", colour="black")+
geom_errorbar(aes(x=Year, y=Response, ymin=Response-sd1, ymax=Response+sd1),
width=.2, # Width of the error bars
position=pd)+
geom_line(aes(x=Year, y=Rate*max(df$Response)),stat="identity",color = 'red', size = 2)+
geom_point(aes(x=Year, y=Rate*max(df$Response)),stat="identity",color = 'black',size = 3)+
scale_y_continuous(name = "Left Y axis", expand=c(0,0),limits = c(0, 1500),breaks = seq(0, 1500, by=500),sec.axis = sec_axis(~./max(df$Response),name = "Right Y axis"))+
theme(
axis.title.y = element_text(color = "black"),
axis.title.y.right = element_text(color = "blue"))+
theme(
axis.text=element_text(size=6, color = "black",family="Times"),
axis.title=element_text(size=7,face="bold", color = "black"),
plot.title = element_text(color="black", size=5, face="bold.italic",hjust = 0.5,margin=margin(b = 5, unit = "pt")))+
theme(axis.text.x = element_text(angle = 360, hjust = 0.5, vjust = 1.2,color = "black" ))+
theme(axis.line = element_line(size = 0.2, color = "black"),axis.ticks = element_line(colour = "black", size = 0.2))+
theme(axis.ticks.length = unit(0.04, "cm"))+
theme(plot.margin=unit(c(1,0.1,0.1,0.4),"mm"))+
theme(axis.title.y = element_text(margin = margin(t = 0, r = 4, b = 0, l = 0)))+
theme(axis.title.x = element_text(margin = margin(t = 0, r = 4, b = 2, l = 0)))+
theme(
panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
panel.background = element_blank())+
ggtitle("SRG3")+
theme(legend.position="top")+
theme( legend.text=element_text(size=4),
#legend.justification=c(2.5,1),
legend.key = element_rect(size = 1.5),
legend.key.size = unit(0.3, 'lines'),
legend.position=c(0.79, .8), #width and height
legend.direction = "horizontal",
legend.title=element_blank())
dev.off()
and my plot is as follows:
A suggestion for future questions: your example is far from being a minimal reproducible example. All the visuals an the annotations are not related to your problem but render the code overly complex which makes it harder for others to work with it.
The following would be sufficient:
ggplot(df) +
geom_bar(aes(x = Year, y = Response),
stat = "identity", fill = "tan1",
colour = "black") +
geom_errorbar(aes(x = Year, ymin = Response - sd1, ymax = Response + sd1),
width = .2,
position = pd) +
geom_line(aes(x = Year, y = Rate * max(df$Response)),
color = 'red', size = 2) +
geom_point(aes(x = Year, y = Rate * max(df$Response)),
color = 'black', size = 3)
(Notice that I've removed stat = "identity" in all geom_s because this is set by default. Furthermore, y is not a valid aestetic for geom_errorbar() so I omitted that, too.)
Assuming that the additional variable you would like to plot error bars for is Rate * max(df$Response)) and that the relevant standard deviation is sd2, you may simply append
+ geom_errorbar(aes(x = Year, ymin = Rate * max(df$Response) - sd2,
ymax = Rate * max(df$Response) + sd2),
colour = "green",
width = .2)
to the code chunk above. This yields the output below.
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)))