R Academy · 课时

dplyr 中的多表连接

掌握 inner_join、left_join、right_join、full_join 和 anti_join

第 3 / 4 课13 个步骤

dplyr 中的多表连接 是 CoddyKit 上的免费 R Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 R Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 R Academy 课程共包含 4 节课。

为什么要连接表?

真实数据很少只存放在一张表中。关系数据库会将信息拆分到多张表中,以避免重复。连接可以根据共享键合并表。dplyr 提供了采用 SQL 风格连接函数的简洁、易读语法。

library(dplyr)

# Two related tables
orders <- data.frame(
  order_id = 1:4,
  customer_id = c(1, 2, 1, 3),
  amount = c(250, 180, 320, 90)
)

customers <- data.frame(
  customer_id = 1:3,
  name = c('Alice','Bob','Carol'),
  city = c('NYC','LA','Chicago')
)

print(orders)
print(customers)

inner_join() — 仅保留匹配的行

inner_join(x, y, by='key')只返回键同时存在于两张表中的行。在另一张表中没有匹配项的行会被删除。这是最常用的连接类型。

library(dplyr)

orders <- data.frame(
  order_id = 1:4,
  customer_id = c(1, 2, 1, 99),
  amount = c(250, 180, 320, 90)
)

customers <- data.frame(
  customer_id = c(1, 2, 3),
  name = c('Alice','Bob','Carol')
)

# customer_id = 99 in orders has no match => dropped
# customer_id = 3 in customers has no match => dropped
inner_join(orders, customers, by = 'customer_id')

left_join() — 保留左表的所有行

left_join(x, y, by='key')保留x 中的所有行,并填入 y 中匹配的数据。x 中在 y 里没有匹配项的行,其 y 列会得到 NA。结果由左表决定。

library(dplyr)

orders <- data.frame(
  order_id = 1:4,
  customer_id = c(1, 2, 1, 99),
  amount = c(250, 180, 320, 90)
)

customers <- data.frame(
  customer_id = c(1, 2, 3),
  name = c('Alice','Bob','Carol')
)

# Order with customer_id=99 is kept, name = NA
left_join(orders, customers, by = 'customer_id')

right_join() — 保留右表的所有行

right_join(x, y, by='key')保留y 中的所有行。y 中在 x 里没有匹配项的行,其 x 列会得到 NA。它与 left_join()正好相反——由于可以交换表的顺序,因此使用得较少。

library(dplyr)

orders <- data.frame(
  order_id = c(1, 2),
  customer_id = c(1, 2),
  amount = c(250, 180)
)

customers <- data.frame(
  customer_id = c(1, 2, 3),
  name = c('Alice','Bob','Carol')
)

# Carol (customer_id=3) has no orders => NA for order columns
right_join(orders, customers, by = 'customer_id')

full_join() — 保留所有行

full_join(x, y, by='key')保留两张表中的每一行。任一方中没有匹配项的行,其另一张表的列会得到 NA。当不能接受丢失任何数据时,请使用它。

library(dplyr)

q1 <- data.frame(product = c('A','B','C'), q1_sales = c(100, 200, 150))
q2 <- data.frame(product = c('A','C','D'), q2_sales = c(120, 160, 90))

# D appears only in q2, B only in q1 => both kept
full_join(q1, q2, by = 'product')

anti_join() — 查找不匹配项

anti_join(x, y, by='key')返回 x 中在 y 里没有匹配项的行。结果不包含 y 的任何列。它非常适合查找孤立记录、未匹配的订单,或参考表中缺失的项目。

library(dplyr)

all_employees <- data.frame(
  id = 1:5,
  name = c('Alice','Bob','Carol','Dave','Eve')
)

trained <- data.frame(id = c(1, 3, 5))

# Who has NOT completed training?
anti_join(all_employees, trained, by = 'id')

semi_join() — 按匹配项筛选

semi_join(x, y, by='key')返回 x 中在 y 里有匹配项的行,但不会添加 y 的列。它类似于 inner_join(),但只返回 x 的列,因此适合作为筛选步骤。

library(dplyr)

products <- data.frame(
  id = 1:5,
  name = c('Widget','Gadget','Donut','Gizmo','Sprocket'),
  price = c(9.99, 24.99, 1.99, 14.99, 4.99)
)

ordered_products <- data.frame(id = c(1, 3, 5))

