跳至主要内容

Tidyverse 快速上手:教程

使用 R 和 tidyverse 开始分析泰坦尼克号数据:学习如何用 dplyr 和 ggplot2 过滤、排序、汇总、变换并可视化您的数据!
· 8分钟 阅读

使用 AI 探索

本教程整理自我们一周前进行的一场 Facebook Live 活动。主题为“Introduction to the Tidyverse(Tidyverse 入门)”,本教程将带您回顾我们在跟码环节中覆盖的全部内容!

您可以在此观看第一部分:

第二部分在这里:

注意,您可以在此仓库中找到本次课程的所有代码。

核心 tidyverse 包含您在日常数据分析中最常用的包,例如用于数据可视化的 ggplot2 和用于数据整理的 dplyr。本教程将重点介绍这两个包。

请记住,包本质上是一组用于处理数据的工具。如果您想进一步了解 R 中的包,请查看这篇教程。

想进一步了解 Tidyverse,请查看 David Robinson 在 DataCamp 开设的Introduction to Tidyverse 课程以及Learn the Tidyverse 资源。

action diagram

开始上手

首先,如果您尚未安装 tidyverse,请先安装:

# Install the tidyverse
# install.packages("tidyverse")

安装好 tidyverse 后,就该加载数据并先看看一些观测值了。

在本教程中,您将探索 泰坦尼克号数据集,其中每条观测对应一名乘客,每个变量是一项特征,例如 Name、Age 和 Survived(是否幸存)。

像这样加载您的数据:

 # Import the Tidyverse
library(tidyverse)

# Import data
passengers <- read.csv("data/train.csv")

# Check out the first several observations of your dataframe
passengers

##   PassengerId Survived Pclass
## 1           1        0      3
## 2           2        1      1
## 3           3        1      3
## 4           4        1      1
## 5           5        0      3
## 6           6        0      3
##                                                  Name    Sex Age SibSp
## 1                             Braund, Mr. Owen Harris   male  22     1
## 2 Cumings, Mrs. John Bradley (Florence Briggs Thayer) female  38     1
## 3                              Heikkinen, Miss. Laina female  26     0
## 4        Futrelle, Mrs. Jacques Heath (Lily May Peel) female  35     1
## 5                            Allen, Mr. William Henry   male  35     0
## 6                                    Moran, Mr. James   male  NA     0
##   Parch           Ticket    Fare Cabin Embarked
## 1     0        A/5 21171  7.2500              S
## 2     0         PC 17599 71.2833   C85        C
## 3     0 STON/O2. 3101282  7.9250              S
## 4     0           113803 53.1000  C123        S
## 5     0           373450  8.0500              S
## 6     0           330877  8.4583              Q

注意,您传给 read.csv() 的路径可能因环境不同而变化。如果您想保持相同的文件路径,可以在我们的 GitHub 仓库中查看本项目的文件夹结构,地址见这里。

另外,如果您想了解执行 passengers 后出现的所有变量含义,可以查看数据集说明。

要快速了解数据概况,您可以使用 summary() 函数:

# Summarize titanic
summary(passengers)

##   PassengerId       Survived          Pclass     
##  Min.   :  1.0   Min.   :0.0000   Min.   :1.000  
##  1st Qu.:223.5   1st Qu.:0.0000   1st Qu.:2.000  
##  Median :446.0   Median :0.0000   Median :3.000  
##  Mean   :446.0   Mean   :0.3838   Mean   :2.309  
##  3rd Qu.:668.5   3rd Qu.:1.0000   3rd Qu.:3.000  
##  Max.   :891.0   Max.   :1.0000   Max.   :3.000  
##                                                  
##                                     Name         Sex           Age       
##  Abbing, Mr. Anthony                  :  1   female:314   Min.   : 0.42  
##  Abbott, Mr. Rossmore Edward          :  1   male  :577   1st Qu.:20.12  
##  Abbott, Mrs. Stanton (Rosa Hunt)     :  1                Median :28.00  
##  Abelson, Mr. Samuel                  :  1                Mean   :29.70  
##  Abelson, Mrs. Samuel (Hannah Wizosky):  1                3rd Qu.:38.00  
##  Adahl, Mr. Mauritz Nils Martin       :  1                Max.   :80.00  
##  (Other)                              :885                NA's   :177    
##      SibSp           Parch             Ticket         Fare       
##  Min.   :0.000   Min.   :0.0000   1601    :  7   Min.   :  0.00  
##  1st Qu.:0.000   1st Qu.:0.0000   347082  :  7   1st Qu.:  7.91  
##  Median :0.000   Median :0.0000   CA. 2343:  7   Median : 14.45  
##  Mean   :0.523   Mean   :0.3816   3101295 :  6   Mean   : 32.20  
##  3rd Qu.:1.000   3rd Qu.:0.0000   347088  :  6   3rd Qu.: 31.00  
##  Max.   :8.000   Max.   :6.0000   CA 2144 :  6   Max.   :512.33  
##                                   (Other) :852                   
##          Cabin     Embarked
##             :687    :  2   
##  B96 B98    :  4   C:168   
##  C23 C25 C27:  4   Q: 77   
##  G6         :  4   S:644   
##  C22 C26    :  3           
##  D          :  3           
##  (Other)    :186

