在 ggpairs 中加入独立图例(取 2)
incorporate standalone legend in ggpairs (take 2)
tl;dr 无法在 ggpairs
中获得一个独立的图例(描述整个情节的常见颜色)令我满意。
抱歉篇幅过长。
我正在尝试使用 GGally::ggpairs
(用于使用 ggplot2
绘制各种绘图矩阵的扩展包)绘制(下三角)对图。这与 How to add an external legend to ggpairs()? 本质上是同一个问题,但我对这个问题的答案在美学上不满意,所以我将其作为扩展发布(如果评论者 suggested/recommended,我将删除它问题并为该问题提供赏金)。特别是,我希望图例出现在子图框架 外部 中,或者将其放在一个虚拟子图中但允许额外的宽度来容纳它,或者(理想情况下)将它放在一个单独的(空的)子图。如下所示,我的两个部分解决方案都有问题。
虚假数据:
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 top/right 列的函数:
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)
问题:
- 图例后面的空白面板实际上掩盖了一些点;我不知道为什么它不像往常一样不在面板之外,我认为那是
ggpairs
正在做的事情
- 如果它在面板之外(在顶部或右侧),我想确保留下一些额外的 space 以便面板本身都是相同的大小。但是,
ggmatrix
/ggpairs
看起来很不灵活。
到目前为止,我能够尝试的唯一替代方法是按照 ggplot separate legend and plot 提取图例并使用 gridExtra::grid.arrange()
:
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)
问题:
- 被
ggpairs
抑制的轴和标签回来了...
我还考虑过创建一个面板,其中包含仅包含图例的特殊图(即尝试使用 theme(SOMETHING=element.blank)
来抑制图本身,但不知道该怎么做。
作为最后的手段,我可以 trim 我自己在适当的地方设置坐标轴,但这实际上是在重新发明 ggpairs
最初所做的事情 ...
对解决方案 1 稍作修改:首先,绘制没有图例的图矩阵(但仍带有颜色映射)。其次,使用 trim_gg
函数删除对角线 space。第三,对于左上角的绘图,绘制其图例,但将其放置在右侧的空白 space 中。
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
tl;dr 无法在 ggpairs
中获得一个独立的图例(描述整个情节的常见颜色)令我满意。
抱歉篇幅过长。
我正在尝试使用 GGally::ggpairs
(用于使用 ggplot2
绘制各种绘图矩阵的扩展包)绘制(下三角)对图。这与 How to add an external legend to ggpairs()? 本质上是同一个问题,但我对这个问题的答案在美学上不满意,所以我将其作为扩展发布(如果评论者 suggested/recommended,我将删除它问题并为该问题提供赏金)。特别是,我希望图例出现在子图框架 外部 中,或者将其放在一个虚拟子图中但允许额外的宽度来容纳它,或者(理想情况下)将它放在一个单独的(空的)子图。如下所示,我的两个部分解决方案都有问题。
虚假数据:
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 top/right 列的函数:
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)
问题:
- 图例后面的空白面板实际上掩盖了一些点;我不知道为什么它不像往常一样不在面板之外,我认为那是
ggpairs
正在做的事情 - 如果它在面板之外(在顶部或右侧),我想确保留下一些额外的 space 以便面板本身都是相同的大小。但是,
ggmatrix
/ggpairs
看起来很不灵活。
到目前为止,我能够尝试的唯一替代方法是按照 ggplot separate legend and plot 提取图例并使用 gridExtra::grid.arrange()
:
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)
问题:
- 被
ggpairs
抑制的轴和标签回来了...
我还考虑过创建一个面板,其中包含仅包含图例的特殊图(即尝试使用 theme(SOMETHING=element.blank)
来抑制图本身,但不知道该怎么做。
作为最后的手段,我可以 trim 我自己在适当的地方设置坐标轴,但这实际上是在重新发明 ggpairs
最初所做的事情 ...
对解决方案 1 稍作修改:首先,绘制没有图例的图矩阵(但仍带有颜色映射)。其次,使用 trim_gg
函数删除对角线 space。第三,对于左上角的绘图,绘制其图例,但将其放置在右侧的空白 space 中。
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