tidyverse初认识

1 第一题 编写代码

利用nycflights13包的flights数据集是2013年从纽约三大机场(JFK、LGA、EWR)起飞的所有航班的准点数据,共336776条记录。

  • 计算纽约三大机场2013起飞航班数和平均延误时间(可使用group_by, summarise函数)

    flights
    # A tibble: 336,776 × 19
        year month   day dep_time sched_dep_time dep_delay arr_time sched_arr_time
       <int> <int> <int>    <int>          <int>     <dbl>    <int>          <int>
     1  2013     1     1      517            515         2      830            819
     2  2013     1     1      533            529         4      850            830
     3  2013     1     1      542            540         2      923            850
     4  2013     1     1      544            545        -1     1004           1022
     5  2013     1     1      554            600        -6      812            837
     6  2013     1     1      554            558        -4      740            728
     7  2013     1     1      555            600        -5      913            854
     8  2013     1     1      557            600        -3      709            723
     9  2013     1     1      557            600        -3      838            846
    10  2013     1     1      558            600        -2      753            745
    # ℹ 336,766 more rows
    # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
    #   tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
    #   hour <dbl>, minute <dbl>, time_hour <dttm>
    ?flights
    starting httpd help server ... done
    flights|>
      group_by(origin)|>
      summarise(n=n(),depm=mean(dep_delay,na.rm=T))
    # A tibble: 3 × 3
      origin      n  depm
      <chr>   <int> <dbl>
    1 EWR    120835  15.1
    2 JFK    111279  12.1
    3 LGA    104662  10.3
  • 计算不同航空公司2013从纽约起飞航班数和平均延误时间

    flights|>
      group_by(carrier)|>
      summarise(n=n(),depm=mean(dep_delay,na.rm=T))|>
      arrange(desc(n))
    # A tibble: 16 × 3
       carrier     n  depm
       <chr>   <int> <dbl>
     1 UA      58665 12.1 
     2 B6      54635 13.0 
     3 EV      54173 20.0 
     4 DL      48110  9.26
     5 AA      32729  8.59
     6 MQ      26397 10.6 
     7 US      20536  3.78
     8 9E      18460 16.7 
     9 WN      12275 17.7 
    10 VX       5162 12.9 
    11 FL       3260 18.7 
    12 AS        714  5.80
    13 F9        685 20.2 
    14 YV        601 19.0 
    15 HA        342  4.90
    16 OO         32 12.6 
  • 计算纽约三大机场排名前三个目的地和平均飞行距离(可使用group_by, summarise, arrange, slice_max函数)

    flights|>
      group_by(origin,dest)|>
      summarise(n=n(),distm=mean(distance))|>
      slice_max(n,n=3)
    `summarise()` has grouped output by 'origin'. You can override using the
    `.groups` argument.
    # A tibble: 9 × 4
    # Groups:   origin [3]
      origin dest      n distm
      <chr>  <chr> <int> <dbl>
    1 EWR    ORD    6100   719
    2 EWR    BOS    5327   200
    3 EWR    SFO    5127  2565
    4 JFK    LAX   11262  2475
    5 JFK    SFO    8204  2586
    6 JFK    BOS    5898   187
    7 LGA    ATL   10263   762
    8 LGA    ORD    8857   733
    9 LGA    CLT    6168   544

2 第二题 解释代码

  1. 代码含义:使用R语言中的dplyr包对iris数据集进行操作。iris是R中自带的一个经典数据集,包含了150个样本的鸢尾花(Iris)的测量数据,包括花萼长度(Sepal.Length)、花萼宽度(Sepal.Width)、花瓣长度(Petal.Length)、花瓣宽度(Petal.Width)以及鸢尾花的种类(Species)。
  • tibble()函数将iris数据集转换为一个tibble对象。tibbledata.frame的现代版本,提供了更好的打印和子集操作功能。这里tibble(iris)iris数据集转换为tibble格式。

  • %>%: 是管道操作符,来自magrittr包(dplyr包中也包含了这个操作符)在这个例子中,tibble(iris)的输出被传递给arrange()函数。

  • arrange()函数用于对数据进行排序。

  • Species是排序的第一个依据,表示按照鸢尾花的种类(Species)进行升序排序。

  • across(starts_with("Sepal"), desc)是排序的第二个依据:

    • starts_with("Sepal")选择所有以"Sepal"开头的列(即Sepal.LengthSepal.Width)。

    • desc()表示对这些列进行降序排序。

    • across()函数用于对多个列应用相同的操作,这里是对所有以"Sepal"开头的列进行降序排序。

