When merging axis labels with the patchwork
package, problems occurred (see this question). From the answer of the question, I applied the idea of the example code to my concrete example, in which I also used a fixed aspect ratio for each plot.
Here is the example code
library(ggplot2)
library(patchwork)
# Create different datasets for each plot
df1 <- expand.grid(x = seq(300, 800, length.out = 50), y = seq(300, 600, length.out = 50))
df1$z <- with(df1, dnorm(x, mean = 500, sd = 50) * dnorm(y, mean = 400, sd = 50))
df2 <- expand.grid(x = seq(300, 800, length.out = 50), y = seq(300, 600, length.out = 50))
df2$z <- with(df2, dnorm(x, mean = 600, sd = 50) * dnorm(y, mean = 450, sd = 50))
df3 <- expand.grid(x = seq(300, 800, length.out = 50), y = seq(300, 600, length.out = 50))
df3$z <- with(df3, dnorm(x, mean = 550, sd = 50) * dnorm(y, mean = 500, sd = 50))
df4 <- expand.grid(x = seq(300, 800, length.out = 50), y = seq(300, 600, length.out = 50))
df4$z <- with(df4, dnorm(x, mean = 650, sd = 50) * dnorm(y, mean = 350, sd = 50))
# Compute global min and max for z-values across all datasets
min_z <- min(c(df1$z, df2$z, df3$z, df4$z), na.rm = TRUE)
max_z <- max(c(df1$z, df2$z, df3$z, df4$z), na.rm = TRUE)
# Generate basic ggplot() objects with fixed aspect ratio
p_tmp <- lapply(list(df1, df2, df3, df4), function(df) {
ggplot(df, aes(x, y, fill = z)) +
geom_raster(interpolate = TRUE) +
theme_minimal() +
theme(
aspect.ratio = 1,
legend.position = "bottom",
legend.box = "horizontal"
)
})
plot_aspr <- wrap_plots(
p_tmp,
nrow = 2,
ncol = 2,
axis_titles = "collect",
guides = "collect"
) +
plot_annotation(
title = "Emission-Excitation-Matrix",
subtitle = "Rayleigh Filtered Data") &
labs(
x = "Emission Wavelength / nm",
y = "Excitation Wavelength / nm"
) &
scale_fill_viridis_c(limits = c(min_z, max_z)) &
coord_cartesian(expand = FALSE)
print(plot_aspr)
and the corresponding plot. In this plot, the axis labels are not merged, but the legends are. In addition, the individual efficiencies are distributed here and have the desired square shape by definition.
Without the fixed aspect ratio
# Generate basic ggplot() objects without fixed aspect ratio
p_tmp <- lapply(list(df1, df2, df3, df4), function(df) {
ggplot(df, aes(x, y, fill = z)) +
geom_raster(interpolate = TRUE) +
theme_minimal() +
theme(
legend.position = "bottom",
legend.box = "horizontal"
)
})
plot_noaspr <- wrap_plots(
p_tmp,
nrow = 2,
ncol = 2,
heights = rep(1, 2),
widths = rep(1, 2),
axis_titles = "collect",
guides = "collect"
) +
plot_annotation(
title = "Emission-Excitation-Matrix",
subtitle = "Rayleigh Filtered Data") &
labs(
x = "Emission Wavelength / nm",
y = "Excitation Wavelength / nm"
) &
scale_fill_viridis_c(limits = c(min_z, max_z)) &
coord_cartesian(expand = FALSE)
print(plot_noaspr)
results in the following plot for the same data set:
In this case, both the axis labels and the legends are combined.
One shortcoming here is that the shape of the individual graphs in the overall graph is not automatically perfectly square.
Based on the results, I conclude that axis_title = "collect"
from patchwork
is not compatible with aspect.ratio
, but is compatible with guide = "collect"
. Hence the question of whether this is desired or a bug.
Edit:
After posting this question, I found an interesting question and article regarding this topic. However, the problem was mainly the alignment of the graphs and not the combination of their axis titles.
When merging axis labels with the patchwork
package, problems occurred (see this question). From the answer of the question, I applied the idea of the example code to my concrete example, in which I also used a fixed aspect ratio for each plot.
Here is the example code
library(ggplot2)
library(patchwork)
# Create different datasets for each plot
df1 <- expand.grid(x = seq(300, 800, length.out = 50), y = seq(300, 600, length.out = 50))
df1$z <- with(df1, dnorm(x, mean = 500, sd = 50) * dnorm(y, mean = 400, sd = 50))
df2 <- expand.grid(x = seq(300, 800, length.out = 50), y = seq(300, 600, length.out = 50))
df2$z <- with(df2, dnorm(x, mean = 600, sd = 50) * dnorm(y, mean = 450, sd = 50))
df3 <- expand.grid(x = seq(300, 800, length.out = 50), y = seq(300, 600, length.out = 50))
df3$z <- with(df3, dnorm(x, mean = 550, sd = 50) * dnorm(y, mean = 500, sd = 50))
df4 <- expand.grid(x = seq(300, 800, length.out = 50), y = seq(300, 600, length.out = 50))
df4$z <- with(df4, dnorm(x, mean = 650, sd = 50) * dnorm(y, mean = 350, sd = 50))
# Compute global min and max for z-values across all datasets
min_z <- min(c(df1$z, df2$z, df3$z, df4$z), na.rm = TRUE)
max_z <- max(c(df1$z, df2$z, df3$z, df4$z), na.rm = TRUE)
# Generate basic ggplot() objects with fixed aspect ratio
p_tmp <- lapply(list(df1, df2, df3, df4), function(df) {
ggplot(df, aes(x, y, fill = z)) +
geom_raster(interpolate = TRUE) +
theme_minimal() +
theme(
aspect.ratio = 1,
legend.position = "bottom",
legend.box = "horizontal"
)
})
plot_aspr <- wrap_plots(
p_tmp,
nrow = 2,
ncol = 2,
axis_titles = "collect",
guides = "collect"
) +
plot_annotation(
title = "Emission-Excitation-Matrix",
subtitle = "Rayleigh Filtered Data") &
labs(
x = "Emission Wavelength / nm",
y = "Excitation Wavelength / nm"
) &
scale_fill_viridis_c(limits = c(min_z, max_z)) &
coord_cartesian(expand = FALSE)
print(plot_aspr)
and the corresponding plot. In this plot, the axis labels are not merged, but the legends are. In addition, the individual efficiencies are distributed here and have the desired square shape by definition.
Without the fixed aspect ratio
# Generate basic ggplot() objects without fixed aspect ratio
p_tmp <- lapply(list(df1, df2, df3, df4), function(df) {
ggplot(df, aes(x, y, fill = z)) +
geom_raster(interpolate = TRUE) +
theme_minimal() +
theme(
legend.position = "bottom",
legend.box = "horizontal"
)
})
plot_noaspr <- wrap_plots(
p_tmp,
nrow = 2,
ncol = 2,
heights = rep(1, 2),
widths = rep(1, 2),
axis_titles = "collect",
guides = "collect"
) +
plot_annotation(
title = "Emission-Excitation-Matrix",
subtitle = "Rayleigh Filtered Data") &
labs(
x = "Emission Wavelength / nm",
y = "Excitation Wavelength / nm"
) &
scale_fill_viridis_c(limits = c(min_z, max_z)) &
coord_cartesian(expand = FALSE)
print(plot_noaspr)
results in the following plot for the same data set:
In this case, both the axis labels and the legends are combined.
One shortcoming here is that the shape of the individual graphs in the overall graph is not automatically perfectly square.
Based on the results, I conclude that axis_title = "collect"
from patchwork
is not compatible with aspect.ratio
, but is compatible with guide = "collect"
. Hence the question of whether this is desired or a bug.
Edit:
After posting this question, I found an interesting question and article regarding this topic. However, the problem was mainly the alignment of the graphs and not the combination of their axis titles.
Share Improve this question edited Mar 25 at 18:38 M-- 29.5k10 gold badges69 silver badges106 bronze badges Recognized by R Language Collective asked Mar 25 at 13:37 ExcelsiorExcelsior 2671 silver badge5 bronze badges2 Answers
Reset to default 4I didn't give it much thought to be able to explain the reason for this, but using unit(rep(1,2), rep("in",2))
instead of rep(1,2)
for widths
/heights
seems to work. I have also used design
instead of nrow
/ncol
to have more control over overall plotting area. Moreover, I had to move theme(...)
to the end of patchwork
code.
p_tmp <- lapply(list(df1, df2, df3, df4), function(df) {
ggplot(df, aes(x, y, fill = z)) +
geom_raster(interpolate = TRUE) +
theme_minimal()
})
wrap_plots(p_tmp,
design = "AAAAABBBBB
AAAAABBBBB
AAAAABBBBB
AAAAABBBBB
AAAAABBBBB
CCCCCDDDDD
CCCCCDDDDD
CCCCCDDDDD
CCCCCDDDDD
CCCCCDDDDD",
widths = unit(rep(1,2), rep("cm",2)),
heights = unit(rep(1,2), rep("cm",2)),
axis_titles = "collect",
guides = "collect") +
plot_annotation(title = "Emission-Excitation-Matrix",
subtitle = "Rayleigh Filtered Data") &
labs(x = "Emission Wavelength / nm",
y = "Excitation Wavelength / nm") &
scale_fill_viridis_c(limits = c(min_z, max_z)) &
coord_cartesian(expand = FALSE) &
theme(legend.position = "bottom",
legend.box = "horizontal")
This gives us the aspect ratio of 1:
As per the dev's comment on this patchwork GitHub ticket
:
there is no way to ensure that plots with fixed aspects are actually occupying the same vertical or horizontal space when resizing the plot so collecting the axes doesn't make sense in general.
This is perhaps why aspect.ratio
overrides axis_titles = "collect"
, alluded to in the Fixed aspect plots section of the Patchwork: Controlling Layouts doc:
It is not possible to simultaneously assign even dimensions and align fixed aspect plots
which, if I'm interpreting this correctly, means patchwork
is forced to 'choose' and aspect.ratio
subsequently overrides any previously defined parameters. However, your desired outcome can be achieved using the patchwork::plot_layout()
function.
As per my answer on your linked question, it's better to keep plot elements in your list of ggplot()
objects to the bare minimum, and instead assign things like titles inside wrap_plots()
.
library(ggplot2)
library(patchwork)
# Generate basic ggplot() objects as a list
p_tmp <- lapply(list(df1, df2, df3, df4), function(df) {
ggplot(df, aes(x, y, fill = z)) +
geom_raster(interpolate = TRUE) +
theme_minimal()
})
wrap_plots(p_tmp,
nrow = 2,
ncol = 2,
axis_titles = "collect",
guides = "collect") +
plot_layout(widths = unit(rep(4,2), rep("cm", 2)),
heights = unit(rep(4,2), rep("cm", 2))) +
plot_annotation(title = "Emission-Excitation-Matrix",
subtitle = "Rayleigh Filtered Data") &
labs(x = "Emission Wavelength / nm",
y = "Excitation Wavelength / nm") &
scale_fill_viridis_c(limits = c(min_z, max_z)) &
coord_cartesian(expand = FALSE) &
theme(legend.position = "bottom",
legend.box = "horizontal")
I checked the x/y plot panel dimensions in an external editor and they are the same for each panel.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744192867a4562516.html
评论列表(0条)