R_for_Data_Science_Introduction&ggplot2

最近参加了刘博发起的《R for data Science》的读书会活动,差不多是每周读一个章节。我决定写一些看这本书过程中的“胡思乱想”来作为我的备忘录。

这是英文版的第1,2,3章的内容

我个人还是推荐看英文版,虽然我第一遍是看的中文版。一来英文版更新,二来英文版看多了你会熟悉Tidyverse系列的语法,这样你在日常过程中有不懂的地方,方便你去google搜索。

1.1 What you will learn

  • 其实整本书所教给我们的就是下图所呈现的几步,即数据分析的整个步骤。从Import(数据导入)——Tidy(数据清洗)——Transform(数据转换)——Visualise(数据可视化)——Model(数据建模)——Communicate(数据交流)

    image

    其实也是对应着Tidverse里面的不同包。下面两张图来自于我逛twitter时候发现的

    image

    图片来源:twitter

    image

    图片来源:biostat2.uni.lu


1.2 How this book is organised

  • 作者提到了一个80%-20%法则。其实我觉得在日常的教学过程中,我们也应该遵循于类似的法则,在课程上教授80%的内容,然后要学生在课下去自学20%的内容。但话说回来,这并不意味着你不用去细心准备那20%的内容。20%的内容也应该充分地考虑到广度与深度,以及学生的学习能力。

1.3 What you won’t learn

  • 作者在这本书中并没有说明如何处理大型数据(10-100G这样子的),但也提到可以考虑用data.table来处理类似数据。不过我觉得,当你非要用这么大型的数据,你应该考虑换语言了……

  • 作者也说明了为什么没有在这本书中提到Py、Julia等语言,他认为在学习过程中一次最好只深入一种语言,这样会学的更快。这让我想起了一篇文章:Why I use R

    再提一句,语言之争是最XXX的


1.4 Prerequisites

  • 作者提到还需要安装三个数据包。关于如何自己建一个数据包,这里有一个很好的视频例子。是我在twitter上看过的,作者手把手教我们如何建一个COV19的数据包。

1.6 Getting help and learning more

  • 关于提问礼节,我觉得是最我们应该掌握的一点。其实包括我到现在也偶尔不遵守一些提问礼节……。遇到问题,首先你应该做是Google,因为很多问题其实别人都已经遇到过了,只是你没有去找或者找不到而已。同时作者也建议最好是把报错设置成英文,这样方便你去搜索,设置的方法之一就是 Sys.setenv(LANGUAGE = "en")

  • 当你实在搜索不到了,你就应该考虑问人问题。这时候你应该准备一个最基本的可复现例子。

    关于这点,让我想起有一个包,叫 reprex 也是tidyverse生态里面的。

  • 有三个基本的要素可以帮助你准备一个可复现例子

    • 在提问的时候,你应该po出你的软件版本,比如用 sessionInfo()。你的版本最好是最新的版本,因为可能你的问题已经作为一个bug在新版本里面修复了。对于tidyverse系列来说,可以用tidyverse_update 来看下你的软件版本

      # 这是我自己的
      > tidyverse_update()
      The following packages are out of date:
      
      * broom   (0.5.4 -> 0.5.5)
      * dplyr   (0.8.3 -> 0.8.5)
      * forcats (0.4.0 -> 0.5.0)
      * ggplot2 (3.2.1 -> 3.3.0)
      * modelr  (0.1.5 -> 0.1.6)
      * rlang   (0.4.2 -> 0.4.5)
      * xml2    (1.2.2 -> 1.2.5)
      
      Start a clean R session then run:
      install.packages(c("broom", "dplyr", "forcats", "ggplot2", "modelr", "rlang", 
      "xml2"))
      
    • dput函数可以快速地帮别人生成你的数据

      【r<-基础|函数】dput函数 - 保存R的数据结构

    • 让你的代码具有可读性

      • Make sure you’ve used spaces and your variable names are concise, yet informative.
      • Use comments to indicate where your problem lies.
      • Do your best to remove everything that is not related to the problem.
        The shorter your code is, the easier it is to understand, and the easier it is to fix.

      就可读性而言,推荐可以看下The tidyverse style guide

  • 最重要的一点是,自己也应该花时间去解决自己的问题,而不是一遇到问题就去找别人帮助


