Drawing a 3 axis graph in ggplot2 with r - r

https://imgur.com/a/fYGgpu7
I am trying to recreate a graph such as these below in ggplot2. I have been looking for 3 axis and seem to be getting 3d visualizations which is clearly not what I need so my googlefu has let me down.
My data is very simple:
https://imgur.com/a/eM8tKAG
With the CTD column determining a different graph.
I guess my main issue is the scaling of the axis. My y axis is Depth. It is common to inverse this value as it places the surface of the water at the top.

It's considered suboptimal by many (myself included) to have even 2 axes on the same dimension of a plot. There are simply better ways of presenting the same information. It is possible to have a second axis in ggplot, but if you want a third you'll have to create it yourself:
ggplot(df, aes(Salinity, Depth)) +
geom_line(color = "green4") +
geom_line(aes(x = (Temperature - 8.25) * 15 + 29), color = "red3") +
geom_line(aes(x = Silicate * 0.3 + 24.5), col = "deepskyblue3") +
annotate(geom = "text", x = seq(15, 27, 3) * 0.3 + 24.5, y = -0.5,
label = seq(15, 27, 3), col = "deepskyblue3", size = 3.1) +
annotate(geom = "text", color = "deepskyblue3", x=30.87, y = -1.5,
label = "Silicates") +
geom_hline(yintercept = 0, color = "deepskyblue3") +
scale_x_continuous(sec.axis = sec_axis(name = "Temperature",
trans = function(x) {
(x - 28) / 15 + 8.25
})) +
coord_cartesian(ylim = c(-2, 20), clip = "off") +
theme_minimal() +
theme(plot.margin = margin(10, 10, 50, 10),
axis.text.x.top = element_text(colour = "red3"),
axis.title.x.top = element_text(colour = "red3"),
axis.ticks.x.top = element_line(color = "red3"),
axis.line.x.top = element_line(color = "red3"),
axis.text.x.bottom = element_text(colour = "green4"),
axis.title.x.bottom = element_text(colour = "green4"),
axis.ticks.x.bottom = element_line(color = "green4"),
axis.line.x.bottom = element_line(colour = "green4"),
axis.line.y.left = element_line())
Data transcribed from OP
df <- data.frame(CTD = c(1, 1, 1, 2, 2),
Depth = c(17.78, 3.89, 1.44, 13.23, 1.34),
Temperature = c(8.28, 8.31, 8.49, 8.25, 8.31),
Salinity = c(31.9, 31.39, 30.45, 32.61, 29.11),
Silicate = c (17.19643, 19.51786, 24.07143, 14.78571, 27.64286))

Related

Why does the top line of ggplot disappear when using xlim, ylim and scale_continuous to define breaks

I am using this piece of code to create a series of 4 point plots. I need the plots to go from x1 to x2 and y1 to y2. The length of the axes is always 10 with a single major break halfway and minor breaks at each unit.
When I get the scale and the breaks right I sometimes (not always) lose the top line on the box surrounding the map
The parts of the data set that are involved are
tag: an identifier used to label the points
lx, ly: the coordinates of the plot which range from 0 -20 in the dataset but each map does only a quarter of the area. So x goes from 0 to 10 or 10 to 20 and y goes from 0 to 10 or 10 to 20.
I tried this piece of code. I expect a point plot surrounded by a box
n ranges from 1:4
x1 = c(0, 10, 10, 0)
x2 = c(10, 20, 20, 10)
y1 = c(0, 0, 10, 10)
y2 = c(10, 10, 20, 20)
theme_set(theme_bw())
ggplot(onemap, aes(x = onemap$lx, y = onemap$ly)) + geom_point(size =
.3) +
xlim(c(x1[n], x2[n])) + ylim(c(y1[n], y2[n])) +
# coord_cartesian(expand = FALSE)
# scale_x_continuous(expand = c(0, 0), limits = c(0, NA)) +
scale_y_continuous(breaks = seq(y1[n], y2[n], 5),
minor_breaks = seq(y1[n], y2[n], 1)) +
scale_x_continuous(breaks = seq(x1[n], x2[n], 5),
minor_breaks = seq(x1[n], x2[n], 1)) +
labs(
x = element_blank(),
y = element_blank(),
title = hd,
subtitle = subheads
) +
theme(plot.title.position = "plot") +
theme(
plot.title = element_text(
size = 14,
face = "bold",
margin = margin(8, 0, 8, 0)
),
plot.subtitle = element_text(size = 10),
plot.margin = margin(
t = 1,
r = 2,
b = 1.5,
l = 2,
unit = "cm"
),
axis.ticks = element_blank(),
axis.text = element_text(size = 6),
axis.text.y = element_text(angle = 90)
) +
theme(
panel.grid.major = element_line(color = "gray30", linewidth = .25),
panel.grid.minor = element_line(
color = "gray30",
linewidth = .25,
linetype = "dashed"
),
panel.border = element_blank()
) +
geom_text_repel(
aes(label = tag),
box.padding = 0.01,
size = 2,
xlim = c(-Inf, Inf),
ylim = c(-Inf, Inf),
max.overlaps = 45,
segment.size = 2,
segment.color = "grey"
)
I worked out the problem. I should not have used xlim and ylim in the main body of ggplot. I should have used the limits in scale_x_continuous and scale_y_continuous as below.
scale_y_continuous(breaks = seq(y1[n], y2[n], 5), minor_breaks = seq(y1[n], y2[n], 1),limits=c(y1[n], y2[n])) +
scale_x_continuous(breaks = seq(x1[n], x2[n], 5), minor_breaks = seq(x1[n], x2[n], 1),limits=c(x1[n], x2[n])) +

