首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在scale_continuous_fill()中测试名称参数

在scale_continuous_fill()中测试名称参数
EN

Stack Overflow用户
提问于 2019-01-17 08:16:00
回答 1查看 136关注 0票数 1

问题:--我正在使用testthat包测试ggplot2图形。我找不到图例名的位置(即name参数用于scale_fill_continuous())。name保存在哪里?(具体示例见文章末尾的可重复示例)。

我的搜索者:我已经搜索过了,但是其他带有[testthat][ggplot]标签的问题没有帮助(例如这一个这一个)。我也浏览了单元测试,找不到答案。

可重复的例子:,我正在寻找expression("Legend name"^2)的位置,这样我就可以测试并确保它是正确的。

代码语言:javascript
运行
AI代码解释
复制
library(ggplot2)
library(testthat)

# Create example data and plots
df <- data.frame(
    x = c(1, 2, 3, 1, 4, 5, 6, 4), 
    y = c(1, 2, 1, 1, 1, 2, 1, 1),
    z = rep(1:2, each = 4),
    group = rep(letters[1:2], each = 4))

my_plot <- 
    ggplot(df, aes(x = x, y = y, group = group, fill = z )) +
    geom_polygon() +
    scale_fill_continuous(name = expression("Legend name"^2), 
                          low = "skyblue", high = "orange")

my_wrong_plot <- 
    ggplot(df, aes(x = x, y = y, group = group, fill = z)) +
    geom_polygon() +
    scale_fill_continuous(name = expression("Wrong name"^2), 
                          low = "skyblue", high = "orange")

# Example tests that work
test_that("plot is drawn correctly", {
    expect_identical(
        deparse(my_plot$mapping$group),
        deparse(my_wrong_plot$mapping$group),
        info = 'The `group` aesthetic is incorrect.'
    )
    expect_identical(
        deparse(my_plot$mapping$fill),
        deparse(my_wrong_plot$mapping$fill),
        info = 'The `fill` aesthetic is incorrect.'
    )     
    expect_identical(
        class(my_plot$layers[[1]]$geom)[1],
        class(my_wrong_plot$layers[[1]]$geom)[1],
        info = 'There is no polygon layer.'
    )         
    expect_identical(
        layer_data(my_plot),
        layer_data(my_wrong_plot),
        info = "The `scale_fill_continuous()` data is incorrect."
    )         
})
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-01-19 05:00:39

简短回答

假设您的ggplot对象名为p,并且您已经在缩放中指定了name参数,那么它将在p$scales$scales[[i]]$name中找到( i对应于标度的顺序)。

长答案

下面是一个关于我是如何找到它的长篇大论。没有必要回答这个问题,但它可能会帮助你下一次,当你想要寻找的东西,在全球合作伙伴关系。

起始点:通常情况下,将ggplot对象转换为grob对象很有用,因为grob对象允许我们在ggplot中做一些我们很难破解的事情(例如,在不被切断的情况下,在绘图区域的边缘绘制一个geom,用不同的颜色为不同的面条着色,为每个方面手工绘制面宽,将绘图添加到另一个地图作为自定义注释,等等)。

ggplot2包有一个函数ggplotGrob,它执行转换。这意味着,如果我们检查沿途的步骤,我们应该能够找到一个步骤,该步骤可以在ggplot对象中找到缩放标题,以便将其转换为某种类型的textGrob。

这反过来意味着我们将接受以下一行代码&向下连续的层,直到我们找出引擎盖下面发生了什么:

代码语言:javascript
运行
AI代码解释
复制
ggplotGrob(my_plot)

Layer 1ggplotGrob本身只是两个函数( ggplot_buildggplot_gtable )的包装器。

代码语言:javascript
运行
AI代码解释
复制
> ggplotGrob
function (x) 
{
    ggplot_gtable(ggplot_build(x))
}

来自?ggplot_build

ggplot_build接受绘图对象,并执行生成可以呈现的对象所需的所有步骤。该函数输出两部分:一个数据帧列表(每个层一个)和一个面板对象,其中包含关于轴限值、断点等的所有信息。

来自?ggplot_gtable

此函数构建显示绘图所需的所有grobs,并将它们存储在称为gtable()的特殊数据结构中。如果您想要编程操作,这个对象是可以接受的(例如)使图例框2厘米宽,或将多个情节组合成一个单一的显示,保持纵横比的情节。

