第四章R、RStudio和ggplot2简介

4.2 dplyr包简介

dplyr包提供了一组函数,用于有效地操作R中的数据集。dplyr包是下一代“plyr”,只关注数据帧。因此,它对于转换和汇总具有行和列的表格数据非常有用,例如对于微生物组数据集。dplyr包包含一组函数(“verbs”),它们执行最常见的数据操作任务,如选择特定列、筛选行、重新排序行、添加新列和汇总数据。重要的单个dplyr函数包括:

select() and rename() 可根据列名称选择列(变量)

filter() 根据值筛选行(案例)

arrange() 对行(案例)进行重新排序或排列

mutate() and transmute()用于创建新列,例如,添加作为现有变量函数的新变量

summarise()去汇总值

group_by() 进行群体观察

sample_n() and sample_frac()进行随机抽样

此外,“dplyr”包含一个重要的函数group_by(),用于执行与“拆分-应用-组合”概念相关的另一个常见任务。此外,dplyr从magrittr包导入了管道操作符:%>%。当组合几个函数时,管道操作符非常有用。通常,在R中,如果将几个函数组合在一起,会将它们彼此嵌套。嵌套函数从内到外操作。例如,在以下代码中,select()嵌套在head()中,操作符从选择列id开始,并写入以生成新的数据帧,然后应用head()来获取新数据帧的前6行。在这里,使用公开可用的数据集hsb2demo说明此程序包。

> setwd("E:/Home/MicrobiomeStatR/Analysis")

> tab <- read.csv("hsb2demo.csv")

> head(tab)

     id female race ses schtyp prog read write math science socst

1  70      0    4  1      1    1  57    52  41      47    57

2 121      1    4  2      1    3  68    59  53      63    61

3  86      0    4  3      1    1  44    33  54      58    31

4 141      0    4  3      1    3  63    44  47      53    56

5 172      0    4  2      1    2  47    52  57      53    61

6 113      0    4  2      1    2  44    52  51      63    61

接下来,安装并加载dplyr。

> install.packages("dplyr")

> library(dplyr)

管道运算符%>%不是从内到外读取函数,而是从左到右读取函数。在下面的R代码中,通过管道将制表符数据框传递给select()函数以选择两列(id和write),然后通过管道将新数据框传递给head()函数,后者返回新数据框头。

> tab %>%

+ select(id,write) %>%

+ head

   id write

1  70    52

2 121    59

3  86    33

4 141    44

5 172    52

6 113    52

使用select()选择列:Select()允许使用通常只在数字变量位置上工作的操作按名称快速设置一组列的子集

> # Select columns: id, read, write and math

> head(select(tab, id, read, write, math))

id read write math

1  70  57    52  41

2 121  68    59  53

3  86  44    33  54

4 141  63    44  47

5 172  47    52  57

6 113  44    52  51

要按名称选择列范围,请使用“:”(冒号)运算符。

> # Select all columns between read and socst (inclusive)

> head(select(tab, read:socst))

  read write math science socst

1  57    52  41      47    57

2  68    59  53      63    61

3  44    33  54      58    31

4  63    44  47      53    56

5  47    52  57      53    61

6  44    52  51      63    61

要选择除特定列或一系列列之外的所有列,请使用“−”(减法)运算符(也称为负索引)。

> # Select all columns except female

> head(select(tab, -female))

id race ses schtyp prog read write math science socst

1  70    4  1      1    1  57    52  41      47    57

2 121    4  2      1    3  68    59  53      63    61

3  86    4  3      1    1  44    33  54      58    31

4 141    4  3      1    3  63    44  47      53    56

5 172    4  2      1    2  47    52  57      53    61

6 113    4  2      1    2  44    52  51      63    61

> # Select all columns except those from female to prog (inclusive)

> head(select(tab, -(female:prog )))

id read write math science socst

1  70  57    52  41      47    57

2 121  68    59  53      63    61

3  86  44    33  54  58    31

4 141  63    44  47      53    56

5 172  47    52  57      53    61

6 113  44    52  51      63    61

在select()中还可以使用其他函数根据特定条件选择列,例如starts_with()、ends_with()、matches()、concludes()和one_of()。它们可以帮助快速匹配满足以下条件的较大变量块标准。Starts_with()用于选择以字符串开头的所有列;ends_with()用于选择以字符串结尾的列;matches()用于选择与正则表达式匹配的列;CONTAINS()用于选择与文字字符串匹配的列。

> # select all columns that start with the character string "s"

> head(select(tab, starts_with("s")))

ses schtyp science socst