GGPLOT2: Adjust Font Size of Plot Title

I have This ggplot2 I made up to satisfy these conditions:
Remove default background that is hash colour to be plain.
Make (a) to be the plot title located within the plot area that is not close to the line (automatically).
Make $\phi = .8$ to be automatically at the head of the line (still within the plot area).
And sd = 1 to be automatically at the tail of the line.
The four(4) Borderlines to be present.
Gridlines to be a grey colour.
.
## simulate ARIMA(1, 0, 0)
set.seed(799837)
ts <- arima.sim(n = 10, model = list(ar = 0.95, order = c(1, 0, 0)), sd = 10)
gplot <- ggplot(NULL, aes(y = ts, x = seq_along(ts))) +
geom_line(color = "#F2AA4CFF") +
geom_point(color = "#101820FF") +
annotate("text", x = mean(seq_along(ts)), y = max(ts) * 1.1, label = "(a)")+
annotate("text", x = min(seq_along(ts)), y = max(ts) * 1.1, label = 'paste(~phi~"=.8")', parse = TRUE )+
annotate("text", x= max(seq_along(ts)), y = ts[[max(seq_along(ts))]] * 1.1, label = "sd=1") +
xlab('Time') +
ylab('Series') +
theme_bw() +
theme(axis.text = element_text(size = 40, angle = 0, vjust = 0.0, hjust = 0.0), #y-axis label size
axis.title = element_text(size = 40), #x-axis label size
axis.title.x = element_text(angle = 0, hjust = 0.5, vjust = 0.5, size = 40), # x-axis title
axis.title.y = element_text(angle = 90, hjust = 0.5, vjust = 0.5, size = 40), # y-axis title
plot.title = element_text(size = 40, margin = margin(t = 25, b = -20, l = 0, r = 0)),
panel.background = element_blank()) +
scale_x_continuous(breaks = seq(1,10,2)) +
scale_y_continuous(expand = c(0.0, 0.00))
gplot
I want the font of the plot title to increase. As you can see that despite setting the font of the plot title to 40 the font title refuse to increase. This question is a follow-up question from Remove Default Background Color and Make Title in Plot Zone
Daniel
If (a) is the 'title' it's not really the title, it's an annotation.
So to change it's size do it when you add the annotation.
annotate("text", x = mean(seq_along(ts)), y = max(ts) * 1.5, label = "(a)", size = 40)
You might also want to resize the other annotations.
annotate("text", x = mean(seq_along(ts)), y = max(ts) * 1.5, label = "(a)", size = 40) +
annotate("text", x = min(seq_along(ts)), y = max(ts) * 1.5, label = 'paste(~phi~"=.8")', parse = TRUE, size = 10)+
annotate("text", x= max(seq_along(ts)), y = ts[[max(seq_along(ts))]] * 1.5, label = "sd=1", size = 10)

ggplot2 Create shaded area with gradient below curve

