使用ggplot、gtable和cowplot固定图例框的宽度

2023-12-23

我想用 R 制作一个绘图,看起来像用 Mac 的 Numbers 制作的示例。我正在努力处理情节和图例框之间的空间。这是我想要实现的目标的示例:

在一些用户的帮助下(请参阅帖子末尾以供参考),我已经非常接近了。这是我当前的功能:

library(tidyverse)
library(cowplot)
library(gtable)
library(grid)
library(patchwork)


custom_barplot <- function(dataset, x_value, y_value, fill_value, nfill, xlab, ylab, y_limit, y_steps,legend_labels) {
# Example color set to choose from
colors=c("#CF232B","#942192","#000000","#f1eef6","#addd8e","#d0d1e6","#31a354","#a6bddb")

# user function for adjusting the size of key-polygons in legend
draw_key_polygon2 <- function(data, params, size) {
  lwd <- min(data$size, min(size) / 4)
  
  grid::rectGrob(
    width = grid::unit(0.8, "npc"),
    height = grid::unit(0.8, "npc"),
    gp = grid::gpar(
      col = data$colour,
      fill = alpha(data$fill, data$alpha),
      lty = data$linetype,
      lwd = lwd * .pt,
      linejoin = "mitre"
    ))
}
# user function for the plot itself
plot <- function(dataset, x_value, y_value, fill_value, nfill, xlab, ylab, y_limit, y_steps,legend,legend_labels) 
{ggplot(data=dataset, mapping=aes(x={{x_value}}, y={{y_value}}, fill={{fill_value}})) +
    geom_col(position=position_dodge(width=0.85),width=0.8,key_glyph="polygon2",show.legend=legend) + 
    geom_smooth(aes(color={{fill_value}}),method="lm",formula=y~x, se=FALSE,show.legend=legend, linetype="dashed") +
    labs(x=xlab,y=ylab) +
    theme(text=element_text(size=9,color="black"),
          panel.background = element_rect(fill="white"),
          panel.grid = element_line(color = "black",linetype="solid",size= 0.3),
          panel.grid.minor = element_blank(),
          panel.grid.major.x=element_blank(),
          axis.text=element_text(size=9),
          axis.line.x=element_line(color="black"),
          axis.ticks= element_blank(),
          legend.text=element_text(size=9),
          legend.position = "right",
          legend.justification = "top",
          legend.title = element_blank(),
          legend.key.size = unit(4,"mm"),
          legend.key = element_rect(fill="white"),
          plot.margin=unit(c(1,0.25,0.5,0.5),"cm")) +
    scale_y_continuous(breaks= seq(from=0, to=y_limit,by=y_steps),
                       limits=c(0,y_limit+1), 
                       expand=c(0,0)) +
    scale_x_continuous(breaks=min(data[,deparse(ensym(x_value))],na.rm=TRUE):max(data[,deparse(ensym(x_value))],na.rm=TRUE)) +
    scale_fill_manual(values = colors[1:nfill],labels={{legend_labels}})+
    scale_color_manual(values= colors[1:nfill],labels=paste("Trend ",{{legend_labels}},sep=""))+
    guides(color=guide_legend(override.aes=list(fill=NA),order=2),fill=guide_legend(override.aes = list(linetype=0),order=1))}

# taking the legend of the plot and removing the first column of the gtable within the legend
p_legend <- #cowplot::get_legend(plot(dataset, {{x_value}}, {{y_value}}, {{fill_value}}, nfill, xlab, ylab, y_limit, y_steps,legend=TRUE))
  gtable_squash_cols(cowplot::get_legend(plot(dataset, {{x_value}}, {{y_value}}, {{fill_value}},nfill, xlab, ylab, y_limit, y_steps,legend=TRUE,legend_labels)),1)

# printing the plot without legend
p_main <- plot(dataset, {{x_value}}, {{y_value}}, {{fill_value}}, nfill, xlab, ylab, y_limit, y_steps,legend=FALSE,legend_labels = NULL)

#joining it all together
Obj<- p_main+plot_spacer() + p_legend +
  plot_layout(widths=c(12.5,1.5,4))

return(Obj)

}