1  1      1      47    57

2  2      1      63    61

3  3      1      58    31

4  3      1      53    56

5  2      1      53    61

6  2      1      63    61

Using filter()选择行:Filter()允许选择数据框中的行子集。与所有单个函数一样,第一个参数是数据框的名称。第二个和后续参数是数据框的变量,选择表达式为TRUE的行。

> #Selecting rows using filter()

> # Filter the rows for students with reading score greater than or equal 70.

> filter(tab, read >= 70)

id female race ses schtyp prog read write math science socst

1  95      0    4  3      1    2  73    60  71      61    71

2 103      0    4  3      1    2  76    52  64      64    61

3 132      0    4  2      1    2  73    62  73      69    66

4  68      0    4  2      1    2  73    67  71      63    66

5  57      1    4  2      1    2  71    65  72      66    56

6 180      1    4  3      2    2  71    65  69      58    71

7  34      1    1  3      2    2  73    61  57      55    66

8  93      1    4  3      1    2  73    67  62      58    66

9  61      1    4  3      1    2  76    63  60      67    66

> #Filter the rows for students with both reading and math scores greater

than or equal 70

> filter(tab, read >= 70, math >= 70)

    id female race ses schtyp prog read write math science socst

1  95      0    4  3      1    2  73    60  71      61    71

2 132      0    4  2      1    2  73    62  73      69    66

3  68      0    4  2      1    2  73    67  71      63    66

4  57      1    4  2      1    2  71    65  72      66    56

Using arrange()重新排序行:Arrange()的工作方式类似于filter(),不同之处在于它不是过滤或选择行,而是对它们重新排序

> #Re-order by read and write

> head(arrange(tab, id, read, write))

id female race ses schtyp prog read write math science socst

1  1      1    1  1      1    3  34    44  40      39    41

2  2      1    1  2      1    3  39    41  33      42    41

3  3      0    1  1      1    2  63    65  48      63    56

4  4      1    1  1      1    2  44    50  41      39    51

5  5      0    1  1      1    2  47    40  43      45    31

6  6      1    1  1      1    2  47    41  46      40    41

> #Use desc() to order a column in descending order

> head(arrange(tab, desc(read)))

id female race ses schtyp prog read write math science socst

1 103      0    4  3      1    2  76    52  64      64    61

2  61      1    4  3    1    2  76    63  60      67    66

3  95      0    4  3      1    2  73    60  71      61    71

4 132      0    4  2      1    2  73    62  73      69    66

5  68      0    4  2      1    2  73    67  71      63    66

6  34      1    1  3    2    2  73    61  57      55    66

管道运算符:%>%可以与Arrange()一起使用

> #To re-order rows by a particular column(female)

> tab %>% arrange(female) %>% head

id female race ses schtyp prog read write math science socst

1  70      0    4  1      1    1  57    52  41      47    57

2  86      0    4  3      1    1  44    33  54      58    31

3 141      0    4  3      1    3  63    44  47      53    56

4 172      0    4  2      1    2  47    52  57      53    61

5 113      0    4  2      1    2  44    52  51      63    61

6  50      0    3  2      1    1  50    59  42      53    61

> #Select three columns id, gender, read from tab

> #Arrange the rows by the gender and then by read

> #Then return the head of the final data frame

> tab%>%select(id, female, read) %>%

+          arrange(female, read) %>%

+          head

id female read

1 164      0  31

2  11      0  34

3  53      0  34

4 108      0  34

5 117      0  34

6 165      0  36

> #Filter the rows for read with score greater or equal to 70

> tab %>% select(id, female, read) %>%

+  arrange(female, read) %>%

+    filter(read >= 70)

id female read

1  95      0  73

2 132      0  73

3  68      0  73

4 103      0  76

5  57      1  71

6 180  1  71

7  34      1  73

8  93      1  73

9  61      1  76

> #Arrange the rows for read in a descending order

> tab %>% select(id, female, read) %>%

+    arrange(female, desc(read)) %>%

+    filter(read >= 70)

id female read

1 103      0  76

2  95      0  73

3 132      0  73

4  68      0  73

5  61      1  76

6  34      1  73

7  93      1  73

8  57      1  71

9 180      1  71

Using mutate()创建新列:创建作为现有列的函数的新列。

> #Create new columns using mutate()

> #Calculate average read and write scores

> head(mutate(tab, avg_read = sum(read)/n()))

id female race ses schtyp prog read write math science socst

1  70      0    4  1      1    1  57    52  41      47    57

2 121      1    4  2      1    3  68    59  53      63    61