3.1 Introduction

  • 在用包和数据前,你应该先加载包,对于Tidyverse系列来说,一个命令就可以了。

    > library(tidyverse)
    -- Attaching packages --------------------------------------- tidyverse 1.3.0 --
    √ ggplot2 3.2.1     √ purrr   0.3.3
    √ tibble  2.1.3     √ dplyr   0.8.3
    √ tidyr   1.0.2     √ stringr 1.4.0
    √ readr   1.3.1     √ forcats 0.4.0
    -- Conflicts ------------------------------------------ tidyverse_conflicts() --
    x dplyr::filter() masks stats::filter()
    x dplyr::lag()    masks stats::lag()
    

    你会发现有一个tidyverse_conflicts(),这就是函数名冲突。让我想起了以前碰到的filter函数有时候能用,有时候不能用的问题,就是函数冲突了。具体的问题找不到了……


3.2 First steps

  • 我们在加载mpg这个数据框的时候,会发现其实际上是个 tibble

    > mpg
    # A tibble: 234 x 11
       manufacturer model displ  year   cyl trans drv     cty   hwy fl   
       <chr>        <chr> <dbl> <int> <int> <chr> <chr> <int> <int> <chr>
     1 audi         a4      1.8  1999     4 auto~ f        18    29 p    
     2 audi         a4      1.8  1999     4 manu~ f        21    29 p    
     3 audi         a4      2    2008     4 manu~ f        20    31 p    
     4 audi         a4      2    2008     4 auto~ f        21    30 p    
     5 audi         a4      2.8  1999     6 auto~ f        16    26 p    
     6 audi         a4      2.8  1999     6 manu~ f        18    26 p    
     7 audi         a4      3.1  2008     6 auto~ f        18    27 p    
     8 audi         a4 q~   1.8  1999     4 manu~ 4        18    26 p    
     9 audi         a4 q~   1.8  1999     4 auto~ 4        16    25 p    
    10 audi         a4 q~   2    2008     4 manu~ 4        20    28 p    
    # ... with 224 more rows, and 1 more variable: class <chr>
    

    tibble的一个好处就是其不会自动把你数据框里面的字符串转成因子,换而言之,stringsAsFactors = F。 当然,在接下来的R 4.0里面,stringsAsFactors = F 将会是一个R的默认选项了。

    > mpg$cyl
      [1] 4 4 4 4 6 6 6 4 4 4 4 6 6 6 6 6 6 8 8 8 8 8 8 8 8 8 8
     [28] 8 8 8 8 8 4 4 6 6 6 4 6 6 6 6 6 6 6 6 6 6 6 6 6 6 8 8
     [55] 8 8 8 6 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 8 6 6 6 6
     [82] 8 8 6 6 8 8 8 8 8 6 6 6 6 8 8 8 8 8 4 4 4 4 4 4 4 4 4
    [109] 4 4 4 4 6 6 6 4 4 4 4 6 6 6 6 6 6 8 8 8 8 8 8 8 8 8 8
    [136] 8 8 6 6 8 8 4 4 4 4 6 6 6 6 6 6 6 6 8 6 6 6 6 8 4 4 4
    [163] 4 4 4 4 4 4 4 4 4 4 4 4 4 6 6 6 8 4 4 4 4 6 6 6 4 4 4
    [190] 4 6 6 6 4 4 4 4 4 8 8 4 4 4 6 6 6 6 4 4 4 4 6 4 4 4 4
    [217] 4 5 5 6 6 4 4 4 4 5 5 4 4 4 4 6 6 6
    
  • 对于ggplot2而言,其有8个元素(当然,具体几个我也不确定……)。这里借用一张patchwork大佬thomasp85的图,来说明这几个元素。
image

