Dan*_*Cee 6 size r legend ggplot2
我想用底部的图例制作一个情节,但图例总是被剪掉......因为它似乎ggplot2
无法自动确定底部图例中的最佳列数,我尝试自己做......没有成功。
假设我有以下mydf
数据框:
mydf <- data.frame(group=paste0('gr',1:10), var=paste('some long text -', LETTERS), value=runif(260, 0, 100))
head(mydf)
# group var value
#1 gr1 some long text - A 7.941256
#2 gr2 some long text - B 50.740651
#3 gr3 some long text - C 89.068872
#4 gr4 some long text - D 77.572413
#5 gr5 some long text - E 9.792349
#6 gr6 some long text - F 35.194944
Run Code Online (Sandbox Code Playgroud)
我希望我的输出图的宽度为 12(英寸)。
当我用 绘制图时ggplot2
,图例的宽度大于图并被剪切:
width_scale <- 12
grDevices::pdf(file='test.pdf', height=10, width=width_scale)
print(#or ggsave()
ggplot2::ggplot(mydf, ggplot2::aes(group, value, fill=var)) +
ggplot2::geom_bar(stat="identity") +
ggplot2::scale_y_continuous("%") +
ggplot2::theme_light() +
ggplot2::theme(legend.text=ggplot2::element_text(size=1.5*width_scale),
legend.title=ggplot2::element_text(size=1.5*width_scale,face="bold"),
legend.position="bottom",
legend.key.size = grid::unit(width_scale/50, "inch"),
legend.key.width = grid::unit(width_scale/50, "inch"))
)
grDevices::dev.off()
Run Code Online (Sandbox Code Playgroud)
它产生这个情节:
由于我的图例由于某种原因被删除,我试图自己确定图例列的最佳数量。我必须即时计算它,因为所有这些都进入一个函数(但对于这种情况,答案应该是 4)。
由于绘图的宽度以英寸为单位,因此我试图对其保持谨慎并计算图例中某个级别的平均大小(以英寸为单位)。然后列数将是绘图宽度除以单个级别的大小,向下取整(减去图例标题将占用的列)。
#find optimal number of legend columns
ceiling_dec <- function(x, level=1) round(x + 5*10^(-level-1), level)
floor_dec <- function(x, level=1) round(x - 5*10^(-level-1), level)
letter_size <- 1.5*width_scale/72.27 #72.27 point in 1 inch
mean_level_size <- mean(nchar(levels(mydf$var))) * letter_size #this is the size in inches of a group level in the legend
mean_level_size <- mean_level_size + (width_scale/50) + (width_scale/50) #plus the size of the level key and some extra space
num_cols <- floor_dec(width_scale/mean_level_size, 0)
cols_to_remove <- ceiling_dec((3*letter_size) / mean_level_size, 0) #number of columns that the legend title (var) would occupy
num_cols <- num_cols - cols_to_remove
if (num_cols<=0){num_cols <- length(levels(mydf$var))}
if (num_cols>length(levels(mydf$var))){num_cols <- length(levels(mydf$var))}
num_rows <- ceiling(length(levels(mydf$var)) / num_cols)
if ((num_rows==1) & (num_cols<length(levels(mydf$var)))){num_cols <- length(levels(mydf$var))}
#
Run Code Online (Sandbox Code Playgroud)
有了这些信息,我将ggplot2
再次使用来制作绘图,将列数传递给guide_legend
.
grDevices::pdf(file='test.pdf', height=10, width=width_scale)
print(#or ggsave()
ggplot2::ggplot(mydf, ggplot2::aes(group, value, fill=var)) +
ggplot2::geom_bar(stat="identity") +
ggplot2::scale_y_continuous("%") +
ggplot2::theme_light() +
ggplot2::theme(legend.text=ggplot2::element_text(size=1.5*width_scale),
legend.title=ggplot2::element_text(size=1.5*width_scale,face="bold"),
legend.position="bottom",
legend.key.size = grid::unit(width_scale/50, "inch"),
legend.key.width = grid::unit(width_scale/50, "inch")) +
ggplot2::guides(fill=ggplot2::guide_legend(ncol=num_cols))
)
grDevices::dev.off()
Run Code Online (Sandbox Code Playgroud)
我以为我几乎拥有它,但结果从来没有成功......看到这个MWE中的代码产生了以下情节......
为什么传奇会被剪成这样?为什么ggplot2
不自动选择最佳列数?
如果我尝试自己确定最佳列数,该怎么做?我在那里做错了什么?
我知道在这种情况下传递给的最佳列数guide_legend
(num_col
那里的块的结果)应该是 4,但我只知道它事后......我需要即时计算这个最佳数字,因为所有这进入一个函数......
谢谢!
这有效:
ggplot2::ggplot(mydf, ggplot2::aes(group, value, fill=var)) +
ggplot2::geom_bar(stat="identity") +
ggplot2::scale_y_continuous("%") +
ggplot2::theme_light() +
ggplot2::theme(legend.text=ggplot2::element_text(size=width_scale),
legend.box.margin = margin(6, 6, 6, 6),
legend.title=ggplot2::element_text(size=1.5*width_scale,face="bold"),
legend.position="bottom",
legend.key.size = grid::unit(width_scale/50, "inch"),
legend.key.width = grid::unit(width_scale/50, "inch"))
Run Code Online (Sandbox Code Playgroud)
您可以根据图例中的元素数量调整 width_scale :
mydf <- data.frame(group=paste0('gr',1:10), var=paste('some long text -', 1:50), value=runif(500, 0, 100))
width_scale <- 12 * 26 / length(unique(mydf$var))
Run Code Online (Sandbox Code Playgroud)