跳至内容
R
数据科学

如何在 R 中进行子集操作:选择、筛选与提取数据

学习使用括号 []、subset() 和 dplyr 在 R 中对子集数据框。包含代码示例与方法对比。
DataCamp Team's photo
DataCamp Team
已更新 · 6分钟 阅读

使用 AI 探索

ChatGPTClaudePerplexity

创建您的免费账户

实践并学习路径你的进步。

使用 Google 继续
继续操作即表示您接受我们的《使用条款》和《隐私政策》,并同意您的数据存储在美国。

几乎所有 R 数据分析项目都会涉及从更大的数据集中提取特定的行、列或数值。子集操作是在 R 中实现这一点的方式:使用括号表示法 [] 进行底层索引控制,使用 subset() 基于条件进行可读性强的筛选,或使用 dplyr 中的 filter() 和 select() 等动词构建现代数据管道。

要点速览

  • 使用括号表示法 df[rows, cols] 按位置对行和列进行子集选择

  • 使用 $ 提取单列为向量:df$column_name

  • 在交互式会话中,使用 subset(df, condition) 进行可读的条件筛选

  • 在选择单列且希望结果保持为数据框时,添加 drop = FALSE

  • 在生产代码和数据管道中,优先使用括号表示法或 dplyr::filter(),而非 subset()

选择行

下面是在名为 debt 的数据框上进行子集操作的示例。

debt[3:6, ]
      name  payment
3      Dan      150
4      Rob       50
5      Rob       75
6      Rob      100

df[rows, columns] 语法是 R 子集操作的基础。这里,3:6 选择第 3 到第 6 行,逗号后的空白表示“返回所有列”。结果是一个更小的数据框,列结构与原始数据相同。

从特定列选择行

当您只选择单列时,需要留意结果的“简化”行为。仅选择 payment 列的前三行会将结果简化为一个向量。

debt[1:3, 2]
100 200 150

这里的 2 指的是 debt 的第二列,即 payment。由于我们选择了单列,R 会丢弃数据框结构并返回一个普通的数值向量。

数据框格式

要将其保持为数据框,只需像下面这样添加 drop = FALSE:

debt[1:3, 2, drop = FALSE]
    payment
1       100
2       200
3       150

选择特定列

您也可以使用 $ 运算符选择单列,写作 dataframe$column。下面的示例从 debt 中提取 payment 列。R 会将结果返回为向量,而不是数据框。

debt$payment
100 200 150 50 75 100

使用 subset() 函数

当需要创建更复杂的子集或基于条件的子集时,更进一步的方法是使用 subset() 函数。比如,若您想查看名为 Dan 的人的债务。您可以直接用括号选择他的记录并求和,但这种方式不够健壮,尤其是在数据集可能发生变化的情况下。

# 这能用,但不具可读性
debt[1:3, ]

对分类变量使用 subset()

更好的做法是使用 subset() 选择 name 列等于 Dan 的行。请注意需要使用双等号(==),它被称为关系运算符。

# 这能用,但既不直观也不健壮
debt[1:3, ]

# 更加直观!
subset(debt, name == "Dan")
      name     payment
1      Dan         100
2      Dan         200
3      Dan         150

结果只包含 name 等于 "Dan" 的三行。注意原始行号(1、2、3)被保留,这有助于将结果追溯回源数据框。

对数值变量使用 subset()

我们也可以对子集进行数值条件筛选。若想查看付款额等于 $100 的行,可以这样做:

subset(debt, payment == 100)
      name  payment
1      Dan      100
6      Rob      100

有两行满足该条件:第 1 行(Dan)和第 6 行(Rob)的付款额都正好是 $100。这表明 subset() 会不受 name 影响扫描每一行并返回所有匹配项。

访问与子集化数据框

如果您只需要公司 A 的现金流怎么办?这里 subset() 函数对另一个数据框 cash 进行行筛选:

subset(cash, company == "A")
      company  cash_flow  year
1           A       1000     1
2           A       4000     3
3           A        550     4

请记住:

  • 传递给 subset() 的第一个参数是数据框名称,这里是 cash。

  • 注意不要给 company 加引号!

  • == 是相等运算符。它用于测试两个值是否相等并返回逻辑向量。

