R 数据框:如何创建、附加、选择和子集

什么是数据框?
A 数据框 数据框是由长度相等的向量组成的列表。矩阵只能包含一种类型的数据,而数据框可以接受不同的数据类型(数值型、字符型、因子型等)。
该定义将数据框置于 R 语言中你会不断遇到的两个相邻节点之间。 矩阵 是矩形的,但只有一种类型,而且 名单 数据是多类型的,但格式混乱。数据框从每种类型中借用了一个属性。
| 结构 | 列类型 | 元素长度 | 典型用途 |
|---|---|---|---|
| 向量 | 仅一种类型 | 单序列 | 一个变量 |
| 矩阵 | 仅一种类型 | 矩形 | 数值代数 |
| 列表 | 任何类型组合 | 可能因元素而异 | 任意收集 |
| 数据框 | 任何类型组合 | 每列长度相等 | 表格分析 |
因为数据框本质上是一个列表,所以列表上使用的访问器在这里也适用,这就是为什么本教程后面会再次出现美元符号的原因。
如何创建数据框
我们可以在 R 通过将变量 a、b、c 和 d 传递给 data.frame() 函数,我们可以创建数据框并使用 names() 函数命名列,只需指定每个变量的名称即可。
data.frame(df, stringsAsFactors = TRUE)
参数:
- df:它可以是一个矩阵,转换为数据框,也可以是一组变量的集合
- 字符串作为因子控制字符向量是否转换为因子列。在旧版本中,默认值为 TRUE,而自 R 4.0.0 起为 FALSE,因此当需要明确指定行为时,请显式传递此参数。
我们可以通过组合四个相同长度的变量在 R 中为我们的第一个数据集创建一个数据框。
# Create a, b, c, d variables a <- c(10,20,30,40) b <- c('book', 'pen', 'textbook', 'pencil_case') c <- c(TRUE,FALSE,TRUE,FALSE) d <- c(2.5, 8, 10, 7) # Join the variables to create a data frame df <- data.frame(a,b,c,d) df
输出:
## a b c d ## 1 10 book TRUE 2.5 ## 2 20 pen FALSE 8.0 ## 3 30 textbook TRUE 10.0 ## 4 40 pencil_case FALSE 7.0
每个向量都成为一列,每个向量中的四个值则成为四行。需要注意的是,参数没有命名,因此 R 会根据变量名自动生成列标题。
我们可以看到列标题与变量同名。我们可以使用函数 names() 更改 R 中的列名。查看下面的 R 创建数据框示例:
# Name the data frame names(df) <- c('ID', 'items', 'store', 'price') df
输出:
## ID items store price ## 1 10 book TRUE 2.5 ## 2 20 pen FALSE 8.0 ## 3 30 textbook TRUE 10.0 ## 4 40 pencil_case FALSE 7.0
赋值给 names() 函数会一次性替换所有列标题,因此替换向量必须每列恰好包含一个条目。要重命名单个列,请对 names 向量进行索引,例如 names(df)[2] <- 'product'。
# Print the structure
str(df)
输出:
## 'data.frame': 4 obs. of 4 variables: ## $ ID : num 10 20 30 40 ## $ items: Factor w/ 4 levels "book","pen","pencil_case",..: 1 2 4 3 ## $ store: logi TRUE FALSE TRUE FALSE ## $ price: num 2.5 8 10 7
版本说明。 上述输出是在 R 4.0.0 之前的版本中生成的,该版本默认将 `data.frame()` 函数将字符向量转换为因子,因此 `items` 被报告为具有四个水平的因子。R 基础文档记录了这是出厂默认行为。 对于 R 4.0.0,已将 stringsAsFactors 设置为 FALSE。在当前版本上运行相同的代码会将数据项作为纯字符列,并且 `str()` 函数会输出 `chr` 字符。在 `data.frame()` 调用中添加 `stringsAsFactors = TRUE` 即可重现打印输出,或者阅读相关文档。 因子教程 当确实需要这些因素时。
切片数据框
框架搭建完成后,下一步就是将框架的各个部分提取出来。切片是 R 语言中实现这一目标的基本方法,它使用与向量相同的方括号,只是需要处理两个位置信息而不是一个。
可以对数据框的值进行切片。我们选择要返回的行和列,并将其放在方括号内,方括号前面加上数据框的名称。
数据框由行和列组成,df[A, B]。A 表示行,B 表示列。我们可以通过指定行和/或列来进行切片。
从下图1可以看出,左侧部分代表 行, 右边是 列. 注意符号 : 表示 至例如,1:3 表示从 1 中选择值 至 3.
下图展示了如何访问数据框的不同选项:
- 黄色箭头选择 行 1 in 栏 2
- 绿色箭头选择 行 1到2
- 红色箭头选择 栏 1
- 蓝色箭头选择 行 1年至3年以及 列 3到4
请注意,如果我们将左侧部分留空,R 将选择 所有的行以此类推,如果我们让右边的部分空白,R 会选择 所有的列.
我们可以在控制台中运行代码:
## Select row 1 in column 2
df[1,2]
输出:
## [1] book ## Levels: book pen pencil_case textbook
之所以会出现 Levels 行,是因为 items 是本次会话中的一个因子。在 R 4.0.0 及更高版本中,同样的调用会输出单个字符串“book”,而不会输出 Levels 行。
## Select Rows 1 to 2
df[1:2,]
输出:
## ID items store price ## 1 10 book TRUE 2.5 ## 2 20 pen FALSE 8.0
## Select Columns 1
df[,1]
输出:
## [1] 10 20 30 40
使用 `df[,1]` 选择单列会移除数据框包装器并返回一个普通的向量。如果需要单列数据框,可以添加 `drop = FALSE`,例如 `df[, 1, drop = FALSE]`。
## Select Rows 1 to 3 and columns 3 to 4
df[1:3, 3:4]
输出:
## store price ## 1 TRUE 2.5 ## 2 FALSE 8.0 ## 3 TRUE 10.0
也可以通过列名来选择列。例如,以下代码示例trac它有两列:ID 和 store。
# Slice with columns name df[, c('ID', 'store')]
输出:
## ID store ## 1 10 TRUE ## 2 20 FALSE ## 3 30 TRUE ## 4 40 FALSE
在生产代码中,名称比位置更安全,因为插入或重新排序列会悄无声息地改变 df[, 3] 所指的内容,而 df[, 'store'] 则始终指向相同的数据。
向数据框添加一列
你也可以向数据框中添加一列。在 R 语言中,你需要使用符号 $ 来命名新变量,然后向数据框中添加一列。
# Create a new vector quantity <- c(10, 35, 40, 5) # Add `quantity` to the `df` data frame df$quantity <- quantity df
输出:
## ID items store price quantity ## 1 10 book TRUE 2.5 10 ## 2 20 pen FALSE 8.0 35 ## 3 30 textbook TRUE 10.0 40 ## 4 40 pencil_case FALSE 7.0 5
注意:向量中的元素个数必须与数据框中的元素个数相等。在 R 中执行以下语句向数据框添加一列。
quantity <- c(10, 35, 40)
# Add `quantity` to the `df` data frame
df$quantity <- quantity
给出错误:
Error in `lt;-.data.frame`(`*tmp*`, quantity, value = c(10, 35, 40))
replacement has 3 rows, data has 4
该消息会指出数据框的替换运算符,并说明两种替换方式的计数,从而准确地告诉你需要修复什么。R 仅在替换值的长度能整除行数时才会重复使用,这就是为什么长度为 1 的值(例如 `df$currency <- 'EUR'`)会被接受,而长度为 3 的向量(对应四行数据)则会被拒绝。`cbind()` 函数以相同的方式添加列,而 `rbind()` 函数则是添加行的对应函数。
选择数据框的一列
有时,我们需要存储数据框中的某一列以供后续使用,或者对某一列执行特定操作。我们可以使用美元符号 $ 来选择数据框中的列。
# Select the column ID
df$ID
输出:
## [1] 1 2 3 4
仔细阅读输出结果。ID 由向量 c(10, 20, 30, 40) 构建而成,因此实时控制台会输出 10 20 30 40;上面显示的 1 2 3 4 是行位置,而不是存储的值。行首的 [1] 只是该行第一个元素的索引,并非数据的一部分。
三种路径都指向同一列:df$ID、df[['ID']] 和 df[, 'ID']。美元符号表示部分匹配,因此 df$I 仍然会找到 ID,这在控制台中很方便,但在已保存的脚本中却存在风险。
对数据框进行子集化
在上一节中,我们无条件地选择了整列。可以 子集 根据某个条件是否真实。
我们使用 subset() 函数。
subset(x, condition) arguments: - x: data frame used to perform the subset - condition: define the conditional statement
我们只想退回价格高于 5 的商品,所以我们可以这样做:
# Select price above 5
subset(df, subset = price > 5)
输出:
ID items store price 2 20 pen FALSE 8 3 30 textbook TRUE 10 4 40 pencil_case FALSE 7
行标签 2、3 和 4 是从 df 继承过来的原始行名,因此您可以判断第一行已被过滤掉。`subset()` 函数也接受一个 `select` 参数,用于同时选择列,其等效的括号形式为 `df[df$price > 5, ]`。括号形式会保留条件缺失的 NA 行,而 `subset()` 函数会删除这些行,因此两者并非总是可以互换的。

![R 数据框切片语法为 df[A, B],其中逗号左侧为行,逗号右侧为列。](https://www.guru99.com/images/r_programming/032918_1452_RDataFrames1.png)