3.3 Aesthetic mappings

  • 在映射里面,你除了可以把数据映射到x,y轴上,也可以把其他变量映射为图形属性(大小、点、颜色等等)。这时候ggplot2会自动为变量里面每个水平分配唯一的图形属性水平(比如说颜色),这个过程就称为标度变换。这时候还会加上图例,以表示图形属性水平和变量值之间的对应关系。

    再读一遍的好处在于你可以对一些词更加的记忆深刻,方便你去google,比如scaling(标度变换),legend(图例)

    尽管x、y和变量的映射没有图例来展示变量与图形属性的关系,但坐标轴其实也是另一种特殊类型的图例

  • ggplot2一次只会使用六种形状,这意味着如果你如果有第7种类型的使用,那么第7种类型的图片就会消失

    # 现在ggplot2会有提示了
    > ggplot(data = mpg) +
    +   geom_point(mapping = aes(x = displ, y = hwy, shape = class))
    Warning messages:
    1: The shape palette can deal with a maximum of 6 discrete values because
    more than 6 becomes difficult to discriminate; you have 7. Consider
    specifying shapes manually if you must have them. 
    2: Removed 62 rows containing missing values (geom_point). 
    
    # Left
    ggplot(data = mpg) + 
      geom_point(mapping = aes(x = displ, y = hwy, alpha = class))
    
    # Right
    ggplot(data = mpg) + 
      geom_point(mapping = aes(x = displ, y = hwy, shape = class))
    
    img
    img
  • 话说我之前一直不知道tick marks(刻度线)这个词的英文是啥……顺便搜到一个ggplot2 axis ticks : A guide to customize tick marks and labels

  • R有25种内建的图形,空心形状(0~14)的边界颜色由color 决定;实心形状(15~20)的填充颜色由 color 决定;填充形状(21~24)的边界颜色由 color 决定,填充颜色由 fill 决定。

    image

    这也意味着你可以画这样的图

    ggplot(data = mpg) +
      geom_point(mapping = aes(x = displ, y = hwy), 
                 shape = 21, 
                 fill = "red",color = "black")
    

    《R数据可视化之美》这书特喜欢fill和color一起上


  • 在exercises 3.1的第一问里面

    # What’s gone wrong with this code? Why are the points not blue?
    
    ggplot(data = mpg) +
    geom_point(mapping = aes(x = displ, y = hwy, color = "blue"))
    
    img

    至于理解的话,我觉得可以认为在原始数据框里面增加了一个新的叫color变量,然后color里面的值全是"blue"这个字符串。然后你把他映射到color这个图形属性,红色这个颜色就跟你blue这个变量level关联了起来

    但其实对于这个,有一个很好的应用在A ggplot2 Tutorial for Beautiful Plotting in R

    ggplot(chic, aes(x = date, y = o3)) +
      geom_line(aes(color = "line")) +
      geom_point(aes(color = "points")) +
      labs(x = "Year", y = "Ozone") +
      scale_color_discrete("Type:")
    
    image

3.5 Facets

  • 如果只想根据一个变量进行分面,那可以考虑 facet_wrap()。两个变量进行分面的话,用 facet_grid(行变量 ~ 列变量)。如果不想在行或列的维度进行分面,你可以使用 . 来代替变量名,例如 + facet_grid(. ~ cyl)。 至于这里面的 . ,只是用来做占位符的吧,代表忽略这个维度,我盲猜。
  • 我想起了Y叔的GSEA或者GO的分面效果。facet compareCluster result GSEA的例子我暂时找不到了。

  • exercise 3.5.1 的第一问是一个很好的问题:1. What happens if you facet on a continuous variable?

3.6 Geometric objects

  • ggplot2提供了超过40种geom,可见ggplot2_gallery。可谓是ggplot can plot everything

    但这网站似乎最近上不去了?

  • 我们时常会忽略的一点是,如果我们将图形属性映射到了分类变量上,ggplot2就可以自动帮我们把数据分类好

    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
      )  
    
    img
    img
    img
  • 我们另一个会忽略的一点是,ggplot2不仅仅是将图层叠加,你也可以在每个图层用不同的数据

    ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
      geom_point(mapping = aes(color = class)) +
      geom_smooth(data = filter(mpg, class == "subcompact"), se = FALSE)
    
    img

  • 对于exercise3.6.1的第6问的最后一个图,solution给出的方法是

    ggplot(mpg, aes(x = displ, y = hwy)) +
      geom_point(size = 4, color = "white") +
      geom_point(aes(colour = drv))
    
    # 但我觉得这样也可以
    ggplot(mpg, aes(x = displ, y = hwy, fill = drv)) +
      geom_point(size = 4, shape = 21, color = "white",
                 stroke = 3)
    

    顺便说下,我发现geom_point的默认shape是16。出自ggplot2 Quick Reference: shape

    img

