使用长标签名称 ggplot 设置标准图例键大小
Set standard legend key size with long label names ggplot
我正在构建一个 ggplot 可视化,其中一些填充美学具有非常长的变量名称,而其他变量名称很短。添加长名称会更改与长文本对应的图例键的大小 - 将其加长以匹配文本。我想知道是否有一种方法可以标准化所有变量的图例键高度,并更改图例项之间的 spaces。
我尝试修改 theme(legend.key.height())
和 theme(legend.key.width())
但这并没有解决问题。
示例代码如下:
#load neccesary package
library('ggplot2')
#create the dataframe
df <- data.frame(year = as.integer(c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2)),
class = c('A', 'B', 'C', 'D', 'E'),
value = c(50, 50))
#Create plot
g <- ggplot(df, aes(x = year, y = value, fill = class)) +
geom_col(position = 'stack') +
scale_fill_discrete(labels = c('This is an\nextremely\nlong label\nname', 'short label1', 'Another\nlong\nlabel\nname', 'short label3', 'short label4'))
地块:
我想要的是所有变量的键大小相同,键之间的白色 space 会发生变化以适应长文本。所以看起来像这样:
正在尝试g + theme(legend.key.height = unit(3, 'mm'), legend.key.width = unit(3, 'mm'))
没有解决问题。
有什么想法吗?
您可以通过定义自己的 class 个图例来做到这一点。这当然比主题中的简单选项更冗长,了解一些内容会很方便 gtable/grid,但它完成了工作。
library(ggplot2)
library(grid)
#create the dataframe
df <- data.frame(year = as.integer(c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2)),
class = c('A', 'B', 'C', 'D', 'E'),
value = c(50, 50))
labs <- c('This is an\nextremely\nlong label\nname', 'short label1',
'Another\nlong\nlabel\nname', 'short label3', 'short label4')
guide_squarekey <- function(...) {
# Constructor just prepends a different class
x <- guide_legend(...)
class(x) <- c("squarekey", class(x))
x
}
guide_gengrob.squarekey <- function(guide, theme) {
# Make default legend
legend <- NextMethod()
# Find the key grobs
is_key <- startsWith(legend$layout$name, "key-")
is_key <- is_key & !endsWith(legend$layout$name, "-bg")
# Extract the width of the key column
key_col <- unique(legend$layout$l[is_key])
keywidth <- convertUnit(legend$widths[2], "mm", valueOnly = TRUE)
# Set the height of every key to the key width
legend$grobs[is_key] <- lapply(legend$grobs[is_key], function(key) {
key$height <- unit(keywidth - 0.5, "mm") # I think 0.5mm is default offset
key
})
legend
}
ggplot(df, aes(x = year, y = value, fill = class)) +
geom_col(position = 'stack') +
scale_fill_discrete(labels = labs,
guide = "squarekey")
由 reprex package (v0.3.0)
于 2021 年 1 月 20 日创建
编辑:如果您也想编辑按键背景:
guide_gengrob.squarekey <- function(guide, theme) {
legend <- NextMethod()
is_key <- startsWith(legend$layout$name, "key-")
is_key_bg <- is_key & endsWith(legend$layout$name, "-bg")
is_key <- is_key & !endsWith(legend$layout$name, "-bg")
key_col <- unique(legend$layout$l[is_key])
keywidth <- convertUnit(legend$widths[2], "mm", valueOnly = TRUE)
legend$grobs[is_key] <- lapply(legend$grobs[is_key], function(key) {
key$height <- unit(keywidth - 0.5, "mm")
key
})
legend$grobs[is_key_bg] <- lapply(legend$grobs[is_key_bg], function(bg) {
bg$height <- unit(keywidth, "mm")
bg
})
legend
}
制作自定义指南的另一种方法是为图例字形制作自定义绘图函数。相对于 draw_key_polygon()
的变化是宽度和高度设置为 "snpc"
单位而不是 "npc"
单位。
#load neccesary package
library(ggplot2)
library(grid)
library(rlang)
draw_square <- function(data, params, size) {
if (is.null(data$size)) {
data$size <- 0.5
}
lwd <- min(data$size, min(size) /4)
grid::rectGrob(
width = unit(1, "snpc") - unit(lwd, "mm"),
height = unit(1, "snpc") - unit(lwd, "mm"),
gp = gpar(
col = data$colour %||% NA,
fill = alpha(data$fill %||% "grey20", data$alpha),
lty = data$linetype %||% 1,
lwd = lwd * .pt,
linejoin = params$linejoin %||% "mitre",
lineend = if (identical(params$linejoin, "round")) "round" else "square"
)
)
}
#create the dataframe
df <- data.frame(year = as.integer(c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2)),
class = c('A', 'B', 'C', 'D', 'E'),
value = c(50, 50))
#Create plot
g <- ggplot(df, aes(x = year, y = value, fill = class)) +
geom_col(position = 'stack', key_glyph = draw_square) +
scale_fill_discrete(labels = c('This is an\nextremely\nlong label\nname', 'short label1', 'Another\nlong\nlabel\nname', 'short label3', 'short label4'))
g
由 reprex package (v1.0.0)
于 2021-08-19 创建
我正在构建一个 ggplot 可视化,其中一些填充美学具有非常长的变量名称,而其他变量名称很短。添加长名称会更改与长文本对应的图例键的大小 - 将其加长以匹配文本。我想知道是否有一种方法可以标准化所有变量的图例键高度,并更改图例项之间的 spaces。
我尝试修改 theme(legend.key.height())
和 theme(legend.key.width())
但这并没有解决问题。
示例代码如下:
#load neccesary package
library('ggplot2')
#create the dataframe
df <- data.frame(year = as.integer(c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2)),
class = c('A', 'B', 'C', 'D', 'E'),
value = c(50, 50))
#Create plot
g <- ggplot(df, aes(x = year, y = value, fill = class)) +
geom_col(position = 'stack') +
scale_fill_discrete(labels = c('This is an\nextremely\nlong label\nname', 'short label1', 'Another\nlong\nlabel\nname', 'short label3', 'short label4'))
地块:
我想要的是所有变量的键大小相同,键之间的白色 space 会发生变化以适应长文本。所以看起来像这样:
正在尝试g + theme(legend.key.height = unit(3, 'mm'), legend.key.width = unit(3, 'mm'))
没有解决问题。
有什么想法吗?
您可以通过定义自己的 class 个图例来做到这一点。这当然比主题中的简单选项更冗长,了解一些内容会很方便 gtable/grid,但它完成了工作。
library(ggplot2)
library(grid)
#create the dataframe
df <- data.frame(year = as.integer(c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2)),
class = c('A', 'B', 'C', 'D', 'E'),
value = c(50, 50))
labs <- c('This is an\nextremely\nlong label\nname', 'short label1',
'Another\nlong\nlabel\nname', 'short label3', 'short label4')
guide_squarekey <- function(...) {
# Constructor just prepends a different class
x <- guide_legend(...)
class(x) <- c("squarekey", class(x))
x
}
guide_gengrob.squarekey <- function(guide, theme) {
# Make default legend
legend <- NextMethod()
# Find the key grobs
is_key <- startsWith(legend$layout$name, "key-")
is_key <- is_key & !endsWith(legend$layout$name, "-bg")
# Extract the width of the key column
key_col <- unique(legend$layout$l[is_key])
keywidth <- convertUnit(legend$widths[2], "mm", valueOnly = TRUE)
# Set the height of every key to the key width
legend$grobs[is_key] <- lapply(legend$grobs[is_key], function(key) {
key$height <- unit(keywidth - 0.5, "mm") # I think 0.5mm is default offset
key
})
legend
}
ggplot(df, aes(x = year, y = value, fill = class)) +
geom_col(position = 'stack') +
scale_fill_discrete(labels = labs,
guide = "squarekey")
由 reprex package (v0.3.0)
于 2021 年 1 月 20 日创建编辑:如果您也想编辑按键背景:
guide_gengrob.squarekey <- function(guide, theme) {
legend <- NextMethod()
is_key <- startsWith(legend$layout$name, "key-")
is_key_bg <- is_key & endsWith(legend$layout$name, "-bg")
is_key <- is_key & !endsWith(legend$layout$name, "-bg")
key_col <- unique(legend$layout$l[is_key])
keywidth <- convertUnit(legend$widths[2], "mm", valueOnly = TRUE)
legend$grobs[is_key] <- lapply(legend$grobs[is_key], function(key) {
key$height <- unit(keywidth - 0.5, "mm")
key
})
legend$grobs[is_key_bg] <- lapply(legend$grobs[is_key_bg], function(bg) {
bg$height <- unit(keywidth, "mm")
bg
})
legend
}
制作自定义指南的另一种方法是为图例字形制作自定义绘图函数。相对于 draw_key_polygon()
的变化是宽度和高度设置为 "snpc"
单位而不是 "npc"
单位。
#load neccesary package
library(ggplot2)
library(grid)
library(rlang)
draw_square <- function(data, params, size) {
if (is.null(data$size)) {
data$size <- 0.5
}
lwd <- min(data$size, min(size) /4)
grid::rectGrob(
width = unit(1, "snpc") - unit(lwd, "mm"),
height = unit(1, "snpc") - unit(lwd, "mm"),
gp = gpar(
col = data$colour %||% NA,
fill = alpha(data$fill %||% "grey20", data$alpha),
lty = data$linetype %||% 1,
lwd = lwd * .pt,
linejoin = params$linejoin %||% "mitre",
lineend = if (identical(params$linejoin, "round")) "round" else "square"
)
)
}
#create the dataframe
df <- data.frame(year = as.integer(c(1, 1, 1, 1, 1, 2, 2, 2, 2, 2)),
class = c('A', 'B', 'C', 'D', 'E'),
value = c(50, 50))
#Create plot
g <- ggplot(df, aes(x = year, y = value, fill = class)) +
geom_col(position = 'stack', key_glyph = draw_square) +
scale_fill_discrete(labels = c('This is an\nextremely\nlong label\nname', 'short label1', 'Another\nlong\nlabel\nname', 'short label3', 'short label4'))
g
由 reprex package (v1.0.0)
于 2021-08-19 创建