3  86      0    4  3      1    1  44    33  54      58    31

4 141      0    4  3      1    3  63    44  47      53    56

5 172      0    4  2      1    2  47    52  57      53    61

6 113      0    4  2      1    2  44    52  51      63    61

avg_read

1    52.23

2    52.23

3    52.23

4    52.23

5    52.23

6    52.23

> #To keep only the new variables, use transmute()

> head(transmute(tab,avg_read = sum(read)/n()))

avg_read

1    52.23

2    52.23

3  52.23

4    52.23

5    52.23

6    52.23

> #Create new columns using mutate() and pipe operator

> tab %>% mutate(avg_read = sum(read/n())) %>%

+  head

id female race ses schtyp prog read write math science socst

1  70      0    4  1      1    1  57    52  41      47    57

2 121      1    4  2      1    3  68    59  53      63    61

3  86      0    4  3      1    1  44    33  54      58    31

4 141      0    4  3      1    3  63    44  47      53    56

5 172      0    4  2      1    2  47    52  57      53    61

6 113      0    4  2      1    2  44    52  51      63    61

avg_read

1    52.23

2    52.23

3    52.23

4    52.23

5    52.23

6    52.23

Using summarise()汇总值:Summarise()结合其他汇总统计信息,例如Mean()、SD()、Min()、Medium()、sum()、n()、First()、Last()和n_DISTINCT(),为数据帧框的给定列创建汇总统计信息。以下代码用于计算阅读分数的平均值

> #To collapses a data frame to a single row.

> summarise(tab, avg_read = mean(read, na.rm = TRUE))

avg_read

1    52.23

以下代码用于查找平均值和其他汇总统计数据。

> #Create summaries of the data frame using summarise() and pipe operator

> tab %>% summarise(avg_read = mean(read),

+                    min_read = min(read),

+                    max_read = max(read),

+                    n = n())

avg_read min_read max_read  n

1    52.23      28      76 200

Using group_by()将观测值分组:此函数将数据集分解为指定的行组。它将数据框按某个变量拆分,对各个数据框应用函数,然后合并输出。接下来,我们首先按性别对总共200个观察数据进行分组,然后得出按性别进行阅读的汇总统计数据。

> #First group by gender, and then get the summary statistics of reading by g

ender

> by_gender <- group_by(tab, female)

> read_by_gender <- summarise(by_gender,

+                              n = n(),

+                              avg_read = mean(read, na.rm = TRUE),

+                              min_read = min(read,na.rm = TRUE),

+                              max_read = max(read,na.rm = TRUE))

> read_by_gender

# A tibble: 2 x 5

female    n avg_read min_read max_read

<int> <int>    <dbl>    <dbl>    <dbl>

1      0    91    52.82      31      76

2      1  109    51.73      28      76

同样的工作可以通过管道操作来完成。

> #Create summaries of the data frame using summarise() and pipe operator

> tab %>% group_by(female) %>%

+        summarise(n = n(),

+                    avg_read  = mean(read),

+                    min_read = min(read),

+                    max_read = max(read))

# A tibble: 2 x 5

female    n avg_read min_read max_read

<int> <int>    <dbl>    <dbl>    <dbl>

1      0    91    52.82      31      76

2      1  109    51.73      28      76

Using sample_n() and sample_frac()对行进行随机抽样

> #Use sample_n() to sample a fixed number

> sample_n(tab, 5)

id female race ses schtyp prog read write math science socst

183  92      1    4  3      1    1  52    67  57      63    61

156 139      1    4  2    1    2  68    59  61      55    71

184 160      1    4  2      1    2  55    65  55      50    61

47  49      0    3  3      1    3  50    40  39      49    47

85  58      0    4  2      1    3  55    41  40      44    41

> #Use sample_frac() to sample a fixed fraction

> sample_frac(tab, 0.02)

id female race ses schtyp prog read write math science socst

38  80      0    4  3      1    2  65    62  68      66    66

160  39      1    3  3      1    2  66    67  67      61    66

127 105      1    4  2      1    2  50    41  45      44    56

130  45      1    3  1      1    3  34    35  41      29    26

> #Use replace = TRUE to perform a bootstrap sampling

> sample_n(tab, 5,replace = TRUE)

id female race ses schtyp prog read write math science socst

11  75      0    4  2      1    3  60    46  51      53    61

180  63      1    4  1      1    1  52    65  60      56    51

182 193      1    4  2      2    2  44    49  48      39    51

103  47      1    3  1      1    2  47    46  49      33    41

