Skip to content

R - 列表

列表 (Lists) 是 R 中最通用的数据结构之一。与必须包含相同类型元素的原子向量 (atomic vectors) 不同,列表可以包含不同类型的元素。这使得它们非常适合存储异构的对象集合,例如模型参数、配置设置或复杂分析的结果。

一个列表可以包含数字、字符串、向量、数据框,甚至其他列表。

您使用 list() 函数创建列表。最佳实践是为列表的元素命名,以提高清晰度和更方便地访问。

# Create a named list with various data types
project_config <- list(
project_name = "Global Sales Analysis",
analyst_id = 101,
regions = c("NA", "EU", "APAC"),
is_active = TRUE,
parameters = list(alpha = 0.05, beta = 0.9)
)
# Print the list to see its structure
print(project_config)

执行上述代码后,将产生一个结构良好的输出:

$project_name
[1] "Global Sales Analysis"
$analyst_id
[1] 101
$regions
[1] "NA" "EU" "APAC"
$is_active
[1] TRUE
$parameters
$parameters$alpha
[1] 0.05
$parameters$beta
[1] 0.9

访问列表元素:三个关键操作符

Section titled “访问列表元素:三个关键操作符”

理解如何访问列表元素至关重要。R 有三个主要的运算符用于此目的,它们的行为各不相同:

  • $(美元符号): 最常见和便捷的方式,用于访问命名元素。它直接提取元素的内容。
  • [[...]](双层方括号): 提取单个元素的内容。您可以配合名称(例如,my_list[["name"]])或索引(例如,my_list[[1]])使用它。
  • [...](单层方括号): 对列表进行子集操作,但总是返回另一个列表。适用于一次性选择多个元素。
# Using the `$` operator to get the project name (returns a string)
name <- project_config$project_name
print(name)
# [1] "Global Sales Analysis"
# Using `[[...]]` to get the regions vector (returns a vector)
regions_vector <- project_config[["regions"]]
print(regions_vector)
# [1] "NA" "EU" "APAC"
# Using `[...]` to get a sub-list (returns a list)
sub_list <- project_config[1:2]
print(sub_list)
# $project_name
# [1] "Global Sales Analysis"
#
# $analyst_id
# [1] 101

常见错误: 初学者常犯的错误是,当他们想要内容本身时却使用了 [],结果得到的是一个列表而不是期望的值,这可能导致下游函数出错。

列表是可变的,这意味着您可以轻松添加、更新或删除元素。

# --- Update an element ---
project_config$is_active <- FALSE
# --- Add a new element ---
project_config$last_updated <- Sys.Date()
# --- Remove an element by setting it to NULL ---
project_config$analyst_id <- NULL
# Print the modified list
str(project_config) # str() gives a compact summary

str() 输出显示了我们的更改:

List of 5
$ project_name: chr "Global Sales Analysis"
$ regions : chr [1:3] "NA" "EU" "APAC"
$ is_active : logi FALSE
$ parameters :List of 2
..$ alpha: num 0.05
..$ beta : num 0.9
$ last_updated: Date, format: "YYYY-MM-DD"

虽然 for 循环可以迭代列表,但更现代、函数式且通常更简洁的方法是使用 purrr 包(tidyverse 的一部分)中的 map() 函数族。

library(purrr)
list_of_numbers <- list(a = 1:5, b = 6:10, c = 11:15)
# Use map() to apply a function to each element.
# The result is always a list.
list_of_means <- map(list_of_numbers, mean)
print(list_of_means)
# Use map_dbl() to do the same, but return a numeric vector.
vector_of_means <- map_dbl(list_of_numbers, mean)
print(vector_of_means)

purrr 示例的输出:

$a
[1] 3
$b
[1] 8
$c
[1] 13
a b c
3 8 13

您可以使用 c() 函数合并列表。要将列表转换为单个原子向量,请使用 unlist(),但请注意,它会将所有元素强制转换为一个通用类型(通常是字符型)。

# Merging two lists
list1 <- list(a = 1, b = 2)
list2 <- list(c = "hello", d = "world")
merged_list <- c(list1, list2)
# Result: list(a = 1, b = 2, c = "hello", d = "world")
# Converting a list to a vector with unlist()
v <- unlist(list1)
# Result: a numeric vector c(a = 1, b = 2)
# Unlisting a mixed-type list forces type coercion
mixed_vector <- unlist(merged_list)
# Result: a character vector c(a = "1", b = "2", c = "hello", d = "world")