现在用 管道 %>% 来做同样的事,它是 tidyverse 中最顺手的工具之一:

# Summarize titanic using a pipe
passengers %>%
  summary()

##   PassengerId       Survived          Pclass     
##  Min.   :  1.0   Min.   :0.0000   Min.   :1.000  
##  1st Qu.:223.5   1st Qu.:0.0000   1st Qu.:2.000  
##  Median :446.0   Median :0.0000   Median :3.000  
##  Mean   :446.0   Mean   :0.3838   Mean   :2.309  
##  3rd Qu.:668.5   3rd Qu.:1.0000   3rd Qu.:3.000  
##  Max.   :891.0   Max.   :1.0000   Max.   :3.000  
##                                                  
##                                     Name         Sex           Age       
##  Abbing, Mr. Anthony                  :  1   female:314   Min.   : 0.42  
##  Abbott, Mr. Rossmore Edward          :  1   male  :577   1st Qu.:20.12  
##  Abbott, Mrs. Stanton (Rosa Hunt)     :  1                Median :28.00  
##  Abelson, Mr. Samuel                  :  1                Mean   :29.70  
##  Abelson, Mrs. Samuel (Hannah Wizosky):  1                3rd Qu.:38.00  
##  Adahl, Mr. Mauritz Nils Martin       :  1                Max.   :80.00  
##  (Other)                              :885                NA's   :177    
##      SibSp           Parch             Ticket         Fare       
##  Min.   :0.000   Min.   :0.0000   1601    :  7   Min.   :  0.00  
##  1st Qu.:0.000   1st Qu.:0.0000   347082  :  7   1st Qu.:  7.91  
##  Median :0.000   Median :0.0000   CA. 2343:  7   Median : 14.45  
##  Mean   :0.523   Mean   :0.3816   3101295 :  6   Mean   : 32.20  
##  3rd Qu.:1.000   3rd Qu.:0.0000   347088  :  6   3rd Qu.: 31.00  
##  Max.   :8.000   Max.   :6.0000   CA 2144 :  6   Max.   :512.33  
##                                   (Other) :852                   
##          Cabin     Embarked
##             :687    :  2   
##  B96 B98    :  4   C:168   
##  C23 C25 C27:  4   Q: 77   
##  G6         :  4   S:644   
##  C22 C26    :  3           
##  D          :  3           
##  (Other)    :186

提示:如果您想深入了解 R 中管道操作符的用法,请查看这篇教程。

在丢弃缺失值观测后再做一次。同样给您个提示:可以串接多个管道!

# Summarize titanic after dropping na
passengers %>%
  drop_na() %>%
  summary()

