《R for Data Science (2e)》免费中文翻译 (第9章) --- Layers(2)

写在前面

本系列推文为《R for Data Science (2)》的中文翻译版本。所有内容都通过开源免费的方式上传至Github,欢迎大家参与贡献,详细信息见:
Books-zh-cn 项目介绍:
Books-zh-cn:开源免费的中文书籍社区
r4ds-zh-cn Github 地址:
https://github.com/Books-zh-cn/r4ds-zh-cn
r4ds-zh-cn 网站地址:
https://books-zh-cn.github.io/r4ds-zh-cn/


目录

  • 9.5 统计转换

  • 9.6 位置调整

  • 9.7 坐标系统

  • 9.8 图形的分层语法

  • 9.9 总结

9.5 统计转换

考虑使用 geom_bar()geom_col() 绘制的基本条形图(bar chart)。 下图显示了 diamonds 数据集中的钻石(diamonds)总数,按 cut 分组。diamonds 数据集位于 ggplot2 包中,包含 ~54,000 颗钻石的信息,包括每颗钻石的 price, carat, color, clarity, and cut。 该图表显示,高质量 cuts 的钻石数量多于低质量 cuts 的钻石。

复制代码
ggplot(diamonds, aes(x = cut)) + 
  geom_bar()

在 x-axis,图表显示 cut,这是 diamonds 的一个变量。 在 y-axis,它显示 count,但 count 不是 diamonds 中的变量! count 从何而来? 许多图表,例如 scatterplots,都会绘制数据集的原始值。 其他图表,例如 bar charts,会计算要绘制的新值:

  • Bar charts, histograms, and frequency polygons 对数据进行分 bin,然后绘制 bin counts,即每个 bin 中的点数。

  • Smoothers 将模型拟合到您的数据,然后根据模型绘制预测。

  • Boxplots 计算分布的 five-number summary,然后将该 summary 显示为特殊格式的 box。

用于计算图形新值的算法称为 stat ,是统计变换(statistical transformation)的缩写。Figure 9.2 显示了此过程如何与 geom_bar() 配合使用。

Figure 9.2: 创建条形图时,我们首先从原始数据开始,然后将其聚合以计算每个条形中的观察值数量,最后映射这些计算变量以绘制美观的图。

您可以通过检查 stat 参数的默认值来了解 geom 使用哪个 stat。 例如,?geom_bar 显示 stat 的默认值为 "count",这意味着 geom_bar() 使用 stat_count()stat_count()geom_bar() 记录在同一页面上。 如果向下滚动,名为 "Computed variables" 的部分会解释它计算两个新变量:countprop

每个 geom 都有一个默认的 stat;每个 stat 都有一个默认的 geom。 这意味着您通常可以使用 geoms,而不必担心底层的统计转换。 但是,您可能需要显式使用 stat 的三个原因如下:

  1. 您可能想要覆盖默认 stat。 在下面的代码中,我们将 geom_bar() 的 stat 从 count (默认)更改为 identity。 这让我们可以将条形的高度映射到 y 变量的原始值。

    复制代码
    diamonds |>
      count(cut) |>
      ggplot(aes(x = cut, y = n)) +
      geom_bar(stat = "identity")
  2. 您可能想要覆盖从转换变量到美学的默认映射。 例如,您可能想要显示比例条形图,而不是计数:

    复制代码
    ggplot(diamonds, aes(x = cut, y = after_stat(prop), group = 1)) + 
      geom_bar()

    要查找可由 stat 计算的可能变量,请在 geom_bar() 的帮助中查找标题为 "computed variables" 的部分。

  3. 您可能希望更加关注代码中的统计转换。 例如,您可以使用 stat_summary(),它总结每个唯一 x 值的 y 值,以引起人们对您正在计算的 summary 的注意:

    复制代码
    ggplot(diamonds) + 
      stat_summary(
        aes(x = cut, y = depth),
        fun.min = min,
        fun.max = max,
        fun = median
      )