tibble(iris) %>% 
  arrange(Species,across(starts_with("Sepal"), desc))
# A tibble: 150 × 5
   Sepal.Length Sepal.Width Petal.Length Petal.Width Species
          <dbl>       <dbl>        <dbl>       <dbl> <fct>  
 1          5.8         4            1.2         0.2 setosa 
 2          5.7         4.4          1.5         0.4 setosa 
 3          5.7         3.8          1.7         0.3 setosa 
 4          5.5         4.2          1.4         0.2 setosa 
 5          5.5         3.5          1.3         0.2 setosa 
 6          5.4         3.9          1.7         0.4 setosa 
 7          5.4         3.9          1.3         0.4 setosa 
 8          5.4         3.7          1.5         0.2 setosa 
 9          5.4         3.4          1.7         0.2 setosa 
10          5.4         3.4          1.5         0.4 setosa 
# ℹ 140 more rows
  1. 代码含义:使用R语言中的dplyr包对starwars数据集进行操作,
  • group_by(gender): 用于对数据进行分组。按照gender列(性别)对数据进行分组。分组后,后续的操作(如filter())会分别对每个性别组进行。

  • filter(mass > mean(mass, na.rm = TRUE)): 用于筛选满足条件的行。这里的条件是mass > mean(mass, na.rm = TRUE)mean(mass, na.rm = TRUE)计算每个性别组中mass列(体重)的平均值,na.rm = TRUE表示忽略缺失值(NA)。mass > mean(mass, na.rm = TRUE)筛选出体重大于该组平均体重的角色。

starwars %>% 
  group_by(gender) %>% 
  filter(mass > mean(mass, na.rm = TRUE))
# A tibble: 15 × 14
# Groups:   gender [3]
   name    height   mass hair_color skin_color eye_color birth_year sex   gender
   <chr>    <int>  <dbl> <chr>      <chr>      <chr>          <dbl> <chr> <chr> 
 1 Darth …    202  136   none       white      yellow          41.9 male  mascu…
 2 Owen L…    178  120   brown, gr… light      blue            52   male  mascu…
 3 Beru W…    165   75   brown      light      blue            47   fema… femin…
 4 Chewba…    228  112   brown      unknown    blue           200   male  mascu…
 5 Jabba …    175 1358   <NA>       green-tan… orange         600   herm… mascu…
 6 Jek To…    180  110   brown      fair       blue            NA   <NA>  <NA>  
 7 IG-88      200  140   none       metal      red             15   none  mascu…
 8 Bossk      190  113   none       green      red             53   male  mascu…
 9 Ayla S…    178   55   none       blue       hazel           48   fema… femin…
10 Gregar…    185   85   black      dark       brown           NA   <NA>  <NA>  
11 Lumina…    170   56.2 black      yellow     blue            58   fema… femin…
12 Zam We…    168   55   blonde     fair, gre… yellow          NA   fema… femin…
13 Shaak …    178   57   none       red, blue… black           NA   fema… femin…
14 Grievo…    216  159   none       brown, wh… green, y…       NA   male  mascu…
15 Tarfful    234  136   brown      brown      blue            NA   male  mascu…
# ℹ 5 more variables: homeworld <chr>, species <chr>, films <list>,
#   vehicles <list>, starships <list>

3.代码含义:使用的dplyr包对starwars数据集进行操作。starwarsdplyr包中自带的一个数据集,包含了《星球大战》系列电影中的角色信息,包括姓名、家乡、物种等信息。

  • select(name, homeworld, species):用于选择数据集中的特定列。选择了name(姓名)、homeworld(家乡)和species(物种)三列。

  • mutate(across(!name, as.factor)): 用于对数据集进行列操作(添加新列或修改现有列)。across()函数用于对多列应用相同的操作。!name表示对除了name列以外的所有列(即homeworldspecies)进行操作。as.factor()将指定的列转换为因子(factor)类型。因子是R中用于表示分类变量的数据类型。

