我正在尝试使用 ggplot2 和拼凑创建散点图矩阵。
我的功能是
library(tidyverse)
library(patchwork)
library(grid)
ggscatter <- function(df, ...) {
plots <- df %>%
mutate(
across(.fns = as.character),
.id = 1:n(),
) %>%
pivot_longer(-.id, names_to = ".var", values_to = ".val") %>%
full_join(., ., by = ".id") %>%
nest(data = -c(.var.x, .var.y)) %>%
mutate(
data = pmap(., function(data, .var.x, .var.y) {
data %>%
mutate(
.val.x = switch(class(df[[.var.x]]),
"factor" = factor(.val.x),
"numeric" = as.numeric(.val.x),
"character" = .val.x
),
.val.y = switch(class(df[[.var.y]]),
"factor" = factor(.val.y),
"numeric" = as.numeric(.val.y),
"character" = .val.y
)
)
})
) %>%
mutate(
plot = pmap(., function(data, .var.x, .var.y) {
if(.var.x == .var.y) {
p <- grid::textGrob(.var.x, gp = gpar(fontsize = 15))
} else {
p <- data %>%
ggplot(aes(x = .val.x, y = .val.y)) +
geom_point(
position = position_jitter(
width = {if(class(data$.val.x) == "factor") .2 else 0},
height = {if(class(data$.val.y) == "factor") .2 else 0}
)
) +
labs(
x = .var.x,
y = .var.y
) +
theme(
axis.title = element_blank(),
axis.text.x = {if(.var.y == names(df)[length(df)] || (.var.x == names(df)[length(df)] & .var.y == names(df)[length(df) -1])) element_text() else element_blank()},
axis.text.y = {if(.var.x == names(df)[1] || (.var.y == names(df)[1] & .var.x == names(df)[2])) element_text() else element_blank()},
axis.ticks.x = {if(.var.y == names(df)[length(df)] || (.var.x == names(df)[length(df)] & .var.y == names(df)[length(df) -1])) element_line() else element_blank()},
axis.ticks.y = {if(.var.x == names(df)[1] || (.var.y == names(df)[1] & .var.x == names(df)[2])) element_line() else element_blank()},
plot.margin = margin(0, 0, 0, 0)
)
}
p
})
)
wrap_plots(plots$plot,
guides = "collect",
byrow = FALSE
)
}
ggscatter(iris)
由于 x 轴和 y 轴标签,这很好用……除了第 1 列和第 2 列以及倒数第 2 行和最后一行之间的间距。显然,因为对角线是 textGrobs,所以“简单”的解决方案是忽略标签为定位图而占用的空间(因为溢出到该区域应该是可以的)。更改没有帮助 - 它看起来超出了轴文本使用的空间plot.margin
。theme
我不知道这在拼凑中是可能的,而且我对网格(或 gridExtra)的了解还不够,无法了解如何实现。任何想法或指向一个好的解决方案?