美文网首页R语言IMP research
2.ggplot2——入门(二)

2.ggplot2——入门(二)

作者: denghb001 | 来源:发表于2021-11-18 08:17 被阅读0次

    2.6绘制几何图形

    您可能会猜测,通过替换geom_point()其他的 geom 函数,您会得到不同类型的图形。这是一个很好的猜测!在以下部分中,您将了解 ggplot2 中提供的一些其他重要图形类型。这不是一个详尽的列表,但包含最常用的绘图类型。你想了解跟多individual-geomscollective-geoms

    2.6.1 在图形中添加平滑曲线

    如果您的散点图包含大量噪声,则很难看到主要模式。在这种情况下,geom_smooth()向图中添加平滑线很有用:

    ggplot(mpg, aes(displ, hwy)) + 
      geom_point() + 
      geom_smooth()
    #> `geom_smooth()` using method = 'loess' and formula 'y ~ x'
    
    image.png

    这将用平滑曲线覆盖散点图,包括以灰色显示的各点置信区间的形式评估不确定性。如果您对置信区间不感兴趣,请使用geom_smooth(se = FALSE)将其关闭。

    method[geom_smooth()](https://ggplot2.tidyverse.org/reference/geom_smooth.html)的一个重要参数,它允许您选择使用哪种类型的模型来拟合平滑曲线:

    • method = "loess",n 较小时的默认值,使用平滑的局部回归(如?loess中所述)。线条的平滑程度由span参数控制,范围从 0(很不平滑)到 1(非常平滑)。

      ggplot(mpg, aes(displ, hwy)) + 
        geom_point() + 
        geom_smooth(span = 0.2)
      #> `geom_smooth()` using method = 'loess' and formula 'y ~ x'
      
      ggplot(mpg, aes(displ, hwy)) + 
        geom_point() + 
        geom_smooth(span = 1)
      #> `geom_smooth()` using method = 'loess' and formula 'y ~ x'
      
      image image

      Loess 不适用于大型数据集(内存消耗是O(n2),因此在n超过1000是下使用另一种平滑算法。

    • method = "gam"可以调用mgcv 包提供的广义可加模型。您需要先加载 mgcv,然后使用类似formula = y ~ s(x)y ~ s(x, bs = "cs")(对于大数据)的公式 。这就是 ggplot2 在超过 1000 个数据时使用。

      library(mgcv)
      ggplot(mpg, aes(displ, hwy)) + 
        geom_point() + 
        geom_smooth(method = "gam", formula = y ~ s(x))
      
    image.png
    • method = "lm" 拟合线性模型,默认进行线性拟合。

      ggplot(mpg, aes(displ, hwy)) + 
        geom_point() + 
        geom_smooth(method = "lm")
      #> `geom_smooth()` using formula 'y ~ x'
      
      image
    • method = "rlm"工作原理类似于lm(),但使用了强大的拟合算法,因此异常值不会对拟合产生太大影响。它是MASS 包的一部分,所以记得先加载它。

    2.6.2 箱线图和扰动点图

    当一组数据包含分类变量和多个连续变量时,您可能需要了解连续变量的值如何随分类变量而变化。假设我们想了解具有相同动力传动系统的汽车的耗油量如何变化。我们可以从这样的散点图开始:

    ggplot(mpg, aes(drv, hwy)) + 
      geom_point()
    
    image

    因为drvhwy的取值很少,所以有很多过度绘制。许多点绘制在同一位置,很难看到分布。有三种有用的技术可以解决这个问题:

    • 扰动点图,geom_jitter(),为数据添加了一些随机噪声,这有助于避免过度重复。

    • 箱线图,geom_boxplot()用若干统计量概括数据分布情况。

    • 小提琴图,geom_violin()显示了分布“密度”,突出数据分布密集的区域。

    这些如下图所示:

    ggplot(mpg, aes(drv, hwy)) + geom_jitter()
    ggplot(mpg, aes(drv, hwy)) + geom_boxplot()
    ggplot(mpg, aes(drv, hwy)) + geom_violin()
    
    image image image

    每种方法都有其优点和缺点。箱线图仅用五个数字对分布进行概括,而扰动点图显示了每个点,但仅适用于相对较小的数据集。小提琴图提供了最丰富的信息,但依赖于密度估计的计算,这可能难以解释。

    对于扰动点图,geom_jitter()geom_point()提供了图形属性作为控制:sizecolour,和shape。对于geom_boxplot()geom_violin(),您可以通过colourfill控制轮廓和内部颜色。

    2.6.3 直方图和频率多边形

    直方图和频数多边图显示单个数值变量的分布。与箱线图相比,它们提供了更多关于单个组分布的信息,但占用内存更大。

    ggplot(mpg, aes(hwy)) + geom_histogram()
    #> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
    ggplot(mpg, aes(hwy)) + geom_freqpoly()
    #> `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
    
    image image

    直方图和频数多边图的工作方式相同:它们对数据进行分箱,然后计算每个分箱中的观察次数。唯一的区别是:直方图使用条形显示,频率多边形使用线条显示。

    您可以使用binwidth参数控制箱的宽度(如果您不想要均匀间隔的箱,您可以使用该breaks参数)。分箱宽度是非常重要的。默认值只是将您的数据分成 30 个箱,这可能不是最佳选择。您应该尝试多个 bin 宽度,并且您可能会发现需要多个 bin 宽度来展示数据。

    ggplot(mpg, aes(hwy)) + 
      geom_freqpoly(binwidth = 2.5)
    ggplot(mpg, aes(hwy)) + 
      geom_freqpoly(binwidth = 1)
    
    image image

    频数多边形的替代方法是密度图,geom_density()。我不喜欢密度图,因为它们更难解释,因为底层计算更复杂。密度图的前提是要求基础分布是连续的、无界的和平滑的。

    要比较不同子组的分布,您可以将分类变量 (geom_histogram()) 或 (geom_freqpoly())映射到填充颜色。使用频数多边形比较分布更容易,因为基础感知任务更容易。您也可以使用分面:这会使比较更困难一些,但更容易查看每个组的分布。

    ggplot(mpg, aes(displ, colour = drv)) + 
      geom_freqpoly(binwidth = 0.5)
    ggplot(mpg, aes(displ, fill = drv)) + 
      geom_histogram(binwidth = 0.5) + 
      facet_wrap(~drv, ncol = 1)
    
    image image

    2.6.4 条形图

    离散变量情形下,条形图与直方图类似,使用geom_bar()

    ggplot(mpg, aes(manufacturer)) + 
      geom_bar()
    
    image

    修复标签链接中学习如何修复标签)。

    条形图可能会令人困惑,因为把两种截然不同的图像通常都称为条形图。上面的表格是未经过处理的数据,每个观察值对应每个条的高度。另一种形式的条形图用于预先处理的数据。例如,您有三种具有平均效果的药物:

    drugs <- data.frame(
      drug = c("a", "b", "c"),
      effect = c(4.2, 9.7, 6.1)
    )
    

    要显示此类数据,您需要修改geom_bar()默认设置( 不让stat 对数据进行分类和计数)。但是,使用geom_point()会更好,因为点比条占用的空间更少,并且不需要 y 轴包含 0。

    ggplot(drugs, aes(drug, effect)) + geom_bar(stat = "identity")
    ggplot(drugs, aes(drug, effect)) + geom_point()
    
    image image

    2.6.5 时间序列中的折线图和路径图

    折线图和路径图通常用于时间序列数据。折线图从左到右连接点,而路径图按照它们在数据集中出现的顺序连接它们(换句话说,折线图是按 x 值排序的数据的路径图)。折线图通常在 x 轴上有时间,显示单个变量如何随时间变化。路径图显示两个变量如何随时间同时变化,时间以观测值的连接方式进行编码。

    由于mpg数据集中的年份变量只有两个值,我们将使用economics数据集显示一些时间序列图,其中包含过去 40 年测量的美国经济数据。下图显示了随时间变化的两个失业图,均使用geom_line(). 第一个显示失业率,而第二个显示失业周数的中位数。我们已经可以看到这两个变量的一些差异,特别是在最后一个高峰期,失业率低于之前的高峰期,但失业的持续时间很长。

    ggplot(economics, aes(date, unemploy / pop)) +
      geom_line()
    ggplot(economics, aes(date, uempmed)) +
      geom_line()
    
    image image

    为了更详细地研究这种关系,我们想在同一个图上绘制两个时间序列。我们可以绘制失业率与失业持续时间的散点图,但是我们无法再看到随时间的演变。解决方案是将时间上相邻的点与线段连接起来,形成路径图。

    下面我们绘制失业率与失业时间的关系,并将个人观察结果与一条路径结合起来。由于有许多线交叉,在第一个图中不容易看出时间流动的方向。在第二个图中,我们为点着色,以便更容易看到时间的方向。

    ggplot(economics, aes(unemploy / pop, uempmed)) + 
      geom_path() +
      geom_point()
    
    year <- function(x) as.POSIXlt(x)$year + 1900
    ggplot(economics, aes(unemploy / pop, uempmed)) + 
      geom_path(colour = "grey50") +
      geom_point(aes(colour = year(date)))
    
    image image

    我们可以看到失业率和失业时间高度相关,但近年来失业时长相对于失业率一直在增加。

    对于纵向数据,您通常希望在每个图上显示多个时间序列,每个序列代表一个人。为此,您需要将group图形属性映射到一个变量,该变量编码每个观察的组成员资格。

    2.7 修改坐标轴

    后续将学习所有可用的选项,但有两个有用的最常见选项。xlab()ylab()修改 x 和 y 轴标签:

    ggplot(mpg, aes(cty, hwy)) +
      geom_point(alpha = 1 / 3)
    
    ggplot(mpg, aes(cty, hwy)) +
      geom_point(alpha = 1 / 3) + 
      xlab("city driving (mpg)") + 
      ylab("highway driving (mpg)")
    
    # Remove the axis labels with NULL
    ggplot(mpg, aes(cty, hwy)) +
      geom_point(alpha = 1 / 3) + 
      xlab(NULL) + 
      ylab(NULL)
    
    image image image

    xlim()ylim()修改轴的限制:

    ggplot(mpg, aes(drv, hwy)) +
      geom_jitter(width = 0.25)
    
    ggplot(mpg, aes(drv, hwy)) +
      geom_jitter(width = 0.25) + 
      xlim("f", "r") + 
      ylim(20, 30)
    #> Warning: Removed 139 rows containing missing values (geom_point).
    
    # For continuous scales, use NA to set only one limit
    ggplot(mpg, aes(drv, hwy)) +
      geom_jitter(width = 0.25, na.rm = TRUE) + 
      ylim(NA, 30)
    
    image image image

    更改坐标区范围,区间之外的值被设置为NA。您可以使用na.rm = TRUE抑制相关警告,但要小心。如果您的绘图计算汇总统计量(例如,样本均值),则此转换NA发生计算汇总统计量之前,并且在某些情况下可能会导致不希望出现的结果。

    2.8 输出

    大多数情况下,您创建一个绘图对象并立即绘制它,但您也可以将绘图保存到变量中并对其进行操作:

    p <- ggplot(mpg, aes(displ, hwy, colour = factor(cyl))) +
      geom_point()
    

    一旦你有了一个绘图对象,你可以用它做一些事情:

    • 显示在屏幕上print()。这在交互式运行时会自动发生,但在循环或函数中,您需要手动输入print()完成。

      print(p)
      
      image
    • 使用ggsave()将其保存到磁盘。

      # Save png to disk
      ggsave("plot.png", p, width = 5, height = 5)
      
    • summary() 查看图像结构。

      summary(p)
      #> data: manufacturer, model, displ, year, cyl, trans, drv, cty, hwy, fl,
      #>   class [234x11]
      #> mapping:  x = ~displ, y = ~hwy, colour = ~factor(cyl)
      #> faceting: <ggproto object: Class FacetNull, Facet, gg>
      #>     compute_layout: function
      #>     draw_back: function
      #>     draw_front: function
      #>     draw_labels: function
      #>     draw_panels: function
      #>     finish_data: function
      #>     init_scales: function
      #>     map_data: function
      #>     params: list
      #>     setup_data: function
      #>     setup_params: function
      #>     shrink: TRUE
      #>     train_scales: function
      #>     vars: function
      #>     super:  <ggproto object: Class FacetNull, Facet, gg>
      #> -----------------------------------
      #> geom_point: na.rm = FALSE
      #> stat_identity: na.rm = FALSE
      #> position_identity
      
    • 使用saveRDS(), 将它的缓存副本保存到磁盘。 这将保存绘图对象的完整副本,因此您可以轻松地使用readRDS()访问.

      saveRDS(p, "plot.rds")
      q <- readRDS("plot.rds")
      

    相关文章

      网友评论

        本文标题:2.ggplot2——入门(二)

        本文链接:https://www.haomeiwen.com/subject/uochtrtx.html