96  173      1    4  1      1    1    50    62  61      63    51


4.3 ggplot2简介

ggplot2 and the Grammar of Graphics:ggplot2包是由Wickham(2016)编写和维护的,目的是为数据分析创建优雅的图形。由于它的多功能性、清晰和一致的界面,并提供漂亮的、可供发表的图形,ggplot2吸引了R社区的许多用户,特别是在高通量测序技术产生的数据的一些研究领域,如微生物组数据。该软件包使用GRID软件包提供了一系列用于创建完整情节的高级函数,并对“图形语法”(Wilkinson 2005)的原理进行了扩展和提炼。图形语法的基本思想是独立地指定绘图组件,并将它们组合在一起来构建我们想要的几乎任何类型的图形显示。Wilkinson’s语法有六个主要组成部分,包括:数据、转换、元素、比例、向导和坐标系。虽然韦翰语法的高级组成部分与威尔金森语法非常相似,但韦翰强调并将他提出的图形语法命名为分层语法,以区别于威尔金森的图形语法。图形的分层语法是基于从多层数据构建图形。它将绘图的组成部分定义为:数据、美学映射、统计变换、几何对象、位置调整、比例、坐标系和刻面,如表4.2所示。威尔金森语法的成分可以映射到分层语法的成分:分层语法的一层相当于威尔金森的元素;分层语法的尺度相当于威尔金森语法的尺度和导向;层次语法的坐标系和分面等同于威尔金森的坐标系。然而,Wilkinson的翻译在ggplot2中没有对应关系(它的角色由内置的R特性扮演)。


分层语法的组成部分

Using ggplot()简化创建plot的规范:ggplot2的算法很简单:您提供数据,告诉ggplot2如何将变量映射到美学,使用什么图形,并且它负责细节。在ggplot2中,层负责创建我们在绘图上感知到的对象。层由四个部分组成:数据和美学映射、统计变换(STAT)、几何对象(GEOM)和位置调整(Wickham 2010)。一个打印可以有多个图层。这些图层与坐标系和变换相结合,以生成最终绘图。以下是绘图生成过程:

map variables to aesthetics —> facet datasets —> transform scales —> compute aesthetics —> train scales —> map scales —> render genoms.

不使用默认值的完整步骤:在本节中,将使用以前使用的iris数据集来说明如何使用gglot()函数创建散点图。从gglot()开始创建一个Plot对象,然后添加其他组件。Sepal.Length与Sepal.Width的散点图的完整ggplot2规范为:

> library(ggplot2)

> ggplot() +

+ layer(

+  data = iris, mapping = aes(x = Sepal.Width, y = Sepal.Length),

+  geom = "point", stat = "identity", position = "identity"

+ )  +

+ scale_y_continuous() +

+ scale_x_continuous() +

+ coord_cartesian()

可以看到,单个图层指定了数据、地图、几何、统计和位置、两个连续的位置比例和一个笛卡尔坐标系。

要通过智能地使用默认值简化规范,请执行以下操作:完整的规格非常复杂,尤其是层是最复杂的。有两种方法可以简化语法语法:一种是智能地使用语法的默认值,我们将在这里介绍;另一种是使用qplot()函数,我们将在下一小节中介绍该函数。您可以智能地使用以下三种默认值来简化代码:(1)每个geom都有一个默认的stat(反之亦然),所以我们只需要指定geom或stat中的一个,而不是两个都指定。(2)不需要指定笛卡尔坐标系,因为它是默认坐标系。(3)根据美学和变量类型增加默认比例。例如,对于位置,用线性缩放变换连续值,并将类别值映射到整数;对于颜色,将连续变量映射到HCL颜色空间中的平滑路径,将离散变量映射到具有相等亮度和色度的均匀间隔色调。因此,我们可以将上述规格减少如下:

> ggplot() +

+ layer(

+  data = iris, mapping = aes(x = Sepal.Width, y = Sepal.Length),

+  geom = "point"

+ )

通常,我们可以省略data=和Mapping=,而不是在gglot()调用中指定默认数据集和映射,还可以在aes(x变量,y变量)中使用基于位置的匹配。我们也可以省略这一层。所以规格可以减少如下:

> ggplot(iris, aes(Sepal.Width, Sepal.Length)) +

+ geom_point()

当省略层时,geom=“geometry”的规范将被替换为相应的几何函数,例如,在本例中,geom=“point”将被替换为geom_point()。类似地,STAT=“STATISTICS”的规范将被替换为相应的统计函数,例如,STAT=“Smooth”将被替换为STAT_Smooth()。图层中指定的任何美学效果都将覆盖默认设置。同样,如果在图层中指定了数据集,它将替代打印默认值。以下代码使用scale_x_log10()和scale_y_log10()函数进行对数变换,覆盖通过scale_y_Continuity()和scale_x_Continuity()指定的默认线性变换。

