在ggpairs中加入独立的传奇(取2)

时间:2016-05-10 01:07:07

标签: r ggplot2 ggally

tl; dr 无法让ggpairs中的独立图例(描述整个图表中的常见颜色)令我满意。

抱歉长度。

我正在尝试使用GGally::ggpairs(一个用ggplot2绘制各种绘图矩阵的扩展包)绘制(下三角)对图。这与How to add an external legend to ggpairs()?基本上是同一个问题,但我对这个问题的答案不满意,所以我将其作为一个扩展名发布(如果评论者建议/推荐,我会删除这个问题,代替那个问题提供赏金)。特别是,我希望图例在子图框外显示,或者将其放在一个虚拟子图中,但允许额外的宽度来保持它,或者(理想情况下)将它放在一个单独的图中(空)子图。如下所示,我的部分解决方案都有问题。

虚假数据:

set.seed(101)
dd <- data.frame(x=rnorm(100),
                 y=rnorm(100),
                 z=rnorm(100),
                 f=sample(c("a","b"),size=100,replace=TRUE))
library(GGally)

基本情节功能:

ggfun <- function(...) {
   ggpairs(dd,mapping = ggplot2::aes(color = f),
    columns=1:3,
    lower=list(continuous="points"),
    diag=list(continuous="blankDiag"),
    upper=list(continuous="blank"),
    ...)
}

修剪顶部/右侧列的功能:

trim_gg <- function(gg) {
    n <- gg$nrow
    gg$nrow <- gg$ncol <- n-1
    v <- 1:n^2
    gg$plots <- gg$plots[v>n & v%%n!=0]
    gg$xAxisLabels <- gg$xAxisLabels[-n]
    gg$yAxisLabels <- gg$yAxisLabels[-1]
    return(gg)
}

gg0 <- trim_gg(ggfun(legends=TRUE))

删除左列中的图例(如上面的链接问题所示):

library(ggplot2)  ## for theme()
for (i in 1:2) {
   inner <- getPlot(gg0,i,1)
   inner <- inner + theme(legend.position="none")
   gg0 <- putPlot(gg0,inner,i,1)
}
inner <- getPlot(gg0,2,2)
inner <- inner + theme(legend.position="right")
gg0 <- putPlot(gg0,inner,2,2)

enter image description here

问题

  • 传说背后的空白面板实际上掩盖了一些点;我不知道为什么它不像往常一样在小组之外,我认为ggpairs正在做的事情
  • 如果它在面板外面(在顶部或右边),我想确保留出一些额外的空间,这样面板本身的尺寸都相同。但是,ggmatrix / ggpairs看起来非常不灵活。

我能够尝试远的唯一选择是通过提取图例并使用gridExtra::grid.arrange()跟踪ggplot separate legend and plot

g_legend <- function(a.gplot){
   tmp <- ggplot_gtable(ggplot_build(a.gplot))
   leg <- which(sapply(tmp$grobs, function(x) x$name) == "guide-box")
   legend <- tmp$grobs[[leg]]
   return(legend)
}

library(gridExtra)
grid.arrange(getPlot(gg0,1,1),
             g_legend(getPlot(gg0,2,2)),
             getPlot(gg0,2,1),
             getPlot(gg0,2,2)+theme(legend.position="none"),
   nrow=2)

enter image description here

问题

  • ggpairs压制的轴和标签又回来了......

我还考虑过创建一个带有特殊情节的面板,该面板仅包含图例(即尝试使用theme(SOMETHING=element.blank)来抑制情节本身,但无法弄清楚如何去做。

作为最后的手段,我可​​以在适当的时候修剪轴,但这实际上是重新发明了ggpairs首先做的事情......

1 个答案:

答案 0 :(得分:2)

对解决方案1稍作修改:首先,绘制没有图例的图表矩阵(但仍然使用颜色映射)。其次,使用trim_gg函数删除对角线空格。第三,对于左上角位置的情节,绘制其图例但将其置于右侧的空白区域。

data(state)
dd <- data.frame(state.x77,
             State = state.name,
             Abbrev = state.abb,
             Region = state.region,
             Division = state.division) 

columns <- c(3, 5, 6, 7)
colour <- "Region"

library(GGally)
library(ggplot2)  ## for theme()

# Base plot
ggfun <- function(data = NULL, columns = NULL, colour = NULL, legends = FALSE) {
   ggpairs(data, 
     columns = columns,
     mapping = ggplot2::aes_string(colour = colour),
     lower = list(continuous = "points"),
     diag = list(continuous = "blankDiag"),
     upper = list(continuous = "blank"),
    legends = legends)
}

# Remove the diagonal elements
trim_gg <- function(gg) {
    n <- gg$nrow
    gg$nrow <- gg$ncol <- n-1
    v <- 1:n^2
    gg$plots <- gg$plots[v > n & v%%n != 0]
    gg$xAxisLabels <- gg$xAxisLabels[-n]
    gg$yAxisLabels <- gg$yAxisLabels[-1]
    return(gg)
}

# Get the plot
gg0 <- trim_gg(ggfun(dd, columns, colour))

# For plot in position (1,1), draw its legend in the empty panels to the right
inner <- getPlot(gg0, 1, 1)

inner <- inner + 
   theme(legend.position = c(1.01, 0.5), 
         legend.direction = "horizontal",
         legend.justification = "left") +
   guides(colour = guide_legend(title.position = "top"))  

gg0 <- putPlot(gg0, inner, 1, 1)
gg0

enter image description here