##   PassengerId       Survived          Pclass     
##  Min.   :  1.0   Min.   :0.0000   Min.   :1.000  
##  1st Qu.:222.2   1st Qu.:0.0000   1st Qu.:1.000  
##  Median :445.0   Median :0.0000   Median :2.000  
##  Mean   :448.6   Mean   :0.4062   Mean   :2.237  
##  3rd Qu.:677.8   3rd Qu.:1.0000   3rd Qu.:3.000  
##  Max.   :891.0   Max.   :1.0000   Max.   :3.000  
##                                                  
##                                     Name         Sex           Age       
##  Abbing, Mr. Anthony                  :  1   female:261   Min.   : 0.42  
##  Abbott, Mr. Rossmore Edward          :  1   male  :453   1st Qu.:20.12  
##  Abbott, Mrs. Stanton (Rosa Hunt)     :  1                Median :28.00  
##  Abelson, Mr. Samuel                  :  1                Mean   :29.70  
##  Abelson, Mrs. Samuel (Hannah Wizosky):  1                3rd Qu.:38.00  
##  Adahl, Mr. Mauritz Nils Martin       :  1                Max.   :80.00  
##  (Other)                              :708                               
##      SibSp            Parch                 Ticket         Fare       
##  Min.   :0.0000   Min.   :0.0000   347082      :  7   Min.   :  0.00  
##  1st Qu.:0.0000   1st Qu.:0.0000   3101295     :  6   1st Qu.:  8.05  
##  Median :0.0000   Median :0.0000   347088      :  6   Median : 15.74  
##  Mean   :0.5126   Mean   :0.4314   CA 2144     :  6   Mean   : 34.69  
##  3rd Qu.:1.0000   3rd Qu.:1.0000   382652      :  5   3rd Qu.: 33.38  
##  Max.   :5.0000   Max.   :6.0000   S.O.C. 14879:  5   Max.   :512.33  
##                                    (Other)     :679                   
##          Cabin     Embarked
##             :529    :  2   
##  B96 B98    :  4   C:130   
##  C23 C25 C27:  4   Q: 28   
##  G6         :  4   S:554   
##  C22 C26    :  3           
##  D          :  3           
##  (Other)    :167

您可能已经注意到上面代码的风格一致性。这是因为您遵循了风格指南。在数据科学以及更广泛的编程/编码中,尽快养成遵循风格指南的习惯很重要。正如 Hadley Wickham 在tidyverse 风格指南中所说,

良好的编码风格就像正确的标点符号:没有它你也能凑合,但itsuremakesthingseasiertoread。

下一节,您将使用 dplyr 进行数据整理,过滤数据、排序,并通过对旧变量进行变换来创建新特征。

整理数据

现在是探索数据并获得初步洞见的时候。您将使用 dplyr 的动词,如 filter()、arrange() 和 mutate(),它们都名副其实。

假设您想选择一组特定观测,例如“Sex”为“female”的那些。dplyr 允许我们以直观的方式,并用与您思考和讨论数据相契合的语言来实现。

filter 动词会挑选出满足条件的观测。如下所示:

# Filter to get all "male" rows
passengers %>%
  filter(Sex == "male")

##   PassengerId Survived Pclass                           Name  Sex Age
## 1           1        0      3        Braund, Mr. Owen Harris male  22
## 2           5        0      3       Allen, Mr. William Henry male  35
## 3           6        0      3               Moran, Mr. James male  NA
## 4           7        0      1        McCarthy, Mr. Timothy J male  54
## 5           8        0      3 Palsson, Master. Gosta Leonard male   2
## 6          13        0      3 Saundercock, Mr. William Henry male  20
##   SibSp Parch    Ticket    Fare Cabin Embarked
## 1     1     0 A/5 21171  7.2500              S
## 2     0     0    373450  8.0500              S
## 3     0     0    330877  8.4583              Q
## 4     0     0     17463 51.8625   E46        S
## 5     3     1    349909 21.0750              S
## 6     0     0 A/5. 2151  8.0500              S

从上述结果看,许多男性没有在 RMS 泰坦尼克号沉没中幸存。这很有意思,稍后我们将在本教程中更严谨地探索这一点!

注意,您可以像读句子一样阅读 dplyr 代码:取数据,然后(%>%)按“性别为男性”的条件进行过滤。上述代码并未修改原始数据框。filter(Sex = "male") 是一个常见错误(Hugo 也犯过同样的错!);这里有一份很棒的tidyverse 错误指南。

# Filter to get all "female" rows
passengers %>%
  filter(Sex == "female")

##   PassengerId Survived Pclass
## 1           2        1      1
## 2           3        1      3
## 3           4        1      1
## 4           9        1      3
## 5          10        1      2
## 6          11        1      3
##                                                  Name    Sex Age SibSp
## 1 Cumings, Mrs. John Bradley (Florence Briggs Thayer) female  38     1
## 2                              Heikkinen, Miss. Laina female  26     0
## 3        Futrelle, Mrs. Jacques Heath (Lily May Peel) female  35     1
## 4   Johnson, Mrs. Oscar W (Elisabeth Vilhelmina Berg) female  27     0
## 5                 Nasser, Mrs. Nicholas (Adele Achem) female  14     1
## 6                     Sandstrom, Miss. Marguerite Rut female   4     1
##   Parch           Ticket    Fare Cabin Embarked
## 1     0         PC 17599 71.2833   C85        C
## 2     0 STON/O2. 3101282  7.9250              S
## 3     0           113803 53.1000  C123        S
## 4     2           347742 11.1333              S
## 5     0           237736 30.0708              C
## 6     1          PP 9549 16.7000    G6        S