I would like to create the plot below using ggplot.
Does anyone know of any geom that create the shaded region below the line chart?
Thank you
I think you're just looking for geom_area. However, I thought it might be a useful exercise to see how close we can get to the graph you are trying to produce, using only ggplot:
Pretty close. Here's the code that produced it:
Data
library(ggplot2)
library(lubridate)
# Data points estimated from the plot in the question:
points <- data.frame(x = seq(as.Date("2019-10-01"), length.out = 7, by = "month"),
y = c(2, 2.5, 3.8, 5.4, 6, 8.5, 6.2))
# Interpolate the measured points with a spline to produce a nice curve:
spline_df <- as.data.frame(spline(points$x, points$y, n = 200, method = "nat"))
spline_df$x <- as.Date(spline_df$x, origin = as.Date("1970-01-01"))
spline_df <- spline_df[2:199, ]
# A data frame to produce a gradient effect over the filled area:
grad_df <- data.frame(yintercept = seq(0, 8, length.out = 200),
alpha = seq(0.3, 0, length.out = 200))
Labelling functions
# Turns dates into a format matching the question's x axis
xlabeller <- function(d) paste(toupper(month.abb[month(d)]), year(d), sep = "\n")
# Format the numbers as per the y axis on the OP's graph
ylabeller <- function(d) ifelse(nchar(d) == 1 & d != 0, paste0("0", d), d)
Plot
ggplot(points, aes(x, y)) +
geom_area(data = spline_df, fill = "#80C020", alpha = 0.35) +
geom_hline(data = grad_df, aes(yintercept = yintercept, alpha = alpha),
size = 2.5, colour = "white") +
geom_line(data = spline_df, colour = "#80C020", size = 1.2) +
geom_point(shape = 16, size = 4.5, colour = "#80C020") +
geom_point(shape = 16, size = 2.5, colour = "white") +
geom_hline(aes(yintercept = 2), alpha = 0.02) +
theme_bw() +
theme(panel.grid.major.x = element_blank(),
panel.grid.minor.x = element_blank(),
panel.grid.minor.y = element_blank(),
panel.border = element_blank(),
axis.line.x = element_line(),
text = element_text(size = 15),
plot.margin = margin(unit(c(20, 20, 20, 20), "pt")),
axis.ticks = element_blank(),
axis.text.y = element_text(margin = margin(0,15,0,0, unit = "pt"))) +
scale_alpha_identity() + labs(x="",y="") +
scale_y_continuous(limits = c(0, 10), breaks = 0:5 * 2, expand = c(0, 0),
labels = ylabeller) +
scale_x_date(breaks = "months", expand = c(0.02, 0), labels = xlabeller)

Exact Positioning of multiple plots in ggplot2 with grid.arrange