ggplot2 提供了 20 多种 stats 供您使用。 每个 stat 都是一个函数,因此您可以通过通常的方式获得帮助,例如 ?stat_bin

9.5.1 练习

  1. stat_summary() 关联的默认 geom 是什么? 如何重写前面的绘图以使用 geom 函数而不是 stat 函数?

  2. geom_col() 的作用是什么? 它与 geom_bar() 有什么不同?

  3. 大多数 geoms 和 stats 都是成对出现的,几乎总是一起使用。 列出所有配对的列表。 他们有什么共同点? (提示:通读文档。)

  4. stat_smooth() 计算哪些变量? 什么参数控制其行为?

  5. 在我们的比例条形图中,我们需要设置 group = 1。 为什么呢?换 句话说,这两张图有什么问题呢?

    复制代码
    ggplot(diamonds, aes(x = cut, y = after_stat(prop))) + 
      geom_bar()
    ggplot(diamonds, aes(x = cut, fill = color, y = after_stat(prop))) + 
      geom_bar()

9.6 位置调整

条形图还有一个神奇之处。 您可以使用 color aesthetic 或更有用的 fill aesthetic 来为条形图着色:

复制代码
# Left
ggplot(mpg, aes(x = drv, color = drv)) + 
  geom_bar()

# Right
ggplot(mpg, aes(x = drv, fill = drv)) + 
  geom_bar()

请注意,如果将 fill aesthetic 映射到另一个变量(例如 class),会发生什么:条形图会自动堆叠(stacked)。 每个彩色矩形代表 drvclass 的组合。

复制代码
ggplot(mpg, aes(x = drv, fill = class)) + 
  geom_bar()

使用 position 参数指定的位置调整(position adjustment )自动执行堆叠。 如果您不需要堆叠条形图,可以使用其他三个选项之一:"identity", "dodge" or "fill"

  • position = "identity" 将把每个对象准确地放置在图表上下文中的位置。 这对于条形图来说不是很有用,因为它会导致重叠。 要看到重叠,我们需要通过将 alpha 设置为较小的值来使条形稍微透明,或者通过设置 fill = NA 使条形完全透明。

    复制代码
    # Left
    ggplot(mpg, aes(x = drv, fill = class)) + 
      geom_bar(alpha = 1/5, position = "identity")
    
    # Right
    ggplot(mpg, aes(x = drv, color = class)) + 
      geom_bar(fill = NA, position = "identity")

    identity position 调整对于 2d geoms 更有用,例如 points,它是默认值。

  • position = "fill" 的工作方式类似于堆叠(stacking),但使每组堆叠的条形高度相同。 这使得比较不同组之间的比例变得更加容易。

  • position = "dodge" 将重叠的对象直接放在一起。 这使得比较各个值变得更容易。

    复制代码
    # Left
    ggplot(mpg, aes(x = drv, fill = class)) + 
      geom_bar(position = "fill")
    
    # Right
    ggplot(mpg, aes(x = drv, fill = class)) + 
      geom_bar(position = "dodge")

还有另一种类型的调整对于条形图没有用,但对于散点图非常有用。 回想一下我们的第一个散点图。 您是否注意到该图仅显示 126 个点,即使数据集中有 234 个观测值?

hwydispl 的基础值是四舍五入的,因此这些点出现在网格上,并且许多点彼此重叠。 此问题称为过度绘图(overplotting )。这 种安排使得很难看到数据的分布。 数据点是否均匀分布在整个图表中,或者是否存在包含 109 个值的 hwydispl 的一种特殊组合?

您可以通过将位置调整设置为 "jitter" 来避免这种网格化。position = "jitter" 为每个点添加少量随机噪声。 这会将点分散开,因为没有两个点可能接收到相同数量的随机噪声。

复制代码
ggplot(mpg, aes(x = displ, y = hwy)) + 
  geom_point(position = "jitter")

