R语言中的列表:如何创建和选择元素

什么是 R 列表?
R 列表 是 R 编程中的一个对象,其中包括矩阵、向量、数据框或列表。R 列表也用于存储对象集合并在需要时使用它们。我们可以将 R 列表想象成一个可以放置许多不同物品的袋子。当我们需要使用某件物品时,我们可以打开袋子并使用它。
与向量的对比正是包的用处所在。向量强制每个元素归为一种类型,因此将单词放在数字旁边会将数字转换为文本。列表则没有这样的规则,所以它可以容纳一个包含五个元素的向量,也就是两行数据。 矩阵 并排显示一个 714 行的数据框,且不做任何修改。
R 中的列表语法
在 R 编程中,我们可以使用 list() 函数来创建列表:
list(element_1, ...) arguments: -element_1: store any type of R object -...: pass as many objects as specifying. each object needs to be separated by a comma
每个参数都可以直接传递,也可以采用以下形式传递: 标签 = 价值裸参数会变成一个位置元素,只能通过其编号访问;而带标签的参数还会获得一个名称。R 基础参考 列表() 文档记录了两种形式,并指出 unlist() 的作用类似于 as.list() 的逆操作。
如何在 R 中创建列表
以下是在 R 中创建列表的分步过程:
在下面的例子中,我们将创建三个不同的对象,一个向量、一个矩阵和一个 数据帧 在 R 中使用列表函数。
步骤 1)创建矢量
使用以下代码在 R 中创建一个向量
# Vector with numeric from 1 up to 5
vect <- 1:5
冒号运算符将序列 1、2、3、4、5 构建为一个整数向量,赋值箭头将其存储在名为 vect 的向量下。
步骤2)创建矩阵
现在,使用以下代码创建一个矩阵。
# A 2x 5 matrix
mat <- matrix(1:9, ncol = 5)
dim(mat)
这里有两个细节需要注意。一个两行五列的网格需要十个值,但只提供了九个,因此 R 会重复使用序列,并打印一条警告,提示数据长度不是行数的倍数。正是由于重复使用了这些值,才导致打印出的矩阵第二行以 1 而不是 10 结尾。然后调用 dim() 函数会报告矩阵的形状。
输出:
## [1] 2 5
步骤 3)创建数据框
使用以下代码在 R 中创建数据框
# select the 10th row of the built-in R data set EuStockMarkets
df <- EuStockMarkets[1:10,]
注释中提到了第十行,但表达式保留了内置的 EuStockMarkets 系列的前十行。子集操作还会删除时间序列类,因此返回的是一个数值矩阵而不是真正的数据框,这正是为什么下面打印的结果带有 [1,] 样式的行标签而不是行名称的原因。每当需要真正的数据框时,请将调用包装在 as.data.frame() 中。
步骤 4)在 R 中创建列表
现在,我们可以使用以下代码将三个对象放入 R 列表中
# Construct list with these vec, mat, and df:
my_list <- list(vect, mat, df)
my_list
输出:
## [[1]] ## [1] 1 2 3 4 5 ## [[2]] ## [,1] [,2] [,3] [,4] [,5] ## [1,] 1 3 5 7 9 ## [2,] 2 4 6 8 1 ## [[3]] ## DAX SMI CAC FTSE ## [1,] 1628.75 1678.1 1772.8 2443.6 ## [2,] 1613.63 1688.5 1750.5 2460.2 ## [3,] 1606.51 1678.6 1718.0 2448.2 ## [4,] 1621.04 1684.1 1708.1 2470.4 ## [5,] 1618.16 1686.6 1723.1 2484.7 ## [6,] 1610.61 1671.6 1714.3 2466.8 ## [7,] 1630.75 1682.9 1734.5 2487.9 ## [8,] 1640.17 1703.6 1757.4 2508.4 ## [9,] 1635.47 1697.5 1754.0 2510.5 ## [10,] 1645.89 1716.3 1754.3 2497.4
输出结果中的三个双括号标题表示列表位置。没有任何数据被扁平化或强制转换:第一个元素仍然是一个整数向量,第二个元素仍然是一个矩阵,第三个元素仍然包含全部十行股票价格。
从 R 列表中选择元素
创建列表后,我们可以轻松地访问它。我们需要使用 `[[index]]` 来选择列表中的元素。双中括号内的值表示我们要选择的项目在列表中的位置。trac例如,我们在括号内传递 2,R 返回列出的第二个元素。
现在在这个 R 教程,让我们尝试选择 R 中名为 my_list 的列表的第二项,我们使用 my_list[[2]]
# Print second element of the list
my_list[[2]]
输出:
## [,1] [,2] [,3] [,4] [,5] ## [1,] 1 3 5 7 9 ## [2,] 2 4 6 8 1
单括号和双括号不能互换使用,混淆它们是列表错误最常见的原因。一个括号保留包装器,两个括号移除包装器。
| 口语 | 返回的结果 | 结果的类别 | 在以下情况下使用 |
|---|---|---|---|
| my_list[[2]] | 存储的元素本身 | 无论存储了什么,这里都是一个矩阵 | 你需要对一个元素进行计算。 |
| my_list[2] | 包含该元素的子列表 | 名单 | 你需要保留列表包装器 |
| my_list[c(1, 3)] | 所选元素的子列表 | 名单 | 你需要同时使用多个元素。 |
| my_list[-2] | 除了第二个元素之外的每个元素 | 名单 | 你需要删除一个元素 |
# Compare the two bracket styles class(my_list[[2]]) # the matrix itself class(my_list[2]) # a list of length one # Several elements, and everything but one element my_list[c(1, 3)] my_list[-2]
R语言中的命名列表
位置索引很脆弱:插入一个元素后,它后面的每个数字都会发生偏移。给元素命名可以消除这种风险,并使代码读起来就像它所描述的数据一样。可以在构建列表时提供名称,也可以之后使用 `names()` 函数添加名称。
# Tag each element at creation time named_list <- list(numbers = vect, grid = mat, prices = df) # Three ways to reach the same element named_list$grid named_list[["grid"]] named_list["grid"] # returns a one-element list # Read or replace the names later names(named_list) names(named_list)[2] <- "grid_2x5"
$ 运算符和双括号在一个容易让初学者感到困惑的地方有所不同。$ 运算符执行的是部分匹配,因此 `named_list$pri` 仍然会找到价格,而 `named_list[[“pri”]]` 会返回 NULL,因为除非指定 `exact = FALSE`,否则双括号会进行精确匹配。部分匹配在控制台中很方便,但在脚本中不安全,因此在保存的代码中最好使用精确匹配。
# A compact map of the whole structure
str(named_list)
str() 函数会打印每个元素一行,包含其类型和大小,这是在对列表进行索引之前确认列表是否包含预期内容的最快方法。
修改、添加和删除 R 列表中的元素
列表一旦创建就不是固定的。读取元素的访问器也可以写入元素,因此更新、扩展和缩减列表都使用普通的赋值操作。
# Replace an element in place named_list[["numbers"]] <- 1:10 # Add a new element simply by naming it named_list[["created"]] <- Sys.Date() # Append without a name: the element lands at the end named_list <- append(named_list, list(TRUE)) # Delete an element by assigning NULL to it named_list[["created"]] <- NULL
- 更换: 给现有元素赋值会覆盖该元素,但不会改变其位置。
- 添加: 将不存在的名称赋值给一个元素,会在列表末尾添加一个新元素。
- 附加: append() 函数的第二个参数是一个列表,因此在传递裸值之前,请先用 list() 函数将其包装起来。
- 删除: 使用双括号赋值为 NULL 会删除该元素并缩短列表。
一个常见的错误是:由于 NULL 表示删除,因此不能用双括号存储真正的 NULL 值。应该使用单括号赋值,例如 `named_list[“empty”] <- list(NULL)`,这样既保留了空位,又将 NULL 值放入其中。
R语言中的嵌套列表和unlist()函数
由于列表可以容纳任何 R 对象,因此它也可以容纳另一个列表。嵌套是 R 中配置对象、JSON 响应和模型结果的常用表示方式,因此访问嵌套列表和展平嵌套列表都是日常操作。
# A list whose elements are themselves lists project <- list( meta = list(owner = "analyst", year = 2026), data = list(vect, mat) ) # Chain the accessors to reach an inner value project$meta$year project[["data"]][[2]] # Flatten every level into one atomic vector flat <- unlist(project) # Strip a single level and keep the rest as a list half <- unlist(project, recursive = FALSE)
扁平化是有代价的,值得理解。`unlist()` 必须返回一个原子向量,因此它会将每个值强制转换为最通用的类型,顺序为逻辑值、整数、双精度浮点数、字符。因此,一个混合了数字和文本的嵌套列表将完全以文本形式返回。结果的名称由外部标签和内部标签连接而成,这就是为什么元素以 `meta.owner` 而不是 `owner` 的形式返回的原因。
如果不需要复合名称,请传递 `use.names = FALSE`;如果只想移除最外层,请设置 `recursive = FALSE`。如果值必须保持其类型,请保持结构完整并遍历列表,而不是将其扁平化。
R 中的内置数据框
列表通常包含从磁盘或网络读取的数据,因此了解数据框在存储到列表之前是如何到达的很有帮助。在创建我们自己的数据框之前,我们可以先查看在线提供的 R 数据集。监狱数据集是一个 714×5 的维度。我们可以使用 `tail()` 函数快速查看数据框的底部。类似地,`head()` 函数显示数据框的顶部。您可以使用 `head(df, 5)` 指定显示的行数。我们将在后续章节中学习更多关于 `read.csv()` 函数的内容。 在 R 中导入数据 教程。
PATH <-'https://raw.githubusercontent.com/guru99-edu/R-Programming/master/prison.csv'
df <- read.csv(PATH)[1:5]
head(df, 5)
输出:
## X state year govelec black ## 1 1 1 80 0 0.2560 ## 2 2 1 81 0 0.2557 ## 3 3 1 82 1 0.2554 ## 4 4 1 83 0 0.2551 ## 5 5 1 84 0 0.2548
`read.csv()` 后面的 `[1:5]` 选择的是前五列,而不是前五行,因为数据框本身就是一个列列表。对列表使用单括号索引会返回一个更小的列表,而在这里,这个更小的列表仍然是一个数据框。
我们可以用 str 检查数据框的结构:
# Structure of the data
str(df)
输出:
## 'data.frame': 714 obs. of 5 variables: ## $ X : int 1 2 3 4 5 6 7 8 9 10 ... ## $ state : int 1 1 1 1 1 1 1 1 1 1 ... ## $ year : int 80 81 82 83 84 85 86 87 88 89 ... ## $ govelec: int 0 0 1 0 0 0 1 0 0 0 ... ## $ black : num 0.256 0.256 0.255 0.255 0.255 ...
所有变量都存储在 数字的 格式。每行的 $ 前缀与之前命名列表中使用的运算符相同,这证实了数据框是由等长列组成的列表,并带有矩形标签。因此,所有关于命名、选择和删除列表元素的知识都可以直接应用到数据框中。 R 数据类型 并映射到数据框列。
