As outras respostas mostrar-lhe como fazer uma lista de data.frames quando você já tem um monte de data.frames, por exemplo, d1
, d2
, .... Ter quadros de dados sequencialmente nomeado é um problema, e colocá-los em uma lista é um boa correção, mas a melhor prática é evitar ter um monte de dados. quadros que não estão em uma lista em primeiro lugar.
As outras respostas fornecem muitos detalhes de como atribuir quadros de dados a elementos de lista, acessá-los etc. Também abordaremos um pouco aqui, mas o ponto principal é dizer: não espere até que você tenha um monte dedata.frames
para adicioná-los a uma lista. Comece com a lista.
O restante desta resposta abordará alguns casos comuns em que você pode ser tentado a criar variáveis seqüenciais e mostra como ir direto para as listas. Se você é novo nas listas em R, também pode ler Qual é a diferença entre [[
e [
ao acessar elementos de uma lista? .
Listas desde o início
Nunca crie d1
d2
d3
, ..., dn
em primeiro lugar. Crie uma lista d
com n
elementos.
Lendo vários arquivos em uma lista de quadros de dados
Isso é feito com bastante facilidade ao ler arquivos. Talvez você tenha arquivos data1.csv, data2.csv, ...
em um diretório. Seu objetivo é uma lista de data.frames chamada mydata
. A primeira coisa que você precisa é de um vetor com todos os nomes de arquivo. Você pode construir isso com pasta (por exemplo, my_files = paste0("data", 1:5, ".csv")
), mas é provavelmente mais fácil de usar list.files
para pegar todos os arquivos apropriados: my_files <- list.files(pattern = "\\.csv$")
. Você pode usar expressões regulares para corresponder aos arquivos. Leia mais sobre expressões regulares em outras perguntas, se precisar de ajuda. Dessa forma, você pode pegar todos os arquivos CSV, mesmo que eles não sigam um bom esquema de nomenclatura. Ou você pode usar um padrão regex mais sofisticado, se precisar escolher certos arquivos CSV dentre vários deles.
Neste ponto, a maioria dos iniciantes de R usará um for
loop, e não há nada de errado nisso, ele funciona muito bem.
my_data <- list()
for (i in seq_along(my_files)) {
my_data[[i]] <- read.csv(file = my_files[i])
}
Uma maneira mais R-like de fazer isso é lapply
, que é um atalho para o acima
my_data <- lapply(my_files, read.csv)
Obviamente, substitua por outras funções de importação de dados read.csv
conforme apropriado. readr::read_csv
ou data.table::fread
será mais rápido, ou você também pode precisar de uma função diferente para um tipo de arquivo diferente.
De qualquer forma, é útil nomear os elementos da lista para corresponder aos arquivos
names(my_data) <- gsub("\\.csv$", "", my_files)
# or, if you prefer the consistent syntax of stringr
names(my_data) <- stringr::str_replace(my_files, pattern = ".csv", replacement = "")
Dividindo um quadro de dados em uma lista de quadros de dados
Isso é super fácil, a função base split()
faz isso por você. Você pode dividir por uma coluna (ou colunas) dos dados ou por qualquer outra coisa que desejar
mt_list = split(mtcars, f = mtcars$cyl)
# This gives a list of three data frames, one for each value of cyl
Essa também é uma boa maneira de dividir um quadro de dados em partes para validação cruzada. Talvez você queira dividir mtcars
em partes de treinamento, teste e validação.
groups = sample(c("train", "test", "validate"),
size = nrow(mtcars), replace = TRUE)
mt_split = split(mtcars, f = groups)
# and mt_split has appropriate names already!
Simulando uma lista de quadros de dados
Talvez você esteja simulando dados, algo como isto:
my_sim_data = data.frame(x = rnorm(50), y = rnorm(50))
Mas quem faz apenas uma simulação? Você quer fazer isso 100 vezes, 1000 vezes, mais! Mas você não deseja 10.000 quadros de dados em seu espaço de trabalho. Use replicate
e coloque-os em uma lista:
sim_list = replicate(n = 10,
expr = {data.frame(x = rnorm(50), y = rnorm(50))},
simplify = F)
Nesse caso, especialmente, você também deve considerar se realmente precisa de quadros de dados separados ou um único quadro de dados com uma coluna "grupo" funcionaria da mesma maneira? Usando data.table
ou dplyr
é muito fácil fazer as coisas "por grupo" em um quadro de dados.
Não coloquei meus dados em uma lista :( farei da próxima vez, mas o que posso fazer agora?
Se eles são uma variedade ímpar (o que é incomum), você pode simplesmente atribuí-los:
mylist <- list()
mylist[[1]] <- mtcars
mylist[[2]] <- data.frame(a = rnorm(50), b = runif(50))
...
Se você tem quadros de dados nomeados em um padrão, por exemplo, df1
, df2
, df3
, e você quer que eles em uma lista, você pode get
lhes se você pode escrever uma expressão regular para coincidir com os nomes. Algo como
df_list = mget(ls(pattern = "df[0-9]"))
# this would match any object with "df" followed by a digit in its name
# you can test what objects will be got by just running the
ls(pattern = "df[0-9]")
# part and adjusting the pattern until it gets the right objects.
Geralmente, mget
é usado para obter vários objetos e retorná-los em uma lista nomeada. Sua contraparte get
é usada para obter um único objeto e devolvê-lo (não em uma lista).
Combinando uma lista de quadros de dados em um único quadro de dados
Uma tarefa comum é combinar uma lista de quadros de dados em um grande quadro de dados. Se você deseja empilhá-las umas sobre as outras, você usaria rbind
para um par delas, mas para uma lista de quadros de dados, aqui estão três boas opções:
# base option - slower but not extra dependencies
big_data = do.call(what = rbind, args = df_list)
# data table and dplyr have nice functions for this that
# - are much faster
# - add id columns to identify the source
# - fill in missing values if some data frames have more columns than others
# see their help pages for details
big_data = data.table::rbindlist(df_list)
big_data = dplyr::bind_rows(df_list)
(Da mesma forma, usando cbind
ou dplyr::bind_cols
para colunas.)
Para mesclar (ingressar) em uma lista de quadros de dados, você pode ver essas respostas . Muitas vezes, a ideia é usar Reduce
commerge
(ou alguma outra função de junção) para reuni-los.
Por que colocar os dados em uma lista?
Coloque dados semelhantes em listas porque você quer fazer coisas semelhantes a cada frame de dados, e funções como lapply
, sapply
do.call
, o purrr
pacote , e as antigas plyr
l*ply
funções tornam mais fácil para fazer isso. Exemplos de pessoas que fazem coisas facilmente com listas estão por toda parte.
Mesmo se você usar um loop for lowly, é muito mais fácil fazer um loop sobre os elementos de uma lista do que construir nomes de variáveis paste
e acessar os objetos com get
. Mais fácil de depurar também.
Pense em escalabilidade . Se você realmente só precisa de três variáveis, é bom para usar d1
, d2
, d3
. Mas se você realmente precisa de 6, é muito mais digitação. E da próxima vez, quando você precisa de 10 ou 20, você encontrar-se copiando e colando linhas de código, talvez usando find / substituir a mudança d14
para d15
, e você está pensando não é assim que a programação deve ser . Se você usar uma lista, a diferença entre 3 casos, 30 casos e 300 casos será no máximo uma linha de código - nenhuma alteração será alterada se o número de casos for detectado automaticamente por, por exemplo, quantos .csv
arquivos existem no seu diretório.
Você pode nomear os elementos de uma lista, caso deseje usar algo diferente de índices numéricos para acessar seus quadros de dados (e você pode usar os dois, essa não é uma opção XOR).
No geral, o uso de listas o levará a escrever códigos mais limpos e fáceis de ler, o que resultará em menos bugs e menos confusão.
=
não por<-
dentrodata.frame()
. Usando<-
você criay1
ey2
em seu ambiente global e seu quadro de dados não é o que você deseja que seja.