添加随机性似乎是改善绘图的一种奇怪方法,但虽然它会使您的图表在小尺度上不太准确,但它会使您的图表在大尺度上更具启发性。 因为这是一个非常有用的操作,所以 ggplot2 附带了 geom_point(position = "jitter") 的简写形式:geom_jitter()

要了解有关 position adjustment 的更多信息,请查找与每个调整相关的帮助页面:?position_dodge, ?position_fill, ?position_identity, ?position_jitter, and ?position_stack

9.6.1 练习

  1. 下面的绘图有什么问题吗? 你可以如何改进它?

    复制代码
    ggplot(mpg, aes(x = cty, y = hwy)) + 
      geom_point()
  2. 两个图之间有什么区别(如果有的话)?为 什么?

    复制代码
    ggplot(mpg, aes(x = displ, y = hwy)) +
      geom_point()
    ggplot(mpg, aes(x = displ, y = hwy)) +
      geom_point(position = "identity")
  3. geom_jitter() 的哪些参数控制抖动量?

  4. geom_jitter()geom_count() 进行比较和对比。

  5. geom_boxplot() 的默认位置调整是多少? 创建 mpg 数据集的可视化来演示它。

9.7 坐标系统

坐标系统(Coordinate systems)可能是 ggplot2 中最复杂的部分。 默认坐标系是笛卡尔坐标系,其中 x 和 y 位置独立作用以确定每个点的位置。 还有另外两个坐标系偶尔会有帮助。

  • coord_quickmap() 正确设置地理地图的纵横比。 如果您使用 ggplot2 绘制空间数据,这一点非常重要。 本书没有足够的篇幅来讨论地图,但您可以在 ggplot2: Elegant graphics for data analysisMaps chapter 了解更多信息。

    复制代码
    nz <- map_data("nz")
    
    ggplot(nz, aes(x = long, y = lat, group = group)) +
      geom_polygon(fill = "white", color = "black")
    
    ggplot(nz, aes(x = long, y = lat, group = group)) +
      geom_polygon(fill = "white", color = "black") +
      coord_quickmap()
  • coord_polar() 使用极坐标。 极坐标揭示了 bar chart 和 Coxcomb chart 之间的有趣联系。

    复制代码
    bar <- ggplot(data = diamonds) + 
      geom_bar(
        mapping = aes(x = clarity, fill = clarity), 
        show.legend = FALSE,
        width = 1
      ) + 
      theme(aspect.ratio = 1)
    
    bar + coord_flip()
    bar + coord_polar()

9.7.1 练习

  1. 使用 coord_polar() 将 stacked bar chart 转换为 pie chart。

  2. coord_quickmap()coord_map() 有什么区别?

  3. 下图告诉您什么关于城市和高速公路 mpg 之间的关系? 为什么 coord_fixed() 很重要?geom_abline() 的作用是什么?

    复制代码
    ggplot(data = mpg, mapping = aes(x = cty, y = hwy)) +
      geom_point() + 
      geom_abline() +
      coord_fixed()

9.8 图形的分层语法

我们可以通过添加 position adjustments, stats, coordinate systems, and faceting 来扩展您在 Section 1.3 中学到的图形模板:

复制代码
ggplot(data = <DATA>) + 
  <GEOM_FUNCTION>(
     mapping = aes(<MAPPINGS>),
     stat = <STAT>, 
     position = <POSITION>
  ) +
  <COORDINATE_FUNCTION> +
  <FACET_FUNCTION>

我们的新模板采用七个参数,即模板中出现的括号内的单词。 在实践中,您很少需要提供所有七个参数来制作图表,因为 ggplot2 将为除 data、mappings、 、geom 函数之外的所有内容提供有用的默认值。

模板中的七个参数组成了图形语法,这是一个用于构建绘图的正式系统。 图形语法基于这样的见解:您可以将任何绘图独特地描述为 a dataset、a geom、a set of mappings、a stat、a position adjustment、a coordinate system、a faceting scheme、a theme 的组合。