starwars %>%
  select(name, homeworld, species) %>%
  mutate(across(!name, as.factor))
# A tibble: 87 × 3
   name               homeworld species
   <chr>              <fct>     <fct>  
 1 Luke Skywalker     Tatooine  Human  
 2 C-3PO              Tatooine  Droid  
 3 R2-D2              Naboo     Droid  
 4 Darth Vader        Tatooine  Human  
 5 Leia Organa        Alderaan  Human  
 6 Owen Lars          Tatooine  Human  
 7 Beru Whitesun Lars Tatooine  Human  
 8 R5-D4              Tatooine  Droid  
 9 Biggs Darklighter  Tatooine  Human  
10 Obi-Wan Kenobi     Stewjon   Human  
# ℹ 77 more rows

4.代码含义:使用R语言中的dplyr包对mtcars数据集进行操作。mtcars是R中自带的一个经典数据集,包含了32辆汽车的性能数据,包括马力(hp)、发动机类型(vs)等信息。

  • group_by(vs):数用于对数据进行分组。这里按照vs列(发动机类型,0表示V型发动机,1表示直列发动机)对数据进行分组。

  • mutate(hp_cut = cut(hp, 3)): mutate()函数用于添加新列或修改现有列cut(hp, 3)hp列(马力)的值分成3个区间(即等宽分箱),并将每个值分配到对应的区间中。hp_cut是新创建的列,存储了hp列的分箱结果。

  • group_by(hp_cut): 再次使用group_by()函数,这次是按照hp_cut列(马力分箱结果)对数据进行分组。

tibble(mtcars) %>%
  group_by(vs) %>%
  mutate(hp_cut = cut(hp, 3)) %>%
  group_by(hp_cut)
# A tibble: 32 × 12
# Groups:   hp_cut [6]
     mpg   cyl  disp    hp  drat    wt  qsec    vs    am  gear  carb hp_cut     
   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <fct>      
 1  21       6  160    110  3.9   2.62  16.5     0     1     4     4 (90.8,172] 
 2  21       6  160    110  3.9   2.88  17.0     0     1     4     4 (90.8,172] 
 3  22.8     4  108     93  3.85  2.32  18.6     1     1     4     1 (75.7,99.3]
 4  21.4     6  258    110  3.08  3.22  19.4     1     0     3     1 (99.3,123] 
 5  18.7     8  360    175  3.15  3.44  17.0     0     0     3     2 (172,254]  
 6  18.1     6  225    105  2.76  3.46  20.2     1     0     3     1 (99.3,123] 
 7  14.3     8  360    245  3.21  3.57  15.8     0     0     3     4 (172,254]  
 8  24.4     4  147.    62  3.69  3.19  20       1     0     4     2 (51.9,75.7]
 9  22.8     4  141.    95  3.92  3.15  22.9     1     0     4     2 (75.7,99.3]
10  19.2     6  168.   123  3.92  3.44  18.3     1     0     4     4 (99.3,123] 
# ℹ 22 more rows

3 第三题 查找帮助理解函数

阅读 https://dplyr.tidyverse.org/reference/mutate-joins.html 内容,说明4个数据集链接函数函数的作用。分别举一个实际例子演示并解释其输出结果。

3.1 1. inner_join():学生成绩与课程信息匹配

加载两个数据集,一个包含学生的成绩,另一个包含课程信息,保留那些既有成绩又有课程信息的学生记录。从输出结果可知,只有course_id101102的课程在gradescourses中都存在。结果中只保留了这些匹配的记录,course_id103104的记录被丢弃。

library(dplyr)

# 学生成绩数据集
grades <- tibble(
  student_id = c(1, 2, 3, 4),
  course_id = c(101, 102, 103, 104),
  grade = c("A", "B", "C", "A")
)

# 课程信息数据集
courses <- tibble(
  course_id = c(101, 102, 105),
  course_name = c("Math", "Science", "History")
)