3.7 Statistical transformations

  • geom里面的很多图形,比如说散点图等,都是展现了你的原始数据,但有些图形,则是会从图像中计算一些新的变量值,从而展现

    • bar charts, histograms, and frequency polygons bin your data and then plot bin counts, the number of points that fall in each bin.
    • smoothers fit a model to your data and then plot predictions from the model.
    • boxplots compute a robust summary of the distribution and then display a specially formatted box.
  • 每种geom都有其默认stat,而每种stat也有其默认geom,但需要注意的是其不是一一对应的,比如 The default geom for stat_summary() is geom_pointrange(). The default stat for geom_pointrange() is identity()。然后常见的像geom_bar的默认统计变换是count,而geom_col()的默认统计变换是identity。

    # 也就是说下面两个是一样的
    ggplot(data = diamonds) +
      stat_count(mapping = aes(x = cut))
    
    ggplot(data = diamonds) +
      geom_bar(mapping = aes(x = cut))
    
    img
  • 你也可以改变默认的统计变换

    demo <- 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")
    
    img
    # 这的确是一个很有意思的操作,展现的不是count值,而是百分比,注意在中文版里面,y = ..prop..
    # 但我还是不太懂这个原理
    # 原书中说可以看?geom_bar的帮助文档的Computed variables部分
    ggplot(data = diamonds) + 
      geom_bar(mapping = aes(x = cut, y = stat(prop), group = 1))
    
    img
    # 还有其他的统计变换
    # 这些应该就是ggplot2画error bar等常见生物统计图的基础了
    # stat_summary的默认geom是pointrange
    ggplot(data = diamonds) + 
      stat_summary(
        mapping = aes(x = cut, y = depth),
        fun.ymin = min,
        fun.ymax = max,
        fun.y = median
      )
    
    
    img
  • 话说我之前一直不太明白geom_bargeom_histogram 的区别,看完这部分可能有点懂了。geom_histogram会对你x对应的变量进行画bin,取count,然后画出柱状图,所以一般对应的是连续型变量,而geom_bar你对x对应的变量,对各个level数count,也画出柱状图,一般对应的是分类变量。不过你也可以认为geom_bar的对各个level进行的数count,也是一种特殊的“分bin”数count。毕竟我们也可以对连续型变量进行cut操作,产生的就是分类变量了。

    > cut(1:20,breaks = 2)
     [1] (0.981,10.5] (0.981,10.5] (0.981,10.5] (0.981,10.5]
     [5] (0.981,10.5] (0.981,10.5] (0.981,10.5] (0.981,10.5]
     [9] (0.981,10.5] (0.981,10.5] (10.5,20]    (10.5,20]   
    [13] (10.5,20]    (10.5,20]    (10.5,20]    (10.5,20]   
    [17] (10.5,20]    (10.5,20]    (10.5,20]    (10.5,20]   
    Levels: (0.981,10.5] (10.5,20]
    
  • solution里面列出了有互补对应的stat和geom

    geom stat
    geom_bar() stat_count()
    geom_bin2d() stat_bin_2d()
    geom_boxplot() stat_boxplot()
    geom_contour() stat_contour()
    geom_count() stat_sum()
    geom_density() stat_density()
    geom_density_2d() stat_density_2d()
    geom_hex() stat_hex()
    geom_freqpoly() stat_bin()
    geom_histogram() stat_bin()
    geom_qq_line() stat_qq_line()
    geom_qq() stat_qq()
    geom_quantile() stat_quantile()
    geom_smooth() stat_smooth()
    geom_violin() stat_violin()
    geom_sf() stat_sf()

    还有不对应的,非常地详细,强烈建议大家down一份

    solution


  • Exercise 3.7.1的第5问

    In our proportion bar chart, we need to set group = 1 Why? In other words, what is the problem with these two graphs?

    我觉得是一个非常好的问题,在solution也给出了很好的回答,虽然我还是似懂非懂……

    If group = 1 is not included, then all the bars in the plot will have the same height, a height of 1. The function geom_bar() assumes that the groups are equal to the x values since the stat computes the counts within the group.

    # 我觉得应该是因为你这里计算的是prop,但这里默认的group是x指定的分类变量,所以prop是在group里面自己计算的,就像你的count一样。prop的总和肯定是1嘛
    ggplot(data = diamonds) +
      geom_bar(mapping = aes(x = cut, y = ..prop..))
    
    img

    The problem with these two plots is that the proportions are calculated within the groups.

    ggplot(data = diamonds) +
      geom_bar(mapping = aes(x = cut, y = ..prop..))
    
    ggplot(data = diamonds) +
      geom_bar(mapping = aes(x = cut, fill = color, y = ..prop..))
    
    img
    img

    The following code will produce the intended stacked bar charts for the case with no fill aesthetic.

    # 这里把group只变成了一组,那么就会分散了
    ggplot(data = diamonds) +
      geom_bar(mapping = aes(x = cut, y = ..prop.., group = 1))
    