要了解其工作原理,请考虑如何从头开始构建基本图:您可以从 dataset 开始,然后将其转换为您想要显示的信息(with a stat)。 接下来,您可以选择一个 geometric object 来表示转换数据中的每个观测值。 然后,您可以使用 geoms 的 aesthetic properties 来表示数据中的变量。 您可以将每个变量的值 map 到 aesthetic 水平。 这些步骤如 Figure 9.3 所示。 然后,您可以选择一个 coordinate system 来放置 geoms,使用对象的位置(其本身就是一种美学属性)来显示 x 和 y 变量的值。

Figure 9.3: 从原始数据到频率表再到条形图的步骤,其中条形的高度代表频率。

此时,您将拥有一个完整的图形,但您可以进一步调整坐标系内 geoms 的位置(a position adjustment)或将图形拆分为子图(faceting)。 您还可以通过添加一个或多个附加图层来扩展绘图,其中每个附加图层都使用 a dataset, a geom, a set of mappings, a stat, and a position adjustment。

您可以使用此方法来构建您想象的任何绘图。 换句话说,您可以使用本章中学到的代码模板来构建数十万个独特的绘图。

如果您想了解更多关于 ggplot2 的理论基础,您可能会喜欢阅读 "The Layered Grammar of Graphics",这是一篇详细描述 ggplot2 理论的科学论文: https://vita.had.co.nz/papers/layered-grammar.pdf

9.9 总结

在本章中,您学习了图形的分层语法,从 aesthetics 和 geometries 开始构建简单的绘图,将绘图 facets 成子集,了解如何计算 geoms 的 statistics,在 geoms 可能发生变化时控制位置细节以避免重叠的 position adjustments。 coordinate systems 允许您从根本上改变 xy 的含义。 我们还没有触及的一层是 theme,我们将在 Section 11.5 中介绍它。

ggplot2 cheatsheet (which you can find at https://posit.co/resources/cheatsheets) 和 ggplot2 package website (https://ggplot2.tidyverse.org) 是了解完整 ggplot2 功能的两个非常有用的资源。

从本章中你应该学到的一个重要教训是,当你觉得需要 ggplot2 未提供的 geom 时,最好看看其他人是否已经通过创建一个 ggplot2 扩展包来解决你的问题,该扩展包提供了那个 geom。

--------------- 本章结束 ---------------

本期翻译贡献:

  • @TigerZ生信宝库

注:本文已开启快捷转载,欢迎大家转载,只需标明文章出处即可。

相关推荐
海大哥21 小时前
深入解析Java中HashMap的工作原理与性能优化策略
r语言
万粉变现经纪人2 天前
如何解决 pip install -r requirements.txt 约束文件 constraints.txt 仅允许固定版本(未锁定报错)问题
开发语言·python·r语言·django·beautifulsoup·pandas·pip
万粉变现经纪人2 天前
如何解决 pip install -r requirements.txt 无效可编辑项 ‘e .‘(-e 拼写错误)问题
开发语言·python·r语言·beautifulsoup·pandas·pip·scipy
zhangfeng11332 天前
亲测可用,R语言 ggplot2 箱线图线条控制参数详解,箱线图离散数值控制
开发语言·python·r语言·生物信息
zhangfeng11333 天前
R 导出 PDF 时中文不显示 不依赖 showtext** 的最简方案(用 extrafont 把系统 TTF 真正灌进 PDF 内核)
开发语言·r语言·pdf·生物信息
生物小卡拉3 天前
R脚本--PCA分析系列1_v1.0
开发语言·r语言
生物小卡拉3 天前
R脚本——LefSE分析与可视化-v1
开发语言·r语言
猫头虎4 天前
如何解决 pip install -r requirements.txt 本地轮子路径 ‘./packages/xxx.whl’ 不存在 问题
开发语言·网络·python·r语言·pip·gpu算力·国产
zhangfeng11335 天前
R语言 表达矩阵 count_table 筛选出 行名是 某个 基因的 数据或者某个列中的数据是某个基因的数据
矩阵·r语言·生物信息