Layer 2:当输入控制台时,ggplot_buildggplot_gtable只返回一个通用的UseMethod("<function name>",而实际的函数没有从ggplot2包中导出。尽管如此,您还是可以在GitHub (链接)上找到它们,也可以使用三冒号:::访问它们。

代码语言:javascript
运行
AI代码解释
复制
> ggplot2:::ggplot_build.ggplot
function (plot) 
{
    plot <- plot_clone(plot)
    # ... omitted for space
    layout <- create_layout(plot$facet, plot$coordinates)
    data <- layout$setup(layer_data, plot$data, plot$plot_env)
    # ... omitted for space
    structure(list(data = data, layout = layout, plot = plot), 
        class = "ggplot_built")
}

> ggplot2:::ggplot_gtable.ggplot_built
function (data) 
{
    plot <- data$plot
    layout <- data$layout
    data <- data$data
    theme <- plot_theme(plot)
    # ... omitted for space
    position <- theme$legend.position %||% "right"
    # ... omitted for space
    legend_box <- if (position != "none") {
        build_guides(plot$scales, plot$layers, plot$mapping, 
            position, theme, plot$guides, plot$labels)
    }
    # ... omitted for space
}

我们看到ggplot2:::ggplot_gtable.ggplot_built中有一个代码块,它似乎创建了一个图例框:

代码语言:javascript
运行
AI代码解释
复制
    legend_box <- if (position != "none") {
        build_guides(plot$scales, plot$layers, plot$mapping, 
            position, theme, plot$guides, plot$labels)
    }

让我们来测试一下是否真的是这样:

代码语言:javascript
运行
AI代码解释
复制
g.build <- ggplot_build(my_plot)

legend.box <- ggplot2:::build_guides(
  g.build$plot$scales, 
  g.build$plot$layers, 
  g.build$plot$mapping, 
  "right", 
  ggplot2:::plot_theme(g.build$plot), 
  g.build$plot$guides, 
  g.build$plot$labels)

grid::grid.draw(legend.box)

的确如此。让我们放大看看ggplot2:::build_guides做了什么。

Layer 3:在ggplot2:::build_guides中,在处理图例框的位置和对齐的代码行之后,指南定义(gdefs)由名为guides_train的函数生成

代码语言:javascript
运行
AI代码解释
复制
> ggplot2:::build_guides
function (scales, layers, default_mapping, position, theme, guides, 
    labels) 
{
    # ... omitted for space
    gdefs <- guides_train(scales = scales, theme = theme, guides = guides, 
        labels = labels)
    # .. omitted for space
}

和以前一样,我们可以为每个参数插入适当的值&检查这些指导定义说了什么:

代码语言:javascript
运行
AI代码解释
复制
gdefs <- ggplot2:::guides_train(
  scales = g.build$plot$scales, 
  theme = ggplot2:::plot_theme(g.build$plot),
  guides = g.build$plot$guides,
  labels = g.build$plot$labels
  )

> gdefs    
[[1]]
$title
expression("Legend name"^2)

$title.position
NULL
#... omitted for space

是的,这就是我们所期望的规模名称:expression("Legend name"^2)ggplot2:::guides_train (或其内部的一些函数)已经将其从g.build$plot$<something> / ggplot2:::plot_theme(g.build$plot)中提取出来,但我们必须深入挖掘,看看哪一个&如何实现。

Layer 4:在ggplot2:::guides_train中,我们找到一行代码,从几个可能的位置之一获取图例标题:

代码语言:javascript
运行
AI代码解释
复制
> guides_train
function (scales, theme, guides, labels) 
{
    gdefs <- list()
    for (scale in scales$scales) {
        for (output in scale$aesthetics) {
            guide <- guides[[output]] %||% scale$guide
            # ... omitted for space
            guide$title <- scale$make_title(guide$title %|W|% 
                scale$name %|W|% labels[[output]])
            # ... omitted for space
        }
    }
    gdefs
}

(ggplot2:::%||%ggplot2:::%|W|%是包中未导出的函数。它们接受两个值,如果定义了/不放弃第一个值,则返回第二个值。)

我们突然从找传奇头衔的地方太少变成了有太多的地方。在这里,按优先次序排列:

  1. 如果定义了g.build$plot$guides[["fill"]],而g.build$plot$guides[["fill"]]$title的值不是waiver()g.build$plot$guides[["fill"]]$title
  2. 否则,如果g.build$plot$scales$scales[[1]]$guide$title的值不是waiver()g.build$plot$scales$scales[[1]]$guide$title
  3. 否则,如果g.build$plot$scales$scales[[1]]$name的值不是waiver()g.build$plot$scales$scales[[1]]$name
  4. 其他:g.build$plot$labels[["fill"]].

我们还通过查看ggplot2:::ggplot_build.ggplot背后的代码了解到,g.build$plot与最初输入的my_plot本质上是相同的,因此您可以用my_plot替换列表中的每个g.build$plot实例。

Side备注:如果您的ggplot对象存在某种身份危机,并且包含为相同比例定义的多个图例标题,则使用的优先级列表是相同的。说明如下:

代码语言:javascript
运行
AI代码解释
复制
base.plot <- ggplot(df, 
         aes(x = x, y = y, group = group, fill = z )) +
  geom_polygon()

cowplot::plot_grid(
  # plot 1: title defined in guides() overrides titles defined in `scale_...`
  base.plot + ggtitle("1") +
    scale_fill_continuous(
      name = "scale",
      low = "skyblue", high = "orange",
      guide = guide_colorbar(title = "guide in scale")) +
    guides(fill = guide_colorbar(title = "guide")),
  # plot 2: title defined in scale_...'s guide overrides scale_...'s name
  base.plot + ggtitle("2") +
    scale_fill_continuous(
      name = "scale",
      low = "skyblue", high = "orange",
      guide = guide_colorbar(title = "guide in scale")),
  # plot 3: title defined in `scale_...'s name
  base.plot + ggtitle("3") +
    scale_fill_continuous(
      name = "scale",
      low = "skyblue", high = "orange"),
  # plot 4: with no title defined anywhere, defaults to variable name
  base.plot + ggtitle("4") +
    scale_fill_continuous(
      low = "skyblue", high = "orange"),
  nrow = 2
)

汇总:现在我们已经爬回兔子洞了,我们知道,根据您为图例定义标题的位置,您可以找到它存储在您的ggplot对象中的相应位置。但是,这个标题在情节中是否是可见的,取决于您是否也定义了另一个具有更高优先级的标题.

代码语言:javascript
运行
AI代码解释
复制
sample.plot <- ggplot(df, 
         aes(x = x, y = y, group = group, fill = z )) +
  geom_polygon() +
    scale_fill_continuous(
      name = "title3",
      guide = guide_colorbar(title = "title2")) +
    guides(fill = guide_colorbar(title = "title1"))

> sample.plot$guides[["fill"]]$title
[1] "title1"
> sample.plot$scales$scales[[1]]$guide$title
[1] "title2"
> sample.plot$scales$scales[[1]]$name
[1] "title3"
> sample.plot$labels[["fill"]]
[1] "z"
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54240034

复制
相关文章
子比主题博客加个底部导航教程
打开自己网站下的 /wp-content/themes/zibll/funactions.php 文件,然后把下面的代码加入到文件内。
你的明明呐丶
2022/06/27
6890
子比主题博客加个底部导航教程
Android shape左边框、上下边框、任意边框
效果图: 上图可以看到,4个边框的显示是不一样的,同理也可以做到单个边框 或者 双边 <?xml version="1.0" encoding="UTF-8"?> <layer-list xmlns:
yechaoa
2022/06/10
3.1K0
Android shape左边框、上下边框、任意边框
WordPress子比主题添加底部统计信息模块小工具
织音在此提醒您:zibll.com是Zibll子比主题唯一官网,子比主题受国家版权保护,著作权登记号: 2021SR0401471 使用盗版主题对您的网站及财产安全将会带来无数的未知风险!同时,开发不易,我们一直在努力让子比主题变得更加美好,为了您的权益及作者的不易,真诚的呼吁每一位用户:支持正版,从我做起!
若梦
2022/04/01
1.5K0
【OpenXml】Pptx的边框虚线转为WPF的边框虚线
首先,我们先安装nuget的需要的有关的Openxml sdk,我们开源了解析pptx的Openxml拍平层,下面两种方式都可以安装:
ryzenWzd
2021/12/31
1.9K0
【OpenXml】Pptx的边框虚线转为WPF的边框虚线
你可以恢复模糊的图像吗?
有人认为恢复模糊的图像是不可能的,因为会丢失信息。但我对这个问题进行了很多思考,并认为如果输出图像的大小与输入图像的大小相同,那实际上是可能的!这样,输出就有足够的像素/信息来恢复原始像素/信息。
小白学视觉
2022/02/14
1.2K0
你可以恢复模糊的图像吗?
VM真的比Container更安全吗?
理论上来说,是的。但在工作实践中,那可就不一定了。 写在前面的话 我们经常会说,“HTTPS是安全的”或者“HTTP是不安全的”。但其实我们想表达的是,“HTTPS的内容更加难被窥探到”,“这将会让中
FB客服
2018/02/28
1.3K0
VM真的比Container更安全吗?
边框的巧妙应用
边框有一些特殊的属性,可以采用边框来实现对话框的效果,而且兼容性杠杠的,不过在ie6下面可能会遇到兼容性问题,在后面分析它。 首先,我们看看边框的组成结构: <div style="width
欲休
2018/03/15
9980
边框的巧妙应用
css边框的秘密
核心:除了样式不可以省略.其他的都可以,但是如果颜色省略了就是默认的黑色。宽度大小如果省略了就是medium;。 编写的顺序:边框的宽度 边框的样式 边框的颜色
贵哥的编程之路
2020/10/28
2.2K0
css边框的秘密
CSS边框
border-方向:width style color(border对应分别是宽度 样式 颜色中间空格隔开。)
十月梦想
2018/08/29
3.3K0
改变UITextView的边框颜色
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010105969/article/details/51086444
用户1451823
2018/09/13
2.2K0
边框阴影
CSS边框阴影 1.属性 box-shadow 2.取值 1.h-shadow(必须加) 代表是水平方向阴影 取正值  代表往右偏移 取负值  代表往左偏移 2.v-shadow(必须加) 代表是垂直方向阴影 取正值   代表往下偏移 取负值   代表往上偏移 3.blur(可以加可以不加)  模糊距离 4.spread(可以加可以不加)阴影的尺寸 5.color(可以加可以不加) 6.inset    将外阴影改为内阴影 最常用的 box-shadow:0 0 blur color; #div1 { wi
十月梦想
2018/08/29
2.4K0
CSS——边框
定义 边框(Border)属性是对HTML元素的边框进行定义的CSS属性。 概述 通过边框的样式设置,给元素增加更丰富的外观 边框的设置包含以下内容: 边框的类型 边框的尺寸 边框的前景背景 圆角边框 列表 元素 描述 border border 属性是规定各种单独的边界属性的简写属性,可用于设置一个或多个以下属性的值:border-width,border-style,border-color。 border-bottom border-bottom 该属性是用来将下边框的所有属性:border-bott
Html5知典
2019/11/26
4K0
边框样式的写法总结
今天在群里讨论了border的样式写法,发现border的写法还真是灵活,做了一下总结,希望对大家有用:
GhostZhang
2022/08/22
4000
【CSS】盒子边框 ② ( 盒子边框单独指定语法 )
盒子的 边框 Border , 由 四个方向 的边框组成 , 左上右下 四个 方向 上的 边框 可以单独指定样式 ,
韩曙亮
2023/03/30
3.2K0
【CSS】盒子边框 ② ( 盒子边框单独指定语法 )
CSS实线边框渐变以及虚线边框渐变
给border-image加linear-gradient不难理解,但是如果单纯使用border-image,会发现效果是这样的:
javascript.shop
2019/09/04
8.7K0
CSS实线边框渐变以及虚线边框渐变
css 边框重合加边框双向展开实现
如果要实现这种效果,高亮边框就不能使用border属性来实现了。 这里我的思路是将高亮边框用div实现代码如下
切图仔
2022/09/14
2.8K0
【MySQL 源码】UNION 比 UNION ALL 的性能差很多吗?
原文地址: 【MySQL 源码】UNION 比 UNION ALL 的性能差很多吗? 欢迎访问我的个人博客: http://blog.duhbb.com/ 引言 本文从源码角度分析了一下 MySQL
tuhooo
2022/07/11
6340
【模型训练】SGD的那些变种,真的比SGD强吗
深度学习框架目前基本上都是使用梯度下降算法及其变种进行优化,通常意义上大家会认为原始的梯度下降算法是最弱的,但事实上并非如此。
用户1508658
2019/07/26
8820
【模型训练】SGD的那些变种,真的比SGD强吗
基于GAN的图像水印去除器,效果堪比PS高手
简介:李翔,国内某互联网大厂AI民工,前携程酒店图像技术负责人,计算机视觉和深度学习重度爱好者,在ICCV和CVPR等会议上发表论文十余篇。
AI科技大本营
2019/07/03
2.1K0
基于GAN的图像水印去除器,效果堪比PS高手
点击加载更多

相似问题

“使用”out参数

70

带有OUT参数的WebMethod,然后在javascript中调用方法

10

PLSQL中IN、OUT、IN OUT参数的区别

13

ItemPreparedStatementSetter在out参数中无效

26

通过javascript中的ref/out参数调用Webmethod

10
添加站长 进交流群

领取专属 10元无门槛券

AI混元助手 在线答疑

扫码加入开发者社群
关注 腾讯云开发者公众号

洞察 腾讯核心技术

剖析业界实践案例

扫码关注腾讯云开发者公众号
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档