从直观上看,女性似乎更有可能在泰坦尼克号灾难中幸存。

在探索数据时,您应尽可能提出并回答自己感兴趣的问题!现在,您可能想按 Fare 从低到高来 arrange() 观测,看看能否发现一些趋势。可使用 arrange() 动词实现:

# Arrange by increasing Fare
passengers %>%
  arrange(Fare)

##   PassengerId Survived Pclass                            Name  Sex Age
## 1         180        0      3             Leonard, Mr. Lionel male  36
## 2         264        0      1           Harrison, Mr. William male  40
## 3         272        1      3    Tornquist, Mr. William Henry male  25
## 4         278        0      2     Parkes, Mr. Francis "Frank" male  NA
## 5         303        0      3 Johnson, Mr. William Cahoone Jr male  19
## 6         414        0      2  Cunningham, Mr. Alfred Fleming male  NA
##   SibSp Parch Ticket Fare Cabin Embarked
## 1     0     0   LINE    0              S
## 2     0     0 112059    0   B94        S
## 3     0     0   LINE    0              S
## 4     0     0 239853    0              S
## 5     0     0   LINE    0              S
## 6     0     0 239853    0              S

许多付费较少的人没有幸存。仅通过重新排序数据,您就发现了一个有趣的现象!

您也可以按 Fare 从高到低 arrange:

# Arrange by decreasing Fare
passengers %>%
  arrange(desc(Fare))

##   PassengerId Survived Pclass                               Name    Sex
## 1         259        1      1                   Ward, Miss. Anna female
## 2         680        1      1 Cardeza, Mr. Thomas Drake Martinez   male
## 3         738        1      1             Lesurer, Mr. Gustave J   male
## 4          28        0      1     Fortune, Mr. Charles Alexander   male
## 5          89        1      1         Fortune, Miss. Mabel Helen female
## 6         342        1      1     Fortune, Miss. Alice Elizabeth female
##   Age SibSp Parch   Ticket     Fare       Cabin Embarked
## 1  35     0     0 PC 17755 512.3292                    C
## 2  36     0     1 PC 17755 512.3292 B51 B53 B55        C
## 3  35     0     0 PC 17755 512.3292        B101        C
## 4  19     3     2    19950 263.0000 C23 C25 C27        S
## 5  23     3     2    19950 263.0000 C23 C25 C27        S
## 6  24     3     2    19950 263.0000 C23 C25 C27        S

确实在高价一端有更多幸存者!

有时您可能需要创建新变量。您知道 Parch 表示父母与子女的数量,SibSp 表示兄弟姐妹与配偶的数量。您可以将它们相加得到新变量 FamSize。这属于特征工程,而特征工程在机器学习中经常占很大比重!

现在,要创建新变量,您可以将原变量 mutate() 成新变量。

# Create new column FamSize (size of family)
passengers %>%
  mutate(FamSize = Parch + SibSp)

##   PassengerId Survived Pclass
## 1           1        0      3
## 2           2        1      1
## 3           3        1      3
## 4           4        1      1
## 5           5        0      3
## 6           6        0      3
##                                                  Name    Sex Age SibSp
## 1                             Braund, Mr. Owen Harris   male  22     1
## 2 Cumings, Mrs. John Bradley (Florence Briggs Thayer) female  38     1
## 3                              Heikkinen, Miss. Laina female  26     0
## 4        Futrelle, Mrs. Jacques Heath (Lily May Peel) female  35     1
## 5                            Allen, Mr. William Henry   male  35     0
## 6                                    Moran, Mr. James   male  NA     0
##   Parch           Ticket    Fare Cabin Embarked FamSize
## 1     0        A/5 21171  7.2500              S       1
## 2     0         PC 17599 71.2833   C85        C       1
## 3     0 STON/O2. 3101282  7.9250              S       0
## 4     0           113803 53.1000  C123        S       1
## 5     0           373450  8.0500              S       0
## 6     0           330877  8.4583              Q       0