# Products that appear in at least one order
semi_join(products, ordered_products, by = 'id')

按不同的列名连接

当 x 和 y 中的键列名称不同时,请使用 by = c('x_col' = 'y_col')语法。它会将左表中的列名映射到右表中对应的列。

library(dplyr)

orders <- data.frame(
  order_id = 1:3,
  user_id = c(10, 20, 10),
  amount = c(100, 200, 150)
)

users <- data.frame(
  id = c(10, 20, 30),
  username = c('alice','bob','carol')
)

# orders.user_id matches users.id
left_join(orders, users, by = c('user_id' = 'id'))

按多个键连接

您可以将向量传递给 by,以便按多个列进行连接。指定的所有列都必须匹配,行才会被连接。这适用于没有任何单列具备唯一性的复合键。

library(dplyr)

actual <- data.frame(
  year = c(2023, 2023, 2024, 2024),
  quarter = c('Q1','Q2','Q1','Q2'),
  sales = c(100, 120, 130, 150)
)

target <- data.frame(
  year = c(2023, 2023, 2024, 2024),
  quarter = c('Q1','Q2','Q1','Q2'),
  target = c(110, 115, 125, 145)
)

inner_join(actual, target, by = c('year', 'quarter'))

串联多个连接

您可以使用管道运算符,在一个管道中串联多个连接。逐步添加多个查找表中的信息,构建一个反规范化视图。

library(dplyr)

orders <- data.frame(order_id=1:3, cust_id=c(1,2,1), prod_id=c(10,10,20))
customers <- data.frame(cust_id=1:2, name=c('Alice','Bob'))
products <- data.frame(prod_id=c(10,20), product=c('Widget','Gadget'))

orders %>%
  left_join(customers, by = 'cust_id') %>%
  left_join(products, by = 'prod_id')

处理重复列

当两张表包含同名列(连接键除外)时,dplyr 会添加 .x 和 .y 后缀。您可以使用 suffix 参数自定义这些后缀,然后根据需要选择或重命名列。

library(dplyr)

current <- data.frame(id=1:3, value=c(10,20,30), date=Sys.Date())
historic <- data.frame(id=1:3, value=c(8,22,28), date=Sys.Date()-365)

# Both have 'value' and 'date' columns
result <- inner_join(current, historic, by='id',
                     suffix=c('_current','_historic'))
print(names(result))

快速检查

dplyr 的哪个连接函数只返回左表中在右表没有匹配行的行?

回顾:dplyr 连接

使用 dplyr 连接多张表的要点:

  • inner_join() — 两张表中都匹配的行
  • left_join() — 左表的所有行;右表没有匹配项时为 NA
  • right_join() — 右表的所有行;左表没有匹配项时为 NA
  • full_join() — 两张表的所有行;没有匹配项时为 NA
  • anti_join() — x 中在 y 里没有匹配项的行(筛选工具)
  • semi_join() — x 中在 y 里有匹配项的行(筛选工具)
  • 列名不同时使用 by = c('x_col' = 'y_col')
  • 复合键使用向量:by = c('year', 'quarter')
library(dplyr)

# Chain of joins: the typical real-world pattern
orders <- data.frame(oid=1:3, cid=c(1,2,1), pid=c(10,20,10))
customers <- data.frame(cid=1:2, name=c('Alice','Bob'))
products <- data.frame(pid=c(10,20), name=c('Widget','Gadget'), price=c(9.99,19.99))

orders %>%
  inner_join(customers, by='cid') %>%
  inner_join(products, by='pid', suffix=c('','_product')) %>%
  select(oid, name, name_product, price)
免费开始

用 AI 导师学习 R — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
43
课程
159

常见问题解答

「dplyr 中的多表连接」课时是免费的吗?

是的 — 「dplyr 中的多表连接」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 R Academy 课程的其余内容,请升级到 CoddyKit PRO。 R Academy 课程共包含 4 节课。

「dplyr 中的多表连接」这节课中我会学到什么?

掌握 inner_join、left_join、right_join、full_join 和 anti_join 你通过在浏览器中直接运行的动手代码来练习 R Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 R Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 R Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。

「dplyr 中的多表连接」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 R Academy 课中编写并运行代码吗?

能。每节 R Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 分组汇总与 group_by()
  2. 窗口函数:lag、lead、cumsum
  3. dplyr 中的多表连接
  4. 整洁求值:{{ }} 与 .data
← 返回 R Academy