img

With the fill aesthetic, the heights of the bars need to be normalized.

# 此图甚好
# 等于展现了2层结果,第一层是百分比,第二层是百分比里面的color分布
ggplot(data = diamonds) +
  geom_bar(aes(x = cut, y = ..count.. / sum(..count..), fill = color))

img

3.8 Position adjustments

  • 你可以给geom_bar上色,如果将 fill 图形属性映射到另一个变量(如 clarity ),那么条形会自动分块堆叠起来。

    ggplot(data = diamonds) +
      geom_bar(mapping = aes(x = cut, fill = clarity))
    
    img

    注意这跟上面那个图不一样,纵坐标是count值。

    我觉得这里出现这个图片的原因是,首先是x=cut,让数据根据cut分组了,其次是fill映射到一个分类变量,那么就会在cut分组的基础上,再次分组

  • 这种堆积效果是通过position参数实现的(默认应该是 stack),position参数里面还有identity ,dodge or fill

  • identity是把图像放在自己的那个位置上,所以你会发现下面的图虽然看起来是跟上图一样是堆积效果。但它其实不是堆积效果,一个证据就是你会发现横坐标是不一样的。它是一层层柱状图叠加的(就像图层一样),所以我们只能设置透明度很低才能看得到

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")
img
img

identity选项对于2D图像更合适,比如说散点图

  • fill选项跟stack很像,但其会把每个堆积的bar变成同一高度,这对于比较不同组别之间的百分比更适合

    ggplot(data = diamonds) + 
      geom_bar(mapping = aes(x = cut, fill = clarity), position = "fill")
    
    img
  • dodge会把overlap的对象直接挨个排好。

      ggplot(data = diamonds) + 
        geom_bar(mapping = aes(x = cut, fill = clarity), position = "dodge")
    
    img

    可以看到这里纵坐标跟identity是一样的

  • 对于过度密度的散点图,还有个特殊的位置参数 jitter,会在每个点之间加一些随机噪音。

    ggplot(data = mpg) + 
      geom_point(mapping = aes(x = displ, y = hwy), position = "jitter")
    
    img

    加一些随机噪音虽然会使得你的图片不精确,但其的确可以提高你图片的可读性。在小尺度上的图片上,这种随机扰动可能会影响很大,但大尺度上并不会。对于这种特殊的位置选项,ggplot2还有对应的快捷函数 geom_jitter

    关于过度密度点图处理的讨论,MSMB_3 High Quality Graphics in R 有过一些。

    jitter会在箱式图或者小提琴图中经常用到,不过你也可以考虑用ggbeeswarm

  • To learn more about a position adjustment, look up the help page associated with each adjustment: ?position_dodge, ?position_fill, ?position_identity, ?position_jitter, and ?position_stack.


  • Exercise 3. 8.1的第2问:

    What parameters to geom_jitter() control the amount of jittering?

    there are two arguments to jitter:

    • width controls the amount of vertical displacement, and
    • height controls the amount of horizontal displacement.

    Note that the height and width arguments are in the units of the data. Thus height = 1 (width = 1) corresponds to different relative amounts of jittering depending on the scale of the y (x) variable. The default values of height and width are defined to be 80% of the resolution() of the data, which is the smallest non-zero distance between adjacent values of a variable. When x and y are discrete variables, their resolutions are both equal to 1, and height = 0.4 and width = 0.4 since the jitter moves points in both positive and negative directions.

  • Exercise 3. 8.1的第3问:

    Compare and contrast geom_jitter() with geom_count().

    geom_count也是个很好玩的函数。

    The geom geom_count() sizes the points relative to the number of observations. Combinations of (x, y) values with more observations will be larger than those with fewer observations.

    ggplot(data = mpg, mapping = aes(x = cty, y = hwy)) +
      geom_count()
    
    img

    两者的优劣在solution也提到了

    我觉得透明度也可以用来处理密集散点图。

  • Exerciese 3.8.1的第4问

    What’s the default position adjustment for geom_boxplot()? Create a visualization of the mpg dataset that demonstrates it.

    可以在soultion中看到,boxplot的默认是"dodge2"。

    which is a shortcut for position_dodge2. This position adjustment does not change the vertical position of a geom but moves the geom horizontally to avoid overlapping other geoms. See the documentation for position_dodge2() for additional discussion on how it works.

    When we add colour = class to the box plot, the different levels of the drv variable are placed side by side, i.e., dodged.

    ggplot(data = mpg, aes(x = drv, y = hwy, colour = class)) +
      geom_boxplot()
    
    img

    If position_identity() is used the boxplots overlap.

    ggplot(data = mpg, aes(x = drv, y = hwy, colour = class)) +
      geom_boxplot(position = "identity")
    
    img