> ggplot(iris, aes(Sepal.Width, Sepal.Length)) +

+ geom_point()

> ggplot(iris, aes(Sepal.Width, Sepal.Length)) +

+ geom_point() +

+ stat_smooth(method = lm) +

+ scale_x_log10() +

+ scale_y_log10()

如果我们不使用默认值,那么完整的规范应该如下所示:

> ggplot() +

+ layer(

+  data = iris, mapping = aes(x = Sepal.Width, y = Sepal.Length),

+  geom = "point", stat = "identity", position = "identity"

+ )  +

+ layer(

+  data = iris, mapping = aes(x = Sepal.Width, y = Sepal.Length),

+  geom = "smooth", position = "identity",

+  stat = "smooth"""", method = lm

+ )  +

+ scale_y_log10() +

+ scale_x_log10() +

+ coord_cartesian()

Using qplot()减少输入语法语法量:在ggplot2中,有两个主要的高级函数用于创建绘图:qlot(),简称为快速绘图,和gglot()。使用qlot(),以一次创建所有图的方式创建一个图;使用gglot(),按块和层函数创建一个图。使用qlot()补充ggplot2的原因是为了减少所需的输入量。因为即使我们使用了许多缺省值,ggplot2的显式语法语法也相当冗长,这使得快速尝试不同的绘图变得困难。它还模仿lot()函数的语法,使ggplot2对于熟悉BaseR图形的用户更容易使用。例如,如果对上面的绘图使用qlot(),则代码为:

> qplot(Sepal.Width, Sepal.Length, data = iris,

+  geom = c("point", "smooth"),

+  method = "lm", log = "xy")

虽然qlot()对于熟悉BASE R图形的用户来说是快速而方便的,但是它的局限性是显而易见的:因为qlot()函数假设多个层将使用相同的数据和美学映射,所以方法参数没有显式的层可供应用,并且特定的数据转换、绘图布局的定义和控制也受到限制。因此,在这种情况下,需要更高级的gglot()函数。

Using ggplot()绘图

使用gglot()逐层创建:ggplot2语法的第一个明显特征是分层,这意味着一个情节至少由一个层创建,并通过使用gglot()函数在现有的情节中添加更多玩家来增强。我们在表4.2中描述并在上面的代码中看到,层结合了数据、美观映射、几何对象(Geom)、统计(统计变换)和位置调整。层是用geom(几何对象)完成的,因此ggplot2中的层也称为“geom”。因此,在ggplot2中,绘图实际上是由geom(例如,geom_point())创建的,并由更多geom(例如,geom_mooth()等)增强。一个几何图形表示一层地块。ggplot2的第二个明显特性是它使用数据框,而不是单个向量。因此,在使用该软件包创建绘图之前,如果数据是矢量,则需要将数据转换为数据框。提供给gglot()本身或提供给各个geom以创建绘图的所有数据都包含在数据框中。使用以前使用过的iris数据集来说明如何使用gglot()函数逐层创建绘图。假设我们想要创建Sepal的散点图。长度与间隔宽度之比。

Step 1:要初始化一个基本的ggPlot,我们从ggPlot()开始,创建一个包含数据和美观映射的Plot对象。我们将绘图对象命名为p(图4.2)。


Fig. 4.2 A blank ggplot() plot object with created by data and aesthetic mapping

> library(ggplot2)

> p <- ggplot(iris, aes(x=Sepal.Width, y=Sepal.Length))

> # Sepal.Width and Sepal.Length are columns in iris dataframe

> p

应该在aes()函数中指定数据帧中需要绘图的任何信息。在本例中,我们通过aes()函数实现美学映射:分别指定x和y变量。但是,只绘制了一个空白的ggplot。因为到目前为止,我们只告诉ggplot()应该使用什么数据集,以及应该为x、y轴和颜色使用哪些列。但是我们还没有明确要求它画任何点或者一条线。要实际绘制散点图或折线图,我们必须使用geom图层显式地请求ggplot()。对象p是由数据和包含关于该图的信息的其他组件组成的类ggPlot的R S3对象。我们可以使用Summary()函数访问信息的详细信息,以跟踪确切使用了哪些数据以及变量是如何映射的。

> summary(p)

data: Sepal.Length, Sepal.Width, Petal.Length, Petal.Width,

Species [150x5]

mapping: x = Sepal.Width, y = Sepal.Length

faceting: <ggproto object: Class FacetNull, Facet>

我们可以看到,数据框有150行和5列(变量),其中两个变量分别映射到x轴和y轴。

Step 2:要绘制散点图,我们使用一个名为geom_point()的geom图层将点添加到绘图对象p。ggplot2中的基本绘图是使用数据、美学映射和几何图形来实现的。我们已经有了数据、美观地图的组件,需要添加的组件是散点图地理图层。可以使用+运算符添加图层,后跟定义带点散点图的函数:geom_point()(图4.3)。

> #Add scatterplot geom (layer1)

> p1 <- p + geom_point()

同样,我们使用Summary()函数访问新Plot对象的详细信息:

> summary(p1)

输出:data: Sepal.Length, Sepal.Width, Petal.Length, Petal.Width, Species[150x5]

mapping: x = Sepal.Width, y = Sepal.Length

faceting: <ggproto object: Class FacetNull, Facet>

-----------------------------------

geom_point: na.rm = FALSE

stat_identity: na.rm = FALSE

position_identity


Fig. 4.3 A scatterplot created by data and aesthetic mapping and geom_point()

我们可以看到,新的Plot对象添加了使用的geom和stat详细信息。在这个绘图中,我们创建一个Plot对象,然后通过+操作符添加层来创建一个新的Plot对象;或者,我们可以一起提供所有代码。这两个选项返回相同的结果。

> ggplot(iris, aes(x=Sepal.Width, y=Sepal.Length)) + geom_point()

与geom_point()一样,网站(http://ggplot2.tidyverse.org/reference/).)上的ggplot2中也提供了许多其他geom。例如,除geom_point()绘制点以生成散点图外;geom_mooth()使数据更平滑,并显示平滑程度及其标准误差;geom_boxlot()生成方框和胡须图以总结一组点的分布;geom_path()和geom_line()在数据点之间绘制线条。对于连续变量,geom_histgraph()绘制直方图,geom_freqpoly()创建频率多边形,以及geom_density()创建密度图。对于离散变量,geom_bar()绘制条形图。这里我们要添加一个平滑层。

Step 3:要绘制具有平滑曲线的散点图,向前面的绘图对象添加了一个名为geom_Smooth()的额外图层。对于这个图,将方法设置为lm(线性模型的缩写)来绘制最佳拟合线(图4.4)。

> #Add smoothing geom (layer2)

> p2 <- p1 + geom_smooth(method="lm")

> p 2

> summary(p2)

data: Sepal.Length, Sepal.Width, Petal.Length, Petal.Width,

Species [150x5]

mapping: x = Sepal.Width, y = Sepal.Length

faceting: <ggproto object: Class FacetNull, Facet>

-----------------------------------

geom_point: na.rm = FALSE

stat_identity: na.rm = FALSE

position_identity

geom_smooth: na.rm = FALSE

stat_smooth: na.rm = FALSE, method = lm, formula = y * x, se = TRUE

position_identity


Fig. 4.4 A scatterplot created by data, aesthetic mapping, and geom_point() and geom_smooth()

输出显示添加到打印对象的附加图层使用线性模型进行平滑。窒息曲线也有置信区间。我们可以设置se=false来关闭置信带。

> #set se = FALSE to turn off confidence bands

> p1 + geom_smooth(method="lm", se = FALSE)

Using Scales更改geom图层的美学效果:从数据到美学属性的映射是由尺度函数控制的,例如在章节中。4.3.2.1,轴中x-y位置的scale_y_Continuity()和scale_x_Continuity()。尺度函数既可用于连续变量,也可用于分类变量。例如,在连续情况下,比例用于填充直方图或密度图;在离散情况下,比例用于填充直方图或条形图,或者在映射颜色、大小或形状时用于散点图。我们需要知道用于映射到变量的美学属性取决于使用的geom()函数。因此,我们可以通过指定各个geom层的参数来更改美学属性。在这种情况下,我们更改点的颜色和大小,以及最佳拟合的线的颜色(图4.5)。更改颜色的另一个重要应用是将不同的颜色映射到源数据集中类别变量的不同级别。例如,在微生物群研究中,我们经常使用不同的颜色来呈现不同的试验组或条件。由于分类变量在源数据集中,因此必须在ase()函数中指定它(图4.6)。

> p3 <- ggplot(iris, aes(x=Sepal.Width, y=Sepal.Length)) +

+ #Add scatterplot geom (layer1)

+ geom_point(col="blue", size=3) +

+ #Add smoothing geom (layer2)

+ geom_smooth(method="lm",col="red",size=2)

> p3


Fig. 4.5 Change the color and size of points and best fitted line

> p4 <- ggplot(iris, aes(x=Sepal.Width, y=Sepal.Length)) +

+ #Add scatterplot geom (layer1)

+ geom_point(aes(col=Species), size=3) +

+ #Add smoothing geom (layer2)

+ geom_smooth(method="lm",col="red",size=2)

> p4


Fig. 4.6 Map the color of points based on levels of categorical variable. Three kinds of speciesare presented by three different colors

我们可以看到,由于使用aes (col = Species),散点图中的点根据其所属的物种呈现不同的颜色。实际上,在ggplot2中,除了颜色之外,我们还可以使用大小、形状、笔划(边界粗细)和填充(填充颜色)来区分适当地块中的分组。

Using the Coordinate System 调整X和Y轴的步骤:坐标系的用途是在计算机屏幕上调整从坐标到2D平面的映射。在ggplot2中可用的不同坐标系中,笛卡尔坐标系和极地坐标系是最常用的。每个坐标系都有关联的功能。例如,对于笛卡尔坐标系,坐标函数包括:coord_cartesian(xlim,ylim)、coord_flip()和coord_fix(Ratio,xlim,ylim);对于极坐标,通常使用函数coord_polal(theta,start,direction)。我们可以使用这些函数及其相应的参数来调整要在绘图中显示的属性。在这里,我们说明如何使用coord_cartesian()的参数xlim和ylim分别调整X轴和Y轴的限制。在下面的代码中,我们创建了一个新的对象P5,并使用coord_cartesian()更改X和Y轴限制以放大到感兴趣的区域。然后我们绘制这个对象(图4.7)。

> p5 <- p4 + coord_cartesian(xlim=c(2.2,4.2), ylim=c(4, 7)) # zooms in

> plot(p5)


Fig. 4.7 Adjust the limits of X and Y axes using the coord_cartesian()

Adding the Labels Layer更改标题和轴标签:默认情况下,ggplot2创建的绘图没有任何标题,轴标签与绘图中使用的变量名相对应。但是,在某些情况下,例如出版物,我们可能想要将标题添加到绘图中,并且可能还想要更改X和Y轴标签。这可以使用labs()函数来完成,在该函数中,我们可以使用title、x和y参数指定轴和标题,或者使用特定的函数ggtitle()来更改标题,并使用xlab()和ylab()来指定轴标签。以下代码使用labs()函数:

> #Add Title and Labels using labs()

> p6 <- p5 + labs(title="Sepal width vs sepal length", subtitle="Using iris dataset", y="Length of Sepal", x="Width of Sepal")

> print(p6)#Or plot(p6)

Or> plot(p6)

以下代码使用ggtitle()、xlab()和ylab()函数

> #Add Title and Labels using ggtitle(), xlab() and ylab()

> p7 <-p5 + ggtitle("Sepal width vs sepal length", subtitle="Using iris

dataset") + ylab("Length of Sepal") + xlab("Width of Sepal")

> print(p7)

完整的散点图调用使用以下代码给出:

> library(ggplot2)

> ggplot(iris, aes(x=Sepal.Width, y=Sepal.Length)) +

+ geom_point(aes(col=Species), size=3) +

+ geom_smooth(method="lm",col="red",size=2) +

+ coord_cartesian(xlim=c(2.2,4.2), ylim=c(4, 7)) +

+ labs(title="Sepal width vs sepal length", subtitle="Using iris

dataset",

y="Length of Sepal", x="Width of Sepal")


Fig. 4.8 Scatterplot with changed titles and axis labels

Using Faceting跨条件检测模式:Faceting是一种强大的工具,可以用来调查不同条件下的图案是相同的还是不同的。多面化的方法是在一个图形中绘制多个地块。刻面的功能类似于网格封装中的面板。它经常出现在有关微生物组研究的出版物中。在ggplot2中,分面可以通过两种主要方式执行:grid faceting and wrap faceting。

Draw multiple plots in a grid using facet_grid(formula)

为了创建曲线图的分面,基于两个或多个变量将数据集分割成子组,然后使用这些数据集子集来生成子曲线图。函数的作用是:创建 grid faceting。该函数的语法为:facet_grid(formula)公式可以是x*y,表示将绘图拆分成变量x的每个值的一行和变量y的每个值的一列。实现facet_grid(x~y)函数会生成一个包含行和列的矩阵图,其中行和列由x和y的可能组合组成。公式可以是x*.,用于按行拆分绘图;实现facet_grid(x~)。函数按行拆分具有方向的绘图。公式也可以是.~y,用于按列拆分绘图;实现facet_grid(.~y)函数可以按列拆分具有方向的绘图。我们举例说明了facet_grid(x~.)和facet_grid(.~y)分别使用来自iris数据集的萼片宽度与萼片长度的先前散点图进行网格分面。散点图具有整个数据集的萼片长度相对于萼片宽度。我们可以使用网格刻面来检测不同种类物种的这种关系(图4.9和4.10)。


Fig. 4.9 Scatterplot with splitting plots by rows


Fig. 4.10 Scatterplot with splitting plots by columns

> #Spliting plots by rows

> ggplot(iris, aes(x=Sepal.Width, y=Sepal.Length)) +

+ geom_point(aes(col=Species), size=3) +

+ geom_smooth(method="lm",col="red",size=2) +

+ coord_cartesian(xlim=c(2.2,4.2), ylim=c(4, 7)) +

+ # Add Facet Grid

+ facet_grid(Species *.)

> #Spliting plots by columns

> ggplot(iris, aes(x=Sepal.Width, y=Sepal.Length)) +

+ geom_point(aes(col=Species), size=3) +

+ geom_smooth(method="lm",col="red",size=2) +

+ coord_cartesian(xlim=c(2.2,4.2), ylim=c(4, 7)) +

+ # Add Facet Grid

+ facet_grid(.* Species)

Facet_grid()函数的边距选项非常有用。如果指定MARCH=TRUE,则它用于创建包含所有数据的附加面。下面的代码创建了所有数据的附加列,显示了所有三个物种的散点图(图4.11)。

> #Spliting plots by columns

> ggplot(iris, aes(x=Sepal.Width, y=Sepal.Length)) +

+ geom_point(aes(col=Species), size=3) +

+ geom_smooth(method="lm",col="red",size=2) +

+ coord_cartesian(xlim=c(2.2,4.2), ylim=c(4, 7)) +

+ # Add Facet Grid

+ facet_grid(.* Species, margin=TRUE)

如果我们想要根据两个或更多变量拆分曲线图,我们需要对所有这些变量执行刻面。例如,公式.~y+z(facet_grid(.~y+z))对两个变量执行刻面,两个变量均为by列,绘图将基于一个变量与另一个变量的级别并排显示。这种可视化使得两个范畴变量的比较非常有效。在这个公式中,我们可以看到使用+运算符将附加变量z加到y上。使用Facet_WRAP(FORMULA)将一大系列地块分解为多个小地块.


Fig. 4.11 Scatterplot with splitting plots by columns containing an additional facet for all the data

Wrap faceting 将一大系列打印生成单个类别的多个小打印。此功能使包装分面特别适用于对多个级别的类别变量的分面组合进行分面。要执行WRAP刻面,我们使用facet_WRAP(FORMULA)函数。刻面变量可以作为参数以facet_WRAP(x~y+z)的形式列出。*符号左边的变量形成行,而右边的变量形成列。Facet_WRAP(x~.)的语法。用于在行中仅按x拆分绘图,并包括绘图中的所有其他子集。wrap faceting and grid faceting之间的主要区别在于,使用wrap faceting,可以选择网格中的行数和列数。我们可以分别使用nrow和ncol参数指定它们(图4.12)。

> #Facet Wrap

> #Splitting plots by columns

> ggplot(iris, aes(x=Sepal.Width, y=Sepal.Length)) +

+ geom_point(aes(col=Species), size=3) +

+ geom_smooth(method="lm",col="red",size=2) +

+ coord_cartesian(xlim=c(2.2,4.2), ylim=c(4, 7)) +

+ #Add Facet Wrap

+ facet_wrap(* Species, nrow=2)


Fig. 4.12 Scatterplot with splitting plots by columns using wrap faceting

4.4 Summary

本章介绍了R、RStudio和R包的基本功能,以及ggplot2。对于R,RStudio,关注的是如何通过R/RStudio分析数据。文中还介绍了R函数在微生物组数据中的一些应用。特别介绍了dplyr软件包,因为它在微生物组数据管理中非常有用和广泛使用。对于ggplot2,介绍了ggplot2与图形语法的关系。我们重点介绍了它的层特性ggplot2,并展示了如何使用gglot()逐层创建绘图。总体而言,本章提供了基本的统计工具,用于数据分析和绘图,以及分析微生物组数据。

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

推荐阅读更多精彩内容