R: Listas do R: O “Container Universal” do R
Última atualização: 2026-08-26
Nas três aulas anteriores, aprendemos sobre vetores e matrizes — ambos exigem que todos os elementos sejam do mesmo tipo. No entanto, na realidade, os dados costumam ser heterogêneos: as informações dos alunos incluem o número de identificação (números), o nome (caracteres) e as notas (vetores). O R usa listas para resolver o problema do armazenamento de dados heterogêneos.
As listas são o verdadeiro “canivete suíço” do R — elas podem conter qualquer tipo (vetores, matrizes, data frames, funções ou até mesmo outras listas). Os data frames data.frame são, em essência, “listas de vetores de comprimento igual”. Esta lição é fundamental para a Fase 1.
1. O que você vai aprender
- list() cria um contêiner de qualquer tipo
- Lista de nomes (pesquisa por nome)
- 4 modos de acesso (
[[ ]][ ]$[[ "name" ]]) - Modificar, adicionar e excluir itens de uma lista
- lapply() para processamento em lote de listas
- Listas aninhadas
- list2env() converte uma lista em variáveis de ambiente
2. Uma história sobre a gestão de informações dos alunos
(1) Desafio: Armazenamento heterogêneo de dados
Ivan trabalha no RH e precisa armazenar todas as informações de um funcionário:
Employee ID:2024001(Numbers)
Name:Alice(Character)
Department:Data Analysis Department(Character)
Salary:15000(Numbers)
Skills:c("R", "Python", "SQL")(Character vector)
Se você usar um vetor, todos os elementos devem ser do mesmo tipo — isso não vai funcionar. Se você usar um data frame, cada coluna deve ter o mesmo número de colunas — isso também não vai funcionar.
(2) Solução utilizando listas
# One list Fits all types
employee <- list(
id = 2024001,
name = "Alice",
department = "Data Analysis Department",
salary = 15000,
skills = c("R", "Python", "SQL"),
is_active = TRUE
)
# Access any field
employee$name # [1] "Alice"
employee$skills[1] # [1] "R"
employee$salary * 12 # [1] 180000 (Annual Salary)
Uma única lista contendo 6 campos de tipos diferentes. Esse é o poder das listas do R.
3. list(): Criar uma lista
(1) Sintaxe básica
list(key1 = value1, key2 = value2, ...)
(2) 5 maneiras de criar
# 1. List of Names(Most Commonly Used)
person <- list(name = "Alice", age = 25, scores = c(85, 90, 92))
person
# $name
# [1] "Alice"
#
# $age
# [1] 25
#
# $scores
# [1] 85 90 92
# 2. Anonymous List(Browse by Location)
unnamed <- list("a", 1, TRUE)
# [[1]] "a"
# [[2]] 1
# [[3]] TRUE
# 3. Nested Lists
company <- list(
hr = list(name = "HR", count = 5),
it = list(name = "IT", count = 20)
)
# 4. Empty list
empty <- list()
length(empty) # [1] 0
# 5. Use list() to convert vector (Maintain Heterogeneity)
as.list(c(1, 2, 3))
# [[1]] 1
# [[2]] 2
# [[3]] 3
(3) Comparação entre listas e vetores
graph TB
A[R Data Structures] --> B[Vector<br/>Homogeneous<br/>One-dimensional]
A --> C[Matrix<br/>Homogeneous<br/>Two-dimensional]
A --> D[List<br/>Heterogeneous<br/>Any type]
A --> E[Data Frame<br/>List of vectors of equal length<br/>Two-dimensional]
style A fill:#fff3cd
style B fill:#cce5ff
style C fill:#d4edda
style D fill:#f8d7da
style E fill:#e1d4ff
| Imóvel | Vector c(1, 2, 3) |
Lista list(1, "a", TRUE) |
|---|---|---|
| Tipo de elemento | Deve ser o mesmo | Pode ser diferente |
| Tipo de elemento | 6 tipos básicos | Qualquer objeto R (incluindo funções e data frames) |
| Visita | v[1] |
l[[1]] |
| Comprimento variável | ❌ | ✅ (Pode ser acrescentado ou removido conforme desejado) |
| Semelhante ao Python | tuple |
dict / list |
4. 4 Métodos de acesso (Pontos-chave)
(1) 4 tipos de tabelas de consulta
| Método | Sintaxe | Retorno | Finalidade |
|---|---|---|---|
[[i]] |
O i-ésimo elemento | O próprio elemento | Recuperar um único elemento |
[i] |
O i-ésimo elemento | Sublista | Selecionar um subconjunto |
$name |
Por nome | O próprio elemento | Obter o elemento nomeado |
[["name"]] |
Por nome | O próprio elemento | Equivalente $name |
(2) [[ ]] x [ ]: Principais diferenças
person <- list(name = "Alice", age = 25, scores = c(85, 90, 92))
# [[ ]] Return the element itself
person[[1]]
# [1] "Alice" ← Character
# [ ] Return to Sublist
person[1]
# $name
# [1] "Alice" ← Or a list
# Key Differences: Using [ ] after extraction, attempting to access sub-elements may cause an error
person[1]$name # ✅ $name Still accessible(Syntax sugar)
person[1][1] # ❌ This is the 1 element,But there is only one child list $name
# Practical Application:Calculate the average score
mean(person[[3]]) # [1] 89 ← [[3]] Extract the vector
mean(person$scores) # [1] 89 ← $scores Extract the vector
mean(person[3]) # Error: need numeric data
[[ ]] ou $ para acessar elementos e [ ] para acessar subconjuntos. Esse é o aspecto mais confuso do acesso a listas no R.
(3) $ vs [["name"]]
# $ is syntactic sugar for [[ "name" ]]
person$name # Equivalent person[["name"]]
person[["name"]] # Equivalent person$name
# $ Supports partial matches(Not recommended)
person$na # Automatically matched to "name"
# [1] "Alice"
# [[ ]] Partial matches are not supported(Safer)
person[["na"]] # Error
[[ "name" ]] para o código de produção — é claro e inequívoco, e não depende de correspondências parciais.
(4) Acesso a listas aninhadas
company <- list(
hr = list(name = "HR", count = 5, head = "Alice"),
it = list(name = "IT", count = 20, head = "Bob")
)
# Accessing Nested Elements
company$hr$head # [1] "Alice"
company[["it"]][["head"]] # [1] "Bob"
company$it$count # [1] 20
5. Modificar, adicionar e excluir itens de uma lista
(1) Modificar um elemento
person <- list(name = "Alice", age = 25)
# Edit ([[ ]] or $ both can be changed)
person$age <- 26
person[["age"]]
# [1] 26
# Batch Edit
person$age <- person$age + 1
person$age # [1] 27
(2) Adicionar um elemento
# Methods 1: Use $ to add
person$email <- "alice@example.com"
# Methods 2: Use [[ ]] to add
person[["phone"]] <- "13800000000"
# Methods 3: Use c() to merge
person <- c(person, address = "Haidian District, Beijing")
(3) Exclusão de elementos
# Assign NULL to delete
person$phone <- NULL
# Or
person[["address"]] <- NULL
(4) Visualizar a estrutura da lista
# View Structure(Important Debugging Functions)
str(person)
# List of 4
# $ name : chr "Alice"
# $ age : num 27
# $ email : chr "alice@example.com"
# $ address : chr "Haidian District, Beijing"
# View All Names
names(person)
# [1] "name" "age" "email" "address"
6. lapply(): Processamento em lote de listas
(1) Por que usar o lapply?
Os tipos de elementos em uma lista podem variar — não é possível simplesmente usar sum() mean(). A função lapply nos permite aplicar uma função a cada elemento:
mixed_list <- list(
numbers = 1:5,
chars = c("a", "b", "c"),
logical = c(TRUE, FALSE, TRUE)
)
# Calculate the length of each element
lapply(mixed_list, length)
# $numbers
# [1] 5
#
# $chars
# [1] 3
#
# $logical
# [1] 3
(2) lapply + Função personalizada
# CalculateFor each element,"Abstract"
summary_list <- lapply(mixed_list, function(x) {
if (is.numeric(x)) {
return(list(mean = mean(x), sum = sum(x)))
} else {
return(list(length = length(x), class = class(x)))
}
})
summary_list$numbers
# $mean
# [1] 3
#
# $sum
# [1] 15
(3) Simplificando os resultados com sapply()
# lapply Back to List,sapply Simplify to a vector
sapply(mixed_list, length)
# numbers chars logical
# 5 3 3
7. Unificação de listas: c() e unlist()
(1) c() Mesclar listas
# Merge Multiple Lists
list1 <- list(a = 1, b = 2)
list2 <- list(c = 3, d = 4)
merged <- c(list1, list2)
merged
# $a 1
# $b 2
# $c 3
# $d 4
(2) A função unlist() transforma o objeto em um vetor
# Flatten the list into a vector(Only for"Atom"Element Valid)
numbers_list <- list(a = 1, b = 2, c = 3)
unlist(numbers_list)
# a b c
# 1 2 3
# Note:The type will be coerced after flattening.
mixed <- list(1, "a", TRUE)
unlist(mixed)
# [1] "1" "a" "TRUE" ← Convert All to Strings
8. list2env(): Converte uma lista em um ambiente
Transforme cada elemento da lista em uma variável global:
config <- list(
host = "localhost",
port = 3306,
user = "root",
password = "secret"
)
# Convert list elements to environment variables
list2env(config, envir = .GlobalEnv)
# You can use it right away
host # [1] "localhost"
port # [1] 3306
list2env() pode contaminar o ambiente global; portanto, use com cautela. É mais comumente utilizado em cenários em que as configurações são carregadas a partir de YAML ou JSON.
9. Comparação de operações comuns
(1) c() x list() x unlist()
| Função | Finalidade | Entrada → Saída |
|---|---|---|
c() |
Combinação de elementos atômicos | c(1, 2, 3) → Vetores |
list() |
Criar um contêiner heterogêneo | list(1, "a") → Lista |
unlist() |
Transformar a lista em um vetor | unlist(list(1,2,3)) → Vetor |
(2) Conversão de uma lista em um DataFrame
# A list of vectors of equal length can be converted data.frame
df <- as.data.frame(list(
name = c("A", "B", "C"),
age = c(20, 25, 30),
score = c(85, 90, 78)
))
print(df)
# name age score
# 1 A 20 85
# 2 B 25 90
# 3 C 30 78
10. Exemplo completo: Gerenciamento de registros de funcionários
A seguir, apresentamos um exemplo de um fluxo de trabalho completo que reúne todos os recursos de listas abordados nesta aula.
▶ Exemplo: Gestão de arquivos de funcionários
# ============================================
# Employee File Management
# Features:Manage with Lists 3 Complete information about each employee
# ============================================
# 1. Create 3 List of employees
employees <- list(
alice = list(
id = 2024001,
name = "Alice",
department = "Data Analysis Department",
salary = 15000,
skills = c("R", "Python", "SQL"),
projects = c("User Profiles", "Sales Forecast")
),
bob = list(
id = 2024002,
name = "Bob",
department = "Engineering Department",
salary = 18000,
skills = c("Java", "Go", "Docker"),
projects = c("API Refactoring", "Microservice Migration")
),
charlie = list(
id = 2024003,
name = "Charlie",
department = "Product Department",
salary = 20000,
skills = c("Figma", "Axure"),
projects = c("V2.0 Design", "User Research")
)
)
# 2. View a specific employee's full profile
cat("=== Alice Full Information ===\n")
str(employees$alice)
# List of 6
# $ id : num 2024001
# $ name : chr "Alice"
# $ department : chr "Data Analysis Department"
# $ salary : num 15000
# $ skills : chr [1:3] "R" "Python" "SQL"
# $ projects : chr [1:2] "User Profiles" "Sales Forecast"
# 3. Use sapply for batch processing
cat("\n=== Annual Salaries of All Employees ===\n")
annual_salaries <- sapply(employees, function(emp) emp$salary * 12)
print(annual_salaries)
# alice bob charlie
# 180000 216000 240000
# 4. Use sapply to count skills
cat("\n=== Number of skills per employee ===\n")
skill_counts <- sapply(employees, function(emp) length(emp$skills))
print(skill_counts)
# alice bob charlie
# 3 3 2
# 5. Use split for grouping by department
cat("\n=== Grouped by Department ===\n")
dept_groups <- split(
sapply(employees, function(emp) emp$name),
sapply(employees, function(emp) emp$department)
)
print(dept_groups)
# $Data Analysis Department
# [1] "Alice"
#
# $Engineering Department
# [1] "Bob"
#
# $Product Department
# [1] "Charlie"
# 6. Add a New Employee
employees$diana <- list(
id = 2024004,
name = "Diana",
department = "Data Analysis Department",
salary = 16000,
skills = c("R", "Tableau"),
projects = c("Data Visualization")
)
cat("\n=== Add Diana after ===\n")
cat("Total Number of Employees:", length(employees), "\n")
cat("Diana Department:", employees$diana$department, "\n")
# 7. Identify the employee with the highest salary
top_salary <- which.max(sapply(employees, function(emp) emp$salary))
cat("\nHighest Salary:", names(employees)[top_salary], "(", max(sapply(employees, function(emp) emp$salary)), "USD)\n")
# 8. Retrieve the skills of all employees(Merge all skill vectors)
all_skills <- unlist(lapply(employees, function(emp) emp$skills))
cat("\n=== Company-wide Skills Summary ===\n")
print(table(all_skills))
# all_skills
# Axure Docker Figma Go Java Python R SQL Tableau
# 1 1 1 1 1 1 2 1 1
Resultado esperado (trecho):
=== Alice Full Information ===
List of 6
$ id : num 2024001
$ name : chr "Alice"
...
=== Annual Salaries of All Employees ===
alice bob charlie
180000 216000 240000
=== Company-wide Skills Summary ===
all_skills
Axure Docker Figma Go Java Python R SQL Tableau
1 1 1 1 1 1 2 1 1
❓ Perguntas Frequentes
P: Qual é a diferença entre
[[ ]]e[ ]? R:[[ ]]retorna o próprio elemento (que pode ser manipulado posteriormente), enquanto[ ]retorna uma sublista (cujos elementos não podem ser manipulados posteriormente). Use[[ ]]ou$para recuperar elementos e[ ]para recuperar subconjuntos. Esse é um dos aspectos mais confusos da sintaxe do R.
P:
$e[[ "name" ]]são a mesma coisa? R: Eles são essencialmente equivalentes. No entanto,$suporta correspondência parcial ($nafaz a correspondência automática com “name”), enquanto[[ ]]não. É mais seguro usar[[ "name" ]]em código de produção.
P: Qual é a relação entre listas e vetores? R: Os vetores são homogêneos e unidimensionais (todos os elementos são do mesmo tipo), enquanto as listas são heterogêneas e podem ter qualquer dimensão (os elementos podem ser de qualquer tipo).
data.frameEm essência, uma lista é uma “lista de vetores de comprimento igual” — compreender listas significa compreender data frames.
P: Como faço para escolher entre
lapply()esapply()? R:lapply()retorna uma lista (preservando a estrutura), enquantosapply()simplifica o resultado para um vetor ou matriz (tornando-o mais fácil de ler). Usesapplypara tarefas cotidianas elapplypara pipelines de programação funcional.
P:
unlist()Quando isso deve ser usado? R: Para “transformar” uma lista em um vetor — mas apenas elementos atômicos podem ser transformados. Tipos mistos serão convertidos (por exemplo, list(1, "a") → c("1", "a")).
📖 Resumo
- As listas são os “contêineres universais” do R: elas podem conter qualquer tipo (vetores, matrizes, funções ou outras listas)
- 4 métodos de acesso:
[[i]]$name[[ "name" ]](recuperar elementos) vs[i](recuperar um subconjunto) $nameSuporta correspondência parcial (não recomendado),[[ "name" ]]Correspondência exata (recomendado) Adicionar/Excluir/Modificar:l$new <- x(Adicionar)/l$old <- NULL(Excluir)/l$old <- new_x(Modificar)lapply()Aplicar uma função a cada elemento retorna uma lista;sapply()Simplificado para um vetorunlist()Transforma uma lista em um vetor (elementos heterogêneos serão convertidos)- O data frame
data.frameé, essencialmente, uma “lista de vetores de comprimento igual” — compreender o conceito de lista é um pré-requisito para entender os data frames.
📝 Exercícios
-
Exercício Básico: Crie uma lista chamada
studentcontendo quatro campos:name(caractere),age(número),scores(vetor de valores c(85, 90, 92)) epassed(booleano). Imprima a estrutura da lista (str()) e acessenameescores[2]. -
Problema básico: Crie uma lista aninhada
familycontendo três sublistasfather,motherechild(cada uma delas contendonameeage). Acessechild$agee imprima-o. -
Problema básico: Use
lapply()para calcular em lote o “salário anual” (salary * 12) de uma lista de três funcionários (que você mesmo criará) e usesapply()para simplificar os resultados em um vetor de saída. -
Problema avançado: Escreva uma função
create_employee(name, dept, salary)que retorne uma lista nomeada (contendo id, nome, departamento, salário, habilidades = vetor vazio, is_active = TRUE). Chame-a três vezes para criar três funcionários e armazene-os em uma lista grande. Usesapply()para extrair o “salário anual” de todos os funcionários. -
Desafio: Escreva um script para simular a gestão de uma “biblioteca”: ① Crie uma lista
librarycontendo 3 livros (cada livro possui 4 campos:title,author,yeareavailable); ② Uselapplypara definir o valor deavailablede todos os livros como FALSE (retirados); ③ Usesapplypara encontrar todos os livros disponíveis para empréstimo (available == TRUE); ④ Adicione um novo livro à lista.