我的问题是,图例框的宽度似乎会根据标签的大小进行调整,因此绘图和图例之间的距离不会保持不变。

示例数据:

set.seed(9)
data <- data.frame(Cat=c(rep("A",times=5),rep("B",times=5),rep("C", times=5)),
                   year=rep(c(2015,2016,2017,2018,2019),times=3),
                   count=c(sample(seq(60,80),replace=TRUE,size=5),sample(seq(100,140),replace=TRUE,size=5),sample(seq(20,30),replace=TRUE,size=5)))

我制作了四个图,其中只有标签不同:

plt <- custom_barplot(dataset=data %>% filter(year %in% c(2015,2016,2017)), 
     x_value=year,
     y_value=count, 
     fill_value=Cat, 
     nfill=3, 
     xlab="Year",
     ylab="Count",
     y_limit=140, 
     y_steps=20,
     legend_labels=c("A","B","C"))


plt_2 <- custom_barplot(dataset=data %>% filter(year %in% c(2015,2016,2017)), 
                        x_value=year,
                        y_value=count, 
                        fill_value=Cat, 
                        nfill=3, 
                        xlab="Year",
                        ylab="Count",
                        y_limit=140, 
                        y_steps=20,
                        legend_labels=c("Long Label A","Long Label B","Long Label C"))

plt_3 <- custom_barplot(dataset=data %>% filter(year %in% c(2015,2016,2017)), 
                        x_value=year,
                        y_value=count, 
                        fill_value=Cat, 
                        nfill=3, 
                        xlab="Year",
                        ylab="Count",
                        y_limit=140, 
                        y_steps=20,
                        legend_labels=c("Xtra Long Label A","Xtra Long Label B","Xtra Long Label C"))

plt_4 <- custom_barplot(dataset=data %>% filter(year %in% c(2015,2016,2017)), 
                        x_value=year,
                        y_value=count, 
                        fill_value=Cat, 
                        nfill=3, 
                        xlab="Year",
                        ylab="Count",
                        y_limit=140, 
                        y_steps=20,
                        legend_labels=c("Super Xtra Long Label A","Super Xtra Long Label B","Super Xtra Long Label C"))

The resulting plots look like this: enter image description here enter image description here enter image description here enter image description here

我需要情节和图例之间的空间保持不变,不管图例中标签的长度。我宁愿不完全显示该标签(所以我认为我必须缩短它)。这些图表用于文档中簇绒讲义风格图例应与注释位于同一区域。

您知道如何保持空间恒定吗?

参考:

  • 基本方法通过tjebo https://stackoverflow.com/a/66925859/14027466在这个post https://stackoverflow.com/q/66918748/14027466
  • 情节和图例之间的空间的一般调整stefan https://stackoverflow.com/a/67029094/14027466在这个post https://stackoverflow.com/q/67026849/14027466

我认为最简单的解决方案是简单地对图例中的文本进行换行。您可以使用以下方法执行此操作stringr::str_wrap()给出如下结果:

这是对函数的一个非常小的编辑,它允许用户控制文本换行:


custom_barplot <- function(dataset, x_value, y_value, fill_value, nfill, xlab, ylab, y_limit, y_steps, legend_labels, wrap_labels = 20) {
  # Example color set to choose from
  colors <- c("#CF232B", "#942192", "#000000", "#f1eef6", "#addd8e", "#d0d1e6", "#31a354", "#a6bddb")

  # user function for adjusting the size of key-polygons in legend
  draw_key_polygon2 <- function(data, params, size) {
    lwd <- min(data$size, min(size) / 4)

    grid::rectGrob(
      width = grid::unit(0.8, "npc"),
      height = grid::unit(0.8, "npc"),
      gp = grid::gpar(
        col = data$colour,
        fill = alpha(data$fill, data$alpha),
        lty = data$linetype,
        lwd = lwd * .pt,
        linejoin = "mitre"
      )
    )
  }
  # user function for the plot itself
  plot <- function(dataset, x_value, y_value, fill_value, nfill, xlab, ylab, y_limit, y_steps, legend, legend_labels) {
    ggplot(data = dataset, mapping = aes(x = {{ x_value }}, y = {{ y_value }}, fill = {{ fill_value }})) +
      geom_col(position = position_dodge(width = 0.85), width = 0.8, key_glyph = "polygon2", show.legend = legend) +
      geom_smooth(aes(color = {{ fill_value }}), method = "lm", formula = y ~ x, se = FALSE, show.legend = legend, linetype = "dashed") +
      labs(x = xlab, y = ylab) +
      theme(
        text = element_text(size = 9, color = "black"),
        panel.background = element_rect(fill = "white"),
        panel.grid = element_line(color = "black", linetype = "solid", size = 0.3),
        panel.grid.minor = element_blank(),
        panel.grid.major.x = element_blank(),
        axis.text = element_text(size = 9),
        axis.line.x = element_line(color = "black"),
        axis.ticks = element_blank(),
        legend.text = element_text(size = 9),
        legend.position = "right",
        legend.justification = "top",
        legend.title = element_blank(),
        legend.key.size = unit(4, "mm"),
        legend.key = element_rect(fill = "white"),
        plot.margin = unit(c(1, 0.25, 0.5, 0.5), "cm")
      ) +
      scale_y_continuous(
        breaks = seq(from = 0, to = y_limit, by = y_steps),
        limits = c(0, y_limit + 1),
        expand = c(0, 0)
      ) +
      scale_x_continuous(breaks = min(data[, deparse(ensym(x_value))], na.rm = TRUE):max(data[, deparse(ensym(x_value))], na.rm = TRUE)) +
      scale_fill_manual(values = colors[1:nfill], labels = stringr::str_wrap({{ legend_labels }}, wrap_labels)) +
      scale_color_manual(values = colors[1:nfill], labels = stringr::str_wrap(paste("Trend ", {{ legend_labels }}, sep = ""), wrap_labels)) +
      guides(color = guide_legend(override.aes = list(fill = NA), order = 2), fill = guide_legend(override.aes = list(linetype = 0), order = 1))
  }

  # taking the legend of the plot and removing the first column of the gtable within the legend
  p_legend <- # cowplot::get_legend(plot(dataset, {{x_value}}, {{y_value}}, {{fill_value}}, nfill, xlab, ylab, y_limit, y_steps,legend=TRUE))
    gtable_squash_cols(cowplot::get_legend(plot(dataset, {{ x_value }}, {{ y_value }}, {{ fill_value }}, nfill, xlab, ylab, y_limit, y_steps, legend = TRUE, legend_labels)), 1)

  # printing the plot without legend
  p_main <- plot(dataset, {{ x_value }}, {{ y_value }}, {{ fill_value }}, nfill, xlab, ylab, y_limit, y_steps, legend = FALSE, legend_labels = NULL)

  # joining it all together
  Obj <- p_main + plot_spacer() + p_legend +
    plot_layout(widths = c(12.5, 1.5, 4))

  return(Obj)
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用ggplot、gtable和cowplot固定图例框的宽度 的相关文章

  • 如何使用 R 计算成为列表中中位数的概率?

    假设我有以下数据集 其中显示了假设实验的每个状态的三个观察结果的列表 state lt c Iowa Minnesota Illinois outcome lt list c 5 11 11 c 3 12 8 c 9 14 2 dat lt
  • 选择 R 中的数据表中隐藏时(在绿色加号下方)列的显示顺序

    Context 使用 DataTables 库制作交互式表格时 当屏幕宽度对于列的数量和宽度来说太窄时 列将隐藏在绿色 号下 我有一个非常宽的表格 有 20 多列 其中一些内容非常冗长 因此某些列在所有屏幕宽度下总是隐藏的 每次隐藏新列时
  • R 中的快速 QR 分解

    我有大量矩阵 需要对其执行 QR 分解并存储生成的 Q 矩阵 进行归一化 以便 R 矩阵在其对角线上具有正数 除了使用之外还有其他方法吗qr 功能 这是工作示例 system time Parameters for the matrix t
  • Dendextend:关于如何根据定义的组为树状图的标签着色

    我正在尝试使用一个名为 dendextend 的很棒的 R 包来绘制树状图并根据一组先前定义的组为其分支和标签着色 我已阅读您在 Stack Overflow 中的答案以及 dendextend vignette 的常见问题解答 但我仍然不
  • 使用 R 选择第一个非 NA 值

    df lt data frame ID c 1 1 1 2 3 3 3 test c NA 5 5 6 4 NA 7 3 NA 10 9 我想创建一个名为 value 的变量 它是每个单独 ID 测试的第一个非 NA 值 对于只有NA的个体
  • 只读取选定的列

    谁能告诉我如何仅读取下面每年数据的前 6 个月 7 列 例如使用read table Year Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec 2009 41 27 25 31 31 39 2
  • 使用 Shiny 发布平行坐标图表时出现“错误:路径[1]="”:没有这样的文件或目录”

    我有一个似乎很常见但我还没有找到解决方案的问题 当尝试使用 rCharts Parcoords 发布 Web 应用程序时 出现以下错误 错误 路径 1 没有这样的文件或目录 奇怪的是 该应用程序在我的笔记本电脑上运行得很好 下面是我正在使用
  • 在 r 中的 group_by 之后建模后取消列表列的嵌套

    我想对所有组进行线性回归group by 将模型系数保存在列表列中 然后使用 unnest 扩展列表列 这里我用的是mtcars以数据集为例 注 我想用do here becausebroom tidy 不适用于所有型号 mtcars gt
  • 如何从 R 中的 txt 文件读取矩阵?

    我有一个带有矩阵的txt文件 Matrix txt 重要 数字之间没有空格 0100 1001 1100 我想在 R 中将其作为矩阵读取 我该怎么做 我尝试使用 as matrix read table Matrix txt sep 但失败
  • ggplot2:如何标记事件发生的日期

    我想从第二个情节中获取第一个情节的信息 第二张图表示事件发生的天数 它看起来更宽 因为它没有图例 但它是相同的时间尺度 我选择在第一个图中手动分配颜色 I would like to overlay the second plot dots
  • R:如何获取该月的周数

    我是 R 新手 我想要该日期所属月份的周数 通过使用以下代码 gt CurrentDate lt Sys Date gt Week Number lt format CurrentDate format U gt Week Number 3
  • 投资决策:R中的NPV、IRR、PB计算

    我正在尝试计算不同数量项目的净现值 NPV 内部收益率 IRR 和投资回收期 PB 时间 以评估哪个投资项目提供最佳回报 到目前为止 我可以为每个项目单独计算几行代码 但我想做的是 编写一个函数 它接受一个包含许多不同项目及其现金流的矩阵
  • python 相当于 R 中的 get() (= 使用字符串检索符号的值)

    在 R 中 get s 函数检索名称存储在字符变量 向量 中的符号的值s e g X lt 10 r lt XVI s lt substr r 1 1 X get s 10 取罗马数字的第一个符号r并将其转换为其等效整数 尽管花了一些时间翻
  • 如何在将两根柱子保持在一起的同时熔化柱子?

    我有这种宽格式的数据 我想将其转换为长格式 Cond Construct Line Plant Tube shoot weight shoot Tube root weight root 1 Standard NA NA 2 199 95
  • 条件字体颜色 R Markdown

    我无法找到一种方法来根据变量的值 gt 0 0 或 r setup include FALSE x lt 4 This is an R Markdown document r if x gt 0 textcolor red Markdown
  • 任意列中包含字符串的子集行

    我有一个如下所示的数据集 Col1 Col2 Col3 abckel NA 7 jdmelw njabc NA 8 jdken jdne 如何对数据集进行子集化 使其仅保留包含字符串 abc 的行 最终预期输出 Col1 Col2 Col3
  • 如何使用 tidymodels 和工作流集在同一数据集上拟合多个不同的线性模型

    我想评估同一数据集上多个 主要是 线性回归模型的性能 我想也许使用tidymodels包连同workflowsets workflow set 可能会起作用 我按照这个例子here https workflowsets tidymodels
  • 无法更改 RStudio 中的 R 版本

    我的 RStudio V 0 99 491 无法更改 R 版本 我以平常的方式行事Global Options gt R Version 然后它挂起并且不再工作或反应 R 运行良好的初始版本是R 3 1 0 我以前从未遇到过这样的问题 也许
  • 如何将plot中的单变量列表图表转换为ggplot2格式?

    我正在搜索 但仍然找不到一个非常简单的问题的答案 我们如何使用 R 中的 ggplot2 生成一个变量的简单线图 我正在分析时间序列数据 并且想要对图表进行更复杂的操作 我认为如果我使用 ggplot2 代替会更好plot It works
  • 如何使用 dplyr 独立过滤每列的行

    我有以下内容 library tidyverse df lt tibble tribble gene colB colC a 1 2 b 2 3 c 3 4 d 1 1 df gt A tibble 4 x 3 gt gene colB c

随机推荐

  • Rails 路由(root :to => ...)

    我知道如何将 Rails 应用程序的路由根设置为控制器和操作 但是如何添加id呢 pages show 1应该是根 我该如何设置这个 遇到了同样的问题 这对我有用 root to gt pages show id gt 1
  • 在谷歌colab中加载图像

    我的 Jupyter Notebook 有以下代码可将图像上传到 Colab from google colab import files uploaded files upload 系统提示我输入该文件 哪个被上传 我使用以下命令验证文件
  • 如何在 Next.js 中为非默认语言环境生成动态路径?

    我正在使用 next i18next 构建一个具有国际化功能的 Next js 应用程序 为我网站的所有页面生成英语和法语页面 但具有动态路由的页面除外 即 blog id blog title 对于具有动态路由的页面 会生成英语页面 但不
  • 将 url 扩展添加到 Laravel 路由

    是否可以像这样向 laravel 路由添加扩展 http www mywebsite com members login html 和另一个具有不同扩展名的页面 http www mywebsite com contactus htm 我正
  • 如何将自定义工具链添加到 eclipse CDT

    我有一个基于 gnu arm 的自定义工具链 我已经下载了带 CDT 的 eclipse IDE 我想知道如何使用 eclipse 添加我的工具链 它有一个通用工具链 即Linux GCC 除此之外就没有什么了 我想添加我的 我没有找到任何
  • 如何生成所有 Tetromino 的列表?

    如何生成所有 Tetromino 的列表 或者 更一般地说 如何生成仅限于多个单元格的多联骨牌子集 有很多方法可以做到这一点 我发现效果很好的一种选择是递归地 更普遍地思考它 尤其 单个矩形是 1 多米诺骨牌 对于任何 n 型骨牌 您可以通
  • Java FX 模块化应用程序,未找到模块(Java 11、Intellij)

    您好 我的模块化 Java FX 应用程序有问题 首先 我使用 Intellij 向导创建了一个 JavaFX 项目 我添加了 Java FX 库 JavaFX 模块得到了认可 我的模块信息 java 我还添加了虚拟机选项 但我总是收到此错
  • Xcode:需要将游戏锁定为仅纵向

    我刚刚向应用商店发布了一款游戏 然后意识到我完全忘记将其仅锁定为纵向 我需要提交一个可以做到这一点的更新版本 此时 只需转到 常规 gt 部署信息 并取消选中除 肖像 之外的所有内容 然后将其作为新版本提交就足够了吗 或者我还需要对代码做一
  • 帮助 PHP call_user_func 并将函数集成到类中?

    下面是我大约一年前发现的一个函数 它应该对内存缓存键加锁 这样您就可以更新它的值 而不会出现 2 个请求同时尝试更新键的麻烦 这是非常基本的 但我需要一些帮助来弄清楚如何 100 使用它 我不确定的部分是它在哪里传递 update函数然后传
  • 解码 Angular 6 中的 html 实体

    我正在寻找一个可以在 Angular 6 中解码 HTML 实体的库 我试图找到一些东西 我在 Angular 2 中找到了一个名为 trustashtml 的函数 但我认为 6 版本不可用 下面你可以在 html 模板中找到我的代码 di
  • 使用静态构建curl链接项目

    我正在使用 CMake 和 MinGW32 在 C 中做一个小项目 它需要 libcurl 库 但是当我尝试链接静态构建 libcurl a 时 出现未定义的引用错误 undefined reference to imp curl easy
  • Kendo UI 网格在初始读取时不显示微调器/加载图标

    我已经设置了 kendo ui 网格来从返回 JSON 的 MVC 操作中读取数据 由于成本原因 我使用的是 Kendo 的免费版本 而不是特定的 MVC 问题是 当页面加载并进行网格的初始填充时 它不会显示加载微调器 填充网格后 我转到另
  • 如何在sequelize连接对象中设置应用程序名称?

    Summary 我想改变application name of the connection string当初始化一个新的sequelize对象时 基于这个计算器问题 https stackoverflow com questions 40
  • 在 Ruby on Rails 中将表单路由到新的控制器操作

    我对 Ruby on Rails 比较陌生 并且正在尝试在现有控制器上设置一个具有新操作的表单 我现有的模型和控制器称为 项目 我在控制器中创建了一个名为 队列 的新操作 目标是用户可以使用 queue username 过滤不同用户的项目
  • 测试 .NET 应用程序中的内存泄漏

    是否有任何好的 且免费 工具可以分析静态源或运行程序来帮助检测内存泄漏 我已经构建了一些 Windows 服务 并希望确保如果我让它们连续运行数周 它们不会消耗内存 不符合你对免费的要求 但 Red Gate 的一个我认为值得推荐 ANTS
  • 在构造函数中使用重写方法的替代方案,Java

    在我正在编码的 Java 项目中 我最终使用了在构造函数中重写的方法 就像是 class SuperClass SuperClass intialise protected void initialise Do some stuff com
  • 实时显示 mathjax 输出

    如何修改这个 mathjax 示例以在打字时进行实时预览 现在它只在我按下回车键后才显示结果 我想调整它 使其工作方式类似于 stackoverflow math stackexchange 在输入问题时显示预览的方式
  • 通过 ASP.NET 菜单控件禁用 javascript 生成

    在我的网站中 我使用标准 ASP NET 菜单控件 我已经编写了一个自定义控制适配器来摆脱由默认控制适配器生成的相当俗气的 html 输出 但有一件事一直困扰着我 不知何故 ASP NET 生成了我的菜单控件不需要的额外 JavaScrip
  • Google 地理编码 API 错误:超出查询限制。 - 导轨

    我知道有人问过这个问题 但大多数答案都是几年前的 而且并非全部针对 Ruby on Rails 项目 在我当前的项目中 我使用 Geocode gem 通过 Ruby on Rails 任何人都可以按用户的位置搜索用户 我还使用 Carme
  • 使用ggplot、gtable和cowplot固定图例框的宽度

    我想用 R 制作一个绘图 看起来像用 Mac 的 Numbers 制作的示例 我正在努力处理情节和图例框之间的空间 这是我想要实现的目标的示例 在一些用户的帮助下 请参阅帖子末尾以供参考 我已经非常接近了 这是我当前的功能 library