# 内部链接
result <- inner_join(grades, courses, by = "course_id")
print(result)
# A tibble: 2 × 4
  student_id course_id grade course_name
       <dbl>     <dbl> <chr> <chr>      
1          1       101 A     Math       
2          2       102 B     Science    

3.2 2.left_join():员工信息与部门信息合并

加载一个员工信息数据集和一个部门信息数据集,保留所有员工信息,并将匹配的部门信息合并到员工信息中。所有员工信息都被保留。dept_id101102的部门信息与员工信息匹配,因此合并到结果中。dept_id103104的部门在departments中不存在,因此dept_name列的值为NA

# 员工信息数据集
employees <- tibble(
  employee_id = c(1, 2, 3, 4),
  name = c("Alice", "Bob", "Charlie", "David"),
  dept_id = c(101, 102, 103, 104)
)

# 部门信息数据集
departments <- tibble(
  dept_id = c(101, 102, 105),
  dept_name = c("HR", "Finance", "IT")
)

# 左外部链接
result <- left_join(employees, departments, by = "dept_id")
print(result)
# A tibble: 4 × 4
  employee_id name    dept_id dept_name
        <dbl> <chr>     <dbl> <chr>    
1           1 Alice       101 HR       
2           2 Bob         102 Finance  
3           3 Charlie     103 <NA>     
4           4 David       104 <NA>     
# 使用 left_join 进行连接
result <- left_join(employees, departments, by = "dept_id")

# 查看结果
print(result)
# A tibble: 4 × 4
  employee_id name    dept_id dept_name
        <dbl> <chr>     <dbl> <chr>    
1           1 Alice       101 HR       
2           2 Bob         102 Finance  
3           3 Charlie     103 <NA>     
4           4 David       104 <NA>     

3.3 3. right_join():订单信息与客户信息合并

加载一个订单信息数据集和一个客户信息数据集,保留所有客户信息,并将匹配的订单信息合并到客户信息中。所有客户信息都被保留。customer_id101102的订单信息与客户信息匹配,因此合并到结果中。customer_id104的客户在orders中没有订单,因此order_idamount列的值为NA

library(dplyr)

# 创建数据框
orders <- tibble(
  order_id = c(1, 2, 3, 4),
  customer_id = c(101, 102, 103, 104),
  product = c("Laptop", "Smartphone", "Tablet", "Headphones")
)

customers <- tibble(
  customer_id = c(101, 102, 104, 105),
  name = c("Alice", "Bob", "David", "Charlie")
)

# 使用 right_join 进行连接
result <- right_join(orders, customers, by = "customer_id")

# 查看结果
print(result)
# A tibble: 4 × 4
  order_id customer_id product    name   
     <dbl>       <dbl> <chr>      <chr>  
1        1         101 Laptop     Alice  
2        2         102 Smartphone Bob    
3        4         104 Headphones David  
4       NA         105 <NA>       Charlie

3.4 4. full_join():产品信息与销售记录合并

加载一个产品信息数据集和一个销售记录数据集,保留所有产品和销售记录,并将匹配的信息合并。所有产品和销售记录都被保留。product_id23的产品和销售记录匹配,因此合并到结果中。product_id1的产品没有销售记录,因此quantity列的值为NAproduct_id4的销售记录没有产品信息,因此product_name列的值为NA

library(dplyr)

# 创建数据框
employees <- tibble(
  emp_id = c(1, 2, 3, 4),
  name = c("Alice", "Bob", "Charlie", "David")
)

projects <- tibble(
  project_id = c(101, 102, 103, 104),
  emp_id = c(1, 2, 4, 5),
  project_name = c("Project A", "Project B", "Project C", "Project D")
)

# 使用 full_join 进行连接
result <- full_join(employees, projects, by = "emp_id")

# 查看结果
print(result)
# A tibble: 5 × 4
  emp_id name    project_id project_name
   <dbl> <chr>        <dbl> <chr>       
1      1 Alice          101 Project A   
2      2 Bob            102 Project B   
3      3 Charlie         NA <NA>        
4      4 David          103 Project C   
5      5 <NA>           104 Project D