注意,mutate() 既可用于创建新列,也可用于修改已有列,有点类似生物学意义上的“突变”。这并不完全贴切,但有助于理解这个动词的命名。

有了这个额外变量,您可以继续发问,例如:“大家庭是否更不容易幸存?”

为检验该假设,如上所示将 Parch 与 SibSp 相加创建新变量 FamSize,然后按 FamSize 从高到低排序:

# Create new column FamSize (size of family)
# Arrange by decreasing FamSize
passengers %>%
  mutate(FamSize = Parch + SibSp) %>%
  arrange(desc(FamSize))

##   PassengerId Survived Pclass                         Name    Sex Age
## 1         160        0      3   Sage, Master. Thomas Henry   male  NA
## 2         181        0      3 Sage, Miss. Constance Gladys female  NA
## 3         202        0      3          Sage, Mr. Frederick   male  NA
## 4         325        0      3     Sage, Mr. George John Jr   male  NA
## 5         793        0      3      Sage, Miss. Stella Anna female  NA
## 6         847        0      3     Sage, Mr. Douglas Bullen   male  NA
##   SibSp Parch   Ticket  Fare Cabin Embarked FamSize
## 1     8     2 CA. 2343 69.55              S      10
## 2     8     2 CA. 2343 69.55              S      10
## 3     8     2 CA. 2343 69.55              S      10
## 4     8     2 CA. 2343 69.55              S      10
## 5     8     2 CA. 2343 69.55              S      10
## 6     8     2 CA. 2343 69.55              S      10

排在最前的大家庭成员无一幸存!这可能具有启发性:也许大家庭更难及时从泰坦尼克号撤离。

不过,0 和 1 往往不够直观,不如将 Survived 变量的数值变换为字符串 No 和 Yes(并创建新数据框!):

# Turn numerical values of Survived column to "No" & "Yes" (new data frame)
passengers1 <- passengers %>%
  mutate(Survived = ifelse(Survived == 0, "No", "Yes"))
passengers1

##   PassengerId Survived Pclass
## 1           1       No      3
## 2           2      Yes      1
## 3           3      Yes      3
## 4           4      Yes      1
## 5           5       No      3
## 6           6       No      3
##                                                  Name    Sex Age SibSp
## 1                             Braund, Mr. Owen Harris   male  22     1
## 2 Cumings, Mrs. John Bradley (Florence Briggs Thayer) female  38     1
## 3                              Heikkinen, Miss. Laina female  26     0
## 4        Futrelle, Mrs. Jacques Heath (Lily May Peel) female  35     1
## 5                            Allen, Mr. William Henry   male  35     0
## 6                                    Moran, Mr. James   male  NA     0
##   Parch           Ticket    Fare Cabin Embarked
## 1     0        A/5 21171  7.2500              S
## 2     0         PC 17599 71.2833   C85        C
## 3     0 STON/O2. 3101282  7.9250              S
## 4     0           113803 53.1000  C123        S
## 5     0           373450  8.0500              S
## 6     0           330877  8.4583              Q

绘制数据图表

使用 ggplot2 作图时,您需要指定三件事:

  • 您的数据
  • 您的映射(例如,x 轴显示什么)
  • 您的图层(例如,条形图、散点图)

首先,绘制 Sex 的条形图,看看泰坦尼克号上记录的男性与女性数量:

# Plot barplot of passenger Sex
ggplot(passengers, aes(x = Sex)) +
  geom_bar()

barplot

从上图可以看出,RMS 泰坦尼克号上大约有 600 名男性和 300 名女性。

注意,aes() 函数用于将图形的 美学属性映射到数据中的变量。更多内容参见 Chester Ismay 与 Albert Y. Kim 的Modern Dive。

接下来是散点图。任一乘客的 Age 是否与其支付的 Fare 有相关性?

# Scatter plot of Age vs Fare
ggplot(passengers, aes(x = Age, y = Fare)) +
  geom_point()

## Warning: Removed 177 rows containing missing values (geom_point).

scatter plot

仅从这一个图中,您就获得了许多洞见!您会看到,许多支付更高票价的人年龄也更大。票价可能会随年龄增加……此外,图中上方有两个离群点,值得进一步调查!