3.9 Coordinate systems

  • 除了默认的笛卡尔坐标系统(x和y位置是独立的),还有其他坐标系统
    • coor_filp可以翻转横纵坐标

      ggplot(data = mpg, mapping = aes(x = class, y = hwy)) + 
        geom_boxplot()
      ggplot(data = mpg, mapping = aes(x = class, y = hwy)) + 
        geom_boxplot() +
        coord_flip()
      
      img
      img
    • coord_quickmap()是地图设置……我还用不到

    • coord_polar()是极坐标系统

      # 注意这里的width,默认应该是0.9.即每个柱子之间是有距离的
      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()
      
      img
      img

  • Exercise 3.9.1:

    Turn a stacked bar chart into a pie chart using coord_polar().

    是一个很好的问题。关键是width和theta = "y"

    A pie chart is a stacked bar chart with the addition of polar coordinates. Take this stacked bar chart with a single category.

    ggplot(mpg, aes(x = factor(1), fill = drv)) +
      geom_bar()
    
    img

    Now add coord_polar(theta="y") to create pie chart.

    ggplot(mpg, aes(x = factor(1), fill = drv)) +
      geom_bar(width = 1) +
      coord_polar(theta = "y")
    
    img

    The argument theta = "y" maps y to the angle of each section. If coord_polar() is specified without theta = "y", then the resulting plot is called a bulls-eye chart.

    ggplot(mpg, aes(x = factor(1), fill = drv)) +
      geom_bar(width = 1) +
      coord_polar()
    
    img
  • Exercise 3.9.2:

    What does labs() do? Read the documentation.

    这里给自己的做个备忘录

    The labs function adds axis titles, plot titles, and a caption to the plot.

    ggplot(data = mpg, mapping = aes(x = class, y = hwy)) +
      geom_boxplot() +
      coord_flip() +
      labs(
        y = "Highway MPG",
        x = "Class",
        title = "Highway MPG by car class",
        subtitle = "1999-2008",
        caption = "Source: http://fueleconomy.gov"
      )
    
    img
  • Exercise 3.9.4

    What does the plot below tell you about the relationship between city and highway mpg? Why is coord_fixed() important? What does geom_abline() do?

    The function coord_fixed() ensures that the line produced by geom_abline() is at a 45-degree angle. A 45-degree line makes it easy to compare the highway and city mileage to the case in which city and highway MPG were equal.

    p <- ggplot(data = mpg, mapping = aes(x = cty, y = hwy)) +
      geom_point() +
      geom_abline()
    p + coord_fixed()
    
    img

    If we didn’t include geom_coord(), then the line would no longer have an angle of 45 degrees.

    p
    
    img

    我们可以在第一张图那里看到在x=20,y=20那里,图像是呈现一个正方形的。coord_fixed我个人感觉的话,应该是x和y在图上的距离与真实距离的对应关系是一致的。比如x也是图上的20-30之间对应1cm,y也是20-30之间对应1cm。

    根据Cartesian coordinates with fixed "aspect ratio"

    A fixed scale coordinate system forces a specified ratio between the physical representation of data units on the axes. The ratio represents the number of units on the y-axis equivalent to one unit on the x-axis. The default, ratio = 1, ensures that one unit on the x-axis is the same length as one unit on the y-axis. Ratios higher than one make units on the y axis longer than units on the x-axis, and vice versa.


3.10 The layered grammar of graphics

  • 下图之所以会有 ..count..。是因为 ..count.. 是统计出来的值,就像 ..prop.. 或者 stat(prop)一样,而非是原始数据框里面的变量

    img
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容