subset() 方法的交互示例

在下面的示例中,我们使用 subset() 选择 cash 中属于公司 B 的行,然后筛选出 1 年到期的现金流。

# 关于公司 B 的行
subset(cash, company == "B")

# 1 年到期的现金流
subset(cash, year == 1)

运行上述代码,会得到如下结果:

  company cash_flow year
4       B      1500    1
5       B      1100    2
6       B       750    4
7       B      6000    5
  company cash_flow year
1       A      1000    1
4       B      1500    1

在我们的“Introduction to R for Finance”课程中,亲自试一试。

本文内容摘自 DataCamp 由 Lore Dirick 授课的 Introduction to R for Finance 课程。

使用 dplyr 进行子集操作

tidyverse 套件中的 dplyr 为数据框子集操作提供了现代化替代方案。其 filter() 用于选择行,select() 用于选择列,二者都采用基于管道的语法将操作串联起来。

library(dplyr)

# 过滤 name 为 "Dan" 的行
debt %>% filter(name == "Dan")

# 仅选择 payment 列(保持为数据框)
debt %>% select(payment)

# 组合:在一条管道中同时过滤行并选择列
debt %>%
  filter(payment >= 100) %>%
  select(name, payment)

与 subset() 不同,dplyr 函数可在其他函数内部可靠运行,并能在同一管道内处理分组操作、连接与汇总。如果您在构建数据分析工作流,而非一次性查询,dplyr 是标准工具。

子集方法对比

我们用一张表来比较 R 中不同的子集方法:

方法 语法 最适合 备注
括号 [] df[rows, cols] 低层控制、编程 适用于所有 R 对象
$ df$col 快速提取单列 返回向量,而非数据框
subset() subset(df, cond) 交互式筛选 不建议在函数内部使用
dplyr::filter() df %>% filter(cond) 数据管道、可读代码 需安装 dplyr 包

总结

R 提供多种子集方式:括号表示法 [] 提供全面控制,subset() 适合可读的交互式筛选,dplyr::filter() 适合数据管道。括号适用于任何 R 对象,subset() 便于一次性探索,而 dplyr 在串联多步操作时更具扩展性。

若想更深入学习 R 的数据处理,推荐 DataCamp 的 Data Manipulation with dplyr 课程或 Introduction to the Tidyverse 课程。

R 子集操作常见问题

R 中 subset() 与 dplyr::filter() 有何区别?

两者都能基于条件筛选行,但在编程场景下行为不同。subset() 使用非标准求值,交互式使用便捷,但在用户自定义函数中不够可靠。dplyr::filter() 旨在在函数内部安全运行,并与管道运算符(%>%)集成以串联多步数据处理。

如何一次性在 R 中选择多列?

您可以在括号中传入列名或列索引的向量。例如,df[, c("name", "payment")] 按名称选择两列,而 df[, c(1, 3)] 按位置选择两列。使用 dplyr 时,可以写 select(df, name, payment),或用 starts_with() 与 contains() 等辅助函数按模式匹配列。

为何在 R 中选择单列会返回向量而非数据框?

当仅使用括号表示法选择单列时,R 会默认简化结果。该行为由参数 drop 控制,默认值为 TRUE。若要让结果保持为数据框,请在括号表达式中添加 drop = FALSE,例如 df[, 2, drop = FALSE]。

我可以根据多个条件在 R 中筛选行吗?

可以。您可以使用 &(与)和 |(或)组合条件。例如,subset(df, name == "Dan" & payment > 100) 返回 name 为 Dan 且 payment 大于 100 的行。使用 dplyr 时,可在 filter() 中用逗号分隔条件:df %>% filter(name == "Dan", payment > 100)。

主题
R
数据科学

热门 R 课程

课程

R 语言入门

4 小时
3.1M
掌握 R 数据分析基础,包括向量、列表和数据框,并用真实数据集实践 R。
查看详情开始课程

创建您的免费账户

实践并学习路径你的进步。

使用 Google 继续
继续操作即表示您接受我们的《使用条款》和《隐私政策》,并同意您的数据存储在美国。
查看更多