I'm trying to create a multiple plot with the same x-axis but different y-axes, because I have values for two groups with different ranges. As I want to control the values of the axes (respectively the y-axes shall reach from 2.000.000 to 4.000.000 and from 250.000 to 500.000), I don't get along with facet_grid with scales = "free".
So what I've tried is to create two plots (named "plots.treat" and "plot.control") and combine them with grid.arrange and arrangeGrob. My problem is, that I don't know how to control the exact position of the two plots, so that both y-axes are positioned on one vertical line. So in the example below the second plot's y-axis needs to be positioned a bit more to the right.
Here is the code:
# Load Packages
library(ggplot2)
library(grid)
library(gridExtra)
# Create Data
data.treat <- data.frame(seq(2005.5, 2015.5, 1), rep("SIFI", 11),
c(2230773, 2287162, 2326435, 2553602, 2829325, 3372657, 3512437,
3533884, 3519026, 3566553, 3527153))
colnames(data.treat) <- c("Jahr", "treatment",
"Aggregierte Depositen (in Tausend US$)")
data.control <- data.frame(seq(2005.5, 2015.5, 1), rep("Nicht-SIFI", 11),
c(324582, 345245, 364592, 360006, 363677, 384674, 369007,
343893, 333370, 318409, 313853))
colnames(data.control) <- c("Jahr", "treatment",
"Aggregierte Depositen (in Tausend US$)")
# Create Plot for data.treat
plot.treat <- ggplot() +
geom_line(data = data.treat,
aes(x = `Jahr`,
y = `Aggregierte Depositen (in Tausend US$)`),
size = 1,
linetype = "dashed") +
geom_point(data = data.treat,
aes(x = `Jahr`,
y = `Aggregierte Depositen (in Tausend US$)`),
fill = "white",
size = 2,
shape = 24) +
scale_x_continuous(breaks = seq(2005, 2015.5, 1),
minor_breaks = seq(2005, 2015.5, 0.5),
limits = c(2005, 2015.8),
expand = c(0.01, 0.01)) +
scale_y_continuous(breaks = seq(2000000, 4000000, 500000),
minor_breaks = seq(2000000, 4000000, 250000),
labels = c("2.000.000", "2.500.000", "3.000.000",
"3.500.000", "4.000.000"),
limits = c(2000000, 4000000),
expand = c(0, 0.01)) +
theme(text = element_text(family = "Times"),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.line.x = element_line(color="black", size = 0.6),
axis.line.y = element_line(color="black", size = 0.6),
legend.position = "none") +
geom_segment(aes(x = c(2008.7068),
y = c(2000000),
xend = c(2008.7068),
yend = c(3750000)),
linetype = "dotted") +
annotate(geom = "text", x = 2008.7068, y = 3875000, label = "Lehman\nBrothers + TARP",
colour = "black", size = 3, family = "Times") +
geom_segment(aes(x = c(2010.5507),
y = c(2000000),
xend = c(2010.5507),
yend = c(3750000)),
linetype = "dotted") +
annotate(geom = "text", x = 2010.5507, y = 3875000, label = "Dodd-Frank-\nAct",
colour = "black", size = 3, family = "Times") +
geom_rect(aes(xmin = 2007.6027, xmax = 2009.5, ymin = -Inf, ymax = Inf),
fill="dark grey", alpha = 0.2)
# Create Plot for data.control
plot.control <- ggplot() +
geom_line(data = data.control,
aes(x = `Jahr`,
y = `Aggregierte Depositen (in Tausend US$)`),
size = 1,
linetype = "solid") +
geom_point(data = data.control,
aes(x = `Jahr`,
y = `Aggregierte Depositen (in Tausend US$)`),
fill = "white",
size = 2,
shape = 21) +
scale_x_continuous(breaks = seq(2005, 2015.5, 1), # x-Achse
minor_breaks = seq(2005, 2015.5, 0.5),
limits = c(2005, 2015.8),
expand = c(0.01, 0.01)) +
scale_y_continuous(breaks = seq(250000, 500000, 50000),
minor_breaks = seq(250000, 500000, 25000),
labels = c("250.000", "300.000", "350.000", "400.000",
"450.000", "500.000"),
limits = c(250000, 500000),
expand = c(0, 0.01)) +
theme(text = element_text(family = "Times"),
axis.title.x = element_blank(), # Achse
axis.title.y = element_blank(), # Achse
axis.line.x = element_line(color="black", size = 0.6),
axis.line.y = element_line(color="black", size = 0.6),
legend.position = "none") +
geom_segment(aes(x = c(2008.7068),
y = c(250000),
xend = c(2008.7068),
yend = c(468750)),
linetype = "dotted") +
annotate(geom = "text", x = 2008.7068, y = 484375, label = "Lehman\nBrothers + TARP",
colour = "black", size = 3, family = "Times") +
geom_segment(aes(x = c(2010.5507),
y = c(250000),
xend = c(2010.5507),
yend = c(468750)),
linetype = "dotted") +
annotate(geom = "text", x = 2010.5507, y = 484375, label = "Dodd-Frank-\nAct",
colour = "black", size = 3, family = "Times") +
geom_rect(aes(xmin = 2007.6027, xmax = 2009.5, ymin = -Inf, ymax = Inf),
fill="dark grey", alpha = 0.2)
# Combine both Plots with grid.arrange
grid.arrange(arrangeGrob(plot.treat, plot.control,
ncol = 1,
left = textGrob("Aggregierte Depositen (in Tausend US$)",
rot = 90,
vjust = 1,
gp = gpar(fontfamily = "Times",
size = 12,
colout = "black",
fontface = "bold")),
bottom = textGrob("Jahr",
vjust = 0.1,
hjust = 0.2,
gp = gpar(fontfamily = "Times",
size = 12,
colout = "black",
fontface = "bold"))))
Do:
install.packages("cowplot")
but do not library(cowplot) as it'll mess up your theme work.
Then, do:
grid.arrange(
arrangeGrob(cowplot::plot_grid(plot.treat, plot.control, align = "v", ncol=1),
ncol = 1,
left = textGrob("Aggregierte Depositen (in Tausend US$)",
rot = 90,
vjust = 1,
gp = gpar(fontfamily = "Times",
size = 12,
colout = "black",
fontface = "bold")),
bottom = textGrob("Jahr",
vjust = 0.1,
hjust = 0.2,
gp = gpar(fontfamily = "Times",
size = 12,
colout = "black",
fontface = "bold"))))

Symmetrical axis labels for polar plot

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

Resources