您可以像读句子一样阅读 ggplot2 代码,与上面的 dplyr 代码相同:“取 titanic 数据,将 Age 映射到 x 轴,将 Fare 映射到 y 轴,并添加点作为图层。”

我们在前图的基础上,按 Sex 给每个点着色,看看 Sex、Age 与 Fare 之间是否存在相关性:

# Scatter plot of Age vs Fare colored by Sex
ggplot(passengers %>% drop_na(), aes(x = Age, y = Fare, color = Sex)) +
  geom_point()

scatter plot 2

您会看到,底部付费较少的多为男性。图中上方还有一簇女性,她们年龄稍大,并且为登船支付了更高票价。

在一张图上可视化三个变量(两个数值变量 Age 与 Fare,以及一个分类型变量 Sex)已经很酷了,但如果想把 Survived 也纳入其中,看看是否出现明显趋势呢?可以使用分面(faceting),它可以同时生成多个图:

# Scatter plot of Age vs Fare colored by Sex faceted by Survived
ggplot(passengers1, aes(x = Age, y = Fare, color = Sex)) +
  geom_point() +
  facet_grid(~Survived)

## Warning: Removed 177 rows containing missing values (geom_point).

scatter plot 3

您会突然发现,前一个图中那些位于上方的许多女性都幸存了,而未幸存者大多支付的票价低于 50 单位。提示:试着自己查一查货币的单位!

现在我们重做按乘客 Sex 的条形图,这次按 Survived 填充条形:

# Plot barplot of passenger Sex & fill according to Survival
ggplot(passengers1, aes(x = Sex, fill = Survived)) +
  geom_bar()

bar plot 2

可以看到,绝大多数男性未能幸存,而女性中有超过三分之二幸存!

汇总与分组数据

使用 summarise() 动词求出平均票价:

# Check out mean Fare
passengers %>%
  summarise(meanFare = mean(Fare))

##   meanFare
## 1 32.20421

使用 summarise() 动词求出票价中位数:

# Check out mean Fare
passengers %>%
  summarise(medianFare = median(Fare))

##   medianFare
## 1    14.4542

您也可以结合使用 filter() 与 summarise() 求出男性的平均票价:

# Check out mean Fare for men
passengers %>%
  filter(Sex == "male") %>%
  summarise(meanFare = mean(Fare))

##   meanFare
## 1 25.52389

使用 filter() 与 summarise() 求出女性的平均票价:

# Check out mean Fare for women
passengers %>%
  filter(Sex == "female") %>%
  summarise(meanFare = mean(Fare))

##   meanFare
## 1 44.47982

使用 filter() 与 summarise() 求出女性的平均票价以及女性幸存人数:

# Check out mean Fare & number of survivors for women
passengers %>%
  filter(Sex == "female") %>%
  summarise(meanFare = mean(Fare), numSurv = sum(Survived))

##   meanFare numSurv
## 1 44.47982     233

使用 group_by() 与 summarise() 求出按性别分组的平均票价与幸存人数:

# Check out mean Fare & number of survivors grouped by Sex
passengers %>%
  group_by(Sex) %>%
  summarise(meanFare = mean(Fare), numSurv = sum(Survived))

## # A tibble: 2 x 3
##   Sex    meanFare numSurv
##   <fct>     <dbl>   <int>
## 1 female     44.5     233
## 2 male       25.5     109

使用 group_by() 与 summarise() 求出按性别分组的平均票价与幸存者比例:

# Check out mean Fare & proportion of survivors grouped by Sex
passengers %>%
  group_by(Sex) %>%
  summarise(meanFare = mean(Fare), numSurv = sum(Survived)/n())

## # A tibble: 2 x 3
##   Sex    meanFare numSurv
##   <fct>     <dbl>   <dbl>
## 1 female     44.5   0.742
## 2 male       25.5   0.189

结语

在本教程中,您从零到一掌握了使用 tidyverse 和整洁工具进行数据分析的基础。您学习了如何用 dplyr 和 ggplot2 对数据进行 filter()、arrange()、mutate()、绘图与 summarise(),并以符合您思考和表达方式的代码来完成。恭喜您。建议您继续学习 David Robinson 的 Introduction to Tidyverse 课程,并将这些工具应用到您感兴趣的其他数据集上。欢迎在推特上与我们分享您的分析:@DataCamp 和 @hugobowne。感谢阅读。

主题