4.6 几何对象
先来看看下面这两个图有什么相似之处呢?
image.png两个图都包含相同的 x 变量和 y 变量,并且都描述了相同的数据。但图形并不相同。每个图都使用不同的几何对象来表示数据。在 ggplot2 语法中,我们说它们使用不同的geoms。
要生成上面的图,可以使用以下代码:
# left
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy))
# right
ggplot(data = mpg) +
geom_smooth(mapping = aes(x = displ, y = hwy))
ggplot2 中的每个 geom 函数都有一个mapping
参数。然而,并不是每一种图形属性都适用于每一种几何对象。您可以设置点的形状,但不能设置线的“形状”。另一方面,您可以设置线的线型。geom_smooth()
将为映射到线型的变量的每个唯一值绘制具有不同线型的线。
ggplot(data = mpg) +
geom_smooth(mapping = aes(x = displ, y = hwy, linetype = drv))
image
这里geom_smooth()
根据汽车的drv
值将汽车分为三类,这描述了汽车的动力传动系统。在这里,4
代表四轮驱动、f
前轮驱动和r
后轮驱动。
如果这听起来很奇怪,我们可以通过将线条叠加在原始数据之上,然后根据drv
对所有内容进行着色来使其更加清晰。
请注意,此图在同一图中包含两个几何体!我们很快就会学习如何在同一个图中放置多个几何体。
ggplot2 提供了 40 多个 geoms,扩展包提供了更多内容(请参阅https://exts.ggplot2.tidyverse.org/gallery/以获取示例)。想要查看 ggplot2 所有的内容,您可以在http://rstudio.com/resources/cheatsheets找到它。要了解有关任何单个 geom 的更多信息,请使用 help: ?geom_smooth
。
许多几何图形,例如geom_smooth()
,使用单个几何对象来显示多行数据。对于这些几何图形,您可以将group
图形属性设置为分类变量以绘制多个对象。ggplot2 将为分组变量的每个唯一值绘制一个单独的对象。在实践中,每当您将图形属性映射到离散变量时(如linetype
示例中所示),ggplot2 将自动对这些几何图形的数据进行分组。依靠此功能很方便,因为group属性本身不会向几何图形添加图例或区别特征。
ggplot(data = mpg) +
geom_smooth(mapping = aes(x = displ, y = hwy))
ggplot(data = mpg) +
geom_smooth(mapping = aes(x = displ, y = hwy, group = drv))
ggplot(data = mpg) +
geom_smooth(
mapping = aes(x = displ, y = hwy, color = drv),
show.legend = FALSE
)
image.png
要在同一个图中显示多个 geom,直接将多个 geom 函数添加到ggplot()
:
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy)) +
geom_smooth(mapping = aes(x = displ, y = hwy))
image
然而,这会在我们的代码中引入一些重复。想象一下,如果您想将 y 轴更改为显示cty
而不是hwy
. 您需要在两个地方更改变量,而且您可能会忘记更新其中一个。您可以通过将一组映射传递给ggplot()
来避免这种类型的重复。ggplot2 将这些映射视为适用于图中每个几何图形的全局映射。换句话说,此代码将生成与先前代码相同的图:
ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
geom_point() +
geom_smooth()
如果将映射放置在 geom 函数中,ggplot2 会将它们视为图层的本地映射。它将仅使用这些映射来扩展或覆盖该层的全局映射。这使得可以在不同的层中展示不同的几何对象。
ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
geom_point(mapping = aes(color = class)) +
geom_smooth()
image
您可以使用相同的想法为data
每个图层指定不同的内容。在这里,我们的平滑线仅显示mpg
数据集的一个子集,即小型汽车。ggplot()
中的局部数据参数仅覆盖该层geom_smooth()
的全局数据参数。
ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
geom_point(mapping = aes(color = class)) +
geom_smooth(data = filter(mpg, class == "subcompact"), se = FALSE)
image
4.7 统计变换
接下来,让我们看一下条形图。条形图看起来很简单,但它们很有趣,因为它们揭示了一些关于图的微妙之处。使用geom_bar()
绘制的基本条形图。下图显示了diamonds
数据集中的钻石总数,按cut
分组。该diamonds
数据集来自GGPLOT2,并包含约54000颗钻石,其中包括每颗钻石的price
,carat
,color
,clarity
,和cut
信息。该图表显示,与低质量切割相比,高质量切割的钻石更多。
ggplot(data = diamonds) +
geom_bar(mapping = aes(x = cut))
image
在 x 轴上,图表显示cut
,一个来自diamonds
的变量。在 y 轴上,它显示计数,但计数不是diamonds
! 计数从何而来?许多图表(如散点图)绘制数据集的原始值。其他图形,如条形图,计算要绘制的新值:
-
条形图、直方图和频率多边形对您的数据进行分箱,然后绘制分箱计数,即落在每个分箱中的点数。
-
平滑器将模型拟合到您的数据,然后根据模型绘制预测。
-
boxplots 计算分布的可靠摘要,然后显示一个特殊格式的框。
用于计算图形新值的算法称为stat,是统计转换的缩写。下图描述了此过程如何与geom_bar()
.
您可以通过检查stat
参数的默认值来了解 geom 使用的统计数据。例如,?geom_bar
显示的默认值为stat
“count”,这意味着geom_bar()
使用stat_count()
. stat_count()
与geom_bar()
记录在同一页面上,如果向下滚动,您可以找到名为“计算变量”的部分。这描述了它如何计算两个新变量:count
和prop
。
您通常可以交替使用 geoms 和 stats。例如,您可以使用stat_count()
代替geom_bar()
:
ggplot(data = diamonds) +
stat_count(mapping = aes(x = cut))
image
这是有效的,因为每个 geom 都有一个默认的统计变量;并且每个 stat 都有一个默认的 geom。这意味着您通常可以使用 geom 而不必担心底层的统计转换。但是有时候,你可能需要明确使用统计数据:
-
您可能想要覆盖默认统计。在下面的代码中,我将geom_bar()的统计从count(默认)更改为identity。这让我把条形图的高度映射到y的原始值变量。不幸的是,当人们不经意地谈论柱状图时,他们可能指的是这种类型的柱状图,其中柱状图的高度已经显示在数据中,或者之前的柱状图中柱状图的高度是通过计算行生成的。
imagedemo <- tribble( ~cut, ~freq, "Fair", 1610, "Good", 4906, "Very Good", 12082, "Premium", 13791, "Ideal", 21551 ) ggplot(data = demo) + geom_bar(mapping = aes(x = cut, y = freq), stat = "identity")
-
您可能想要覆盖从转换变量到图形属性的默认映射。例如,你可能想要显示一个比例条形图,而不是计数:
imageggplot(data = diamonds) + geom_bar(mapping = aes(x = cut, y = stat(prop), group = 1))
要查找由 stat 计算的变量,请查找标题为“computed variables”的帮助部分。
-
您可能希望更多地关注代码中的统计转换。例如,您可以使用
stat_summary()
,它总结了每个唯一 x 值的 y 值,以引起对您正在计算的总结的注意:
imageggplot(data = diamonds) + stat_summary( mapping = aes(x = cut, y = depth), fun.min = min, fun.max = max, fun = median )
ggplot2 提供了 20 多个统计变量使用。每个 stat 都是一个函数,因此您可以通过通常的方式获得帮助,例如 ?stat_bin
. 要查看完整的统计信息列表,请尝试使用 ggplot2 备忘单。
4.8 位置调整
还有一种与条形图相关的。使用colour
属性为条形图着色,或者更有用的是fill
:
ggplot(data = diamonds) +
geom_bar(mapping = aes(x = cut, colour = cut))
ggplot(data = diamonds) +
geom_bar(mapping = aes(x = cut, fill = cut))
image.png
请注意如果将fill图形属性映射到另一个变量会发生什么,例如clarity
:条形自动堆叠。每个彩色矩形代表的组合cut
和clarity
。
ggplot(data = diamonds) +
geom_bar(mapping = aes(x = cut, fill = clarity))
image
通过参数指定的位置调整自动执行堆叠position
。如果您不想要堆积条形图,您可以使用其他三个选项之一:"identity"
、"dodge"
或"fill"
。
-
position = "identity"
将把每个对象准确地放置在图形上下文中的位置。这对条形不是很有用,因为它与它们重叠。要查看重叠,我们需要通过设置alpha
为较小的值来使条形略微透明,或者通过设置 使条形完全透明fill = NA
。ggplot(data = diamonds, mapping = aes(x = cut, fill = clarity)) + geom_bar(alpha = 1/5, position = "identity") ggplot(data = diamonds, mapping = aes(x = cut, colour = clarity)) + geom_bar(fill = NA, position = "identity")
`identity`位置调整对于二维几何图形更有用,例如点,它是默认设置。
-
position = "fill"
像堆叠一样工作,但使每组堆叠的条具有相同的高度。这样可以更轻松地比较各组之间的比例。
imageggplot(data = diamonds) + geom_bar(mapping = aes(x = cut, fill = clarity), position = "fill")
-
position = "dodge"
将重叠的对象直接放在一起。这样可以更轻松地比较各个值。
imageggplot(data = diamonds) + geom_bar(mapping = aes(x = cut, fill = clarity), position = "dodge")
还有一种对条形图没有用的调整类型,但它对散点图非常有用。回想一下我们的第一个散点图。您是否注意到该图仅显示 126 个点,即使数据集中有 234 个观测值?
imagehwy
和displ
的值是圆形的,所以点出现在网格上,许多点相互重叠。这个问题被称为overplotting。这种图形使得很难看到大量数据在哪里。数据点是否均匀分布在整个图中,或者是否存在一个包含109个值的特殊的hwy
和displ
组合?
您可以通过将位置调整设置为“抖动”来避免这种网格化。position = "jitter"
向每个点添加少量随机噪声。这会将点分散开,因为没有两个点可能会收到相同数量的随机噪声。
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy), position = "jitter")
image
添加随机性似乎是一种改善绘图的奇特方法,但虽然它会在小尺度上降低图形的准确性,但它会使你的图形在大尺度上更具揭示性。因为这是这样一个有用的操作,GGPLOT2自带的简写geom_point(position = "jitter")
:geom_jitter()
。
要了解更多关于位置调节,查找与每个调整相关的帮助页面:?position_dodge
,?position_fill
,?position_identity
,?position_jitter
,和?position_stack
。
4.9 坐标系
坐标系可能是 ggplot2 中最复杂的部分。默认坐标系是笛卡尔坐标系,其中 x 和 y 位置独立作用以确定每个点的位置。还有许多其他坐标系有时会有所帮助。
-
coord_flip()
切换 x 和 y 轴。如果您想要水平箱线图,这很有用(例如)。它对于长标签也很有用:很难让它们在 x 轴上不重叠。ggplot(data = mpg, mapping = aes(x = class, y = hwy)) + geom_boxplot() ggplot(data = mpg, mapping = aes(x = class, y = hwy)) + geom_boxplot() + coord_flip()
-
coord_quickmap()
正确设置地图的纵横比。如果您使用 ggplot2 绘制空间数据,这非常重要。nz <- map_data("nz") ggplot(nz, aes(long, lat, group = group)) + geom_polygon(fill = "white", colour = "black") ggplot(nz, aes(long, lat, group = group)) + geom_polygon(fill = "white", colour = "black") + coord_quickmap()
-
coord_polar()
使用极坐标。极坐标揭示了条形图和 Coxcomb 图之间的有趣联系。bar <- ggplot(data = diamonds) + geom_bar( mapping = aes(x = cut, fill = cut), show.legend = FALSE, width = 1 ) + theme(aspect.ratio = 1) + labs(x = NULL, y = NULL) bar + coord_flip() bar + coord_polar()
4.10 图形的分层语法
在前面的部分中,您学到的不仅仅是如何制作散点图、条形图和箱线图。你学习了一个基础,你可以用它来用 ggplot2制作任何类型的图。为了看到这一点,让我们向我们的代码模板添加位置调整、统计数据、坐标系和分面:
ggplot(data = <DATA>) +
<GEOM_FUNCTION>(
mapping = aes(<MAPPINGS>),
stat = <STAT>,
position = <POSITION>
) +
<COORDINATE_FUNCTION> +
<FACET_FUNCTION>
我们的新模板采用七个参数,即模板中出现的括号内的词。实际上,您很少需要提供所有七个参数来制作图形,因为 ggplot2 将为除数据、映射和 geom 函数之外的所有内容提供有用的默认值。
模板中的七个参数组成了图形的语法,一个用于构建图的正式模板。图形的语法基于这样的见解,即您可以将任何图唯一地描述为数据集、几何图形、一组映射、统计数据、位置调整、坐标系和分面方案的组合。
要了解其工作原理,请考虑如何从头开始构建基本图:您可以从数据集开始,然后将其转换为您想要显示的信息(使用统计数据)。
image接下来,您可以选择一个几何对象来表示转换数据中的每个观察值。然后,您可以使用几何图形的美学属性来表示数据中的变量。您可以将每个变量的值映射到美学级别。
image然后选择一个坐标系统来放置几何图形。您可以使用对象的位置(这本身就是一个图形属性)来显示x和y变量的值。此时,您将拥有一个完整的图,但您可以进一步调整坐标系统中的图形的位置(位置调整)或将图分割为子图(分面)。您还可以通过添加一个或多个额外层来扩展绘图,其中每个额外层使用一个数据集、一个geom、一组映射、一个统计数据和一个位置调整。
image
您可以使用此方法构建您想象的任何图形。
网友评论