1

我正在尝试使用 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.margintheme我不知道这在拼凑中是可能的,而且我对网格(或 gridExtra)的了解还不够,无法了解如何实现。任何想法或指向一个好的解决方案?

4

0 回答 0