Como faço uma lista de quadros de dados?

Como faço uma lista de quadros de dados e como acedo a cada um desses quadros da lista?

por exemplo, Como posso colocar estes quadros de dados numa lista ?

d1 <- data.frame(y1 = c(1, 2, 3),
                 y2 = c(4, 5, 6))
d2 <- data.frame(y1 = c(3, 2, 1),
                 y2 = c(6, 5, 4))
Author: Moody_Mudskipper, 2013-07-06

7 answers

Isto não está relacionado com a tua pergunta, mas queres usar = e não <- dentro da chamada de função. Se utilizar <-, acabará por criar variáveis y1 e {[8] } em qualquer ambiente em que esteja a trabalhar:

d1 <- data.frame(y1 <- c(1, 2, 3), y2 <- c(4, 5, 6))
y1
# [1] 1 2 3
y2
# [1] 4 5 6

Isto não terá o efeito aparentemente desejado de criar nomes de colunas no quadro de Dados:

d1
#   y1....c.1..2..3. y2....c.4..5..6.
# 1                1                4
# 2                2                5
# 3                3                6

O operador =, por outro lado, irá associar os seus vetores com argumentos a data.frame.

Quanto à sua pergunta, fazer uma lista de molduras de dados é fácil:
d1 <- data.frame(y1 = c(1, 2, 3), y2 = c(4, 5, 6))
d2 <- data.frame(y1 = c(3, 2, 1), y2 = c(6, 5, 4))
my.list <- list(d1, d2)

Você acede aos quadros de dados tal como acederia a qualquer outro elemento da lista:

my.list[[1]]
#   y1 y2
# 1  1  4
# 2  2  5
# 3  3  6
 102
Author: Peyton, 2017-12-11 01:30:56
As outras respostas mostram como fazer uma lista de dados.molduras quando você já tem um monte de dados.= = ligações externas = = , d1, d2, .... Ter molduras de dados sequencialmente nomeadas é um problema, e colocá-las em uma lista é uma boa solução, mas a melhor prática é evitar ter um monte de dados.quadros não incluídos numa lista em primeiro lugar.

As outras respostas dão bastante detalhe de como atribuir quadros de dados a elementos de lista, acessá-los, etc. Nós ... cubra isso um pouco aqui também, mas o ponto principalé dizer Não espere até ter um monte de data.frames para adicioná-los a uma lista. Começa pela lista.

Se eles são uma variedade estranha( o que é incomum), você pode simplesmente atribuí-los:

mylist <- list()
mylist[[1]] <- mtcars
mylist[[2]] <- data.frame(a = rnorm(50), b = runif(50))
...

O resto desta resposta irá cobrir alguns casos comuns onde você pode ser tentado a criar variáveis sequenciais, e mostrar-lhe como ir direto para listas. Se você é novo em listas em R, você pode querer também ler Qual é a diferença entre [[ e [ no acesso aos elementos de uma lista?.


Listas desde o início

Nunca cries d1 d2 d3, ... em primeiro lugar. Crie uma lista d com 3 elementos.

Ler vários ficheiros numa lista de quadros de dados

Isto é feito muito facilmente quando se lê em ficheiros. Talvez tenhas ficheiros numa pasta. Seu objetivo é uma lista de dados.quadros chamados mydata. A primeira coisa que precisas é um vetor com todos os nomes dos arquivos. Você pode construir isso com o paste (por exemplo, my_files = paste0("data", 1:5, ".csv")), mas provavelmente é mais fácil usar list.files para pegar todos os arquivos apropriados: my_files <- list.files(pattern = "\\.csv$"). Neste momento, a maioria dos principiantes usarão um laço, e não há nada de errado nisso, funciona muito bem.
my_data <- list()
for (i in seq_along(my_files)) {
    my_data[[i]] <- read.csv(file = my_files[i])
}
Uma forma mais parecida de o fazer é com ... lapply
my_data <- lapply(my_files, read.csv)

Seja como for, é útil nomear os elementos da lista para corresponder aos ficheiros

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 = "")

Dividir uma moldura de dados em um lista dos quadros de dados

Isto é super fácil, a função base fá-lo por ti. Você pode dividir por uma coluna (ou colunas) dos dados, ou por qualquer outra coisa que você quiser
mt_list = split(mtcars, f = mtcars$cyl)
# This gives a list of three data frames, one for each value of cyl
Também é uma boa maneira de quebrar uma moldura de dados em pedaços para validação cruzada. Talvez queiras dividir em peças de treino, 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!

Simular uma lista de quadros de dados

Talvez estejas a simular dados, algo assim.
my_sim_data = data.frame(x = rnorm(50), y = rnorm(50))

Mas quem só há uma simulação? Queres fazer isto 100 vezes, 1000 vezes, mais! Mas você não quer 10 mil quadros de dados no seu espaço de trabalho. Use replicate e coloque-os numa lista:

sim_list = replicate(n = 10,
                     expr = {data.frame(x = rnorm(50), y = rnorm(50))},
                     simplify = F)

Especialmente neste caso, você também deve considerar se você realmente precisa de quadros de dados separados, ou uma única estrutura de dados com uma coluna de "grupo" também funcionaria? Usando data.table ou dplyr é muito fácil fazer as coisas "por grupo" a uma moldura de dados.

Não pus os meus dados numa lista. da próxima vez, mas o que posso fazer agora?

Se você tem quadros de dados nomeados em um padrão, por exemplo, df1, df2, df3, e se os quiser numa lista, pode obtê-losse conseguir escrever uma expressão regular que corresponda aos 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 devolvê-los em uma lista com nome. Seu equivalente get é usado para obter um único objeto e devolvê-lo não em uma lista.

Combinar uma lista de quadros de dados num único quadro de dados

Uma tarefa comum é combinar uma lista de quadros de dados em um grande quadro de dados. Se você quiser empilhá-los em cima um do outro, você usaria rbind para um par deles, mas para uma lista de molduras de dados aqui são três boas escolhas:

# 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
# they will be faster and can also add id columns to identify
# which list item they came from. They can also fill in
# missing values if some data frames have more columns than others
big_data = data.table::rbindlist(df_list)
big_data = dplyr::bind_rows(df_list)

(da mesma forma que cbind ou dplyr::bind_cols para colunas.)

Para juntar (juntar) uma lista de molduras de dados, você pode ver estas respostas. Muitas vezes, a idéia é usar Reduce com merge (ou alguma outra função de união) para obtê-los juntamente.

Porquê colocar os dados numa lista?

Coloque dados semelhantes em listas porque você quer fazer coisas semelhantes a cada moldura de dados, e funções como lapply, sapply do.call, o pacotepurrr e o antigo plyr l*ply as funções facilitam isso. Exemplos de pessoas que facilmente fazem coisas com listas estão por todo o lado.

Mesmo que você use um loop baixo para o loop, é muito mais fácil de loop sobre os elementos de uma lista do que é construir nomes de variáveis com paste e aceder aos objectos com get. Também é mais fácil depurar.

Pensa em escalabilidade. Se você realmente só precisa de três variáveis, é bom usar d1, d2, d3. Mas se precisares mesmo de 6, é muito mais dactilografar. E da próxima vez, quando você precisar de 10 ou 20, você se encontra copiando e colando linhas de código, talvez usando find / replace para mudar d14 para d15, e você está pensando Isso não é como a programação deve ser . Se utilizar uma lista, a diferença entre 3 casos, 30 casos e 300 casos é no máximo uma linha de código - - - nenhuma alteração se o seu número de casos é detectado automaticamente por, por exemplo, quantos arquivos .csv estão em seu diretório.

Você pode nomear os elementos de uma lista, no caso de você querer usar algo diferente de índices numéricos para acessar seus quadros de dados (e você pode usar ambos, isso não é uma escolha XOR).

De um modo geral, a utilização de listas levar-te-á a escrever um código mais limpo, mais fácil de ler, que irá resulta em menos bugs e menos confusão.

 258
Author: Gregor, 2018-06-23 03:24:56

Também pode aceder a colunas e valores específicos em cada elemento da lista com [ e [[. Aqui estão alguns exemplos. Primeiro, podemos acessar apenas a primeira coluna de cada quadro de dados na lista com lapply(ldf, "[", 1), onde 1 significa o número da coluna.

ldf <- list(d1 = d1, d2 = d2)  ## create a named list of your data frames
lapply(ldf, "[", 1)
# $d1
#   y1
# 1  1
# 2  2
# 3  3
#
# $d2
#   y1
# 1  3
# 2  2
# 3  1
Da mesma forma, podemos aceder ao primeiro valor na segunda coluna com
lapply(ldf, "[", 1, 2)
# $d1
# [1] 4
# 
# $d2
# [1] 6

Então também podemos acessar os valores da coluna diretamente, como um vetor, com [[

lapply(ldf, "[[", 1)
# $d1
# [1] 1 2 3
#
# $d2
# [1] 3 2 1
 16
Author: Rich Scriven, 2016-04-15 00:02:15

Se tiver um grande número de quadros de dados sequencialmente nomeados, poderá criar uma lista do subconjunto desejado de quadros de dados como este:

d1 <- data.frame(y1=c(1,2,3), y2=c(4,5,6))
d2 <- data.frame(y1=c(3,2,1), y2=c(6,5,4))
d3 <- data.frame(y1=c(6,5,4), y2=c(3,2,1))
d4 <- data.frame(y1=c(9,9,9), y2=c(8,8,8))

my.list <- list(d1, d2, d3, d4)
my.list

my.list2 <- lapply(paste('d', seq(2,4,1), sep=''), get)
my.list2

Onde my.list2 devolve uma lista que contém as 2.ª, 3. ª e 4. ª molduras de dados.

[[1]]
  y1 y2
1  3  6
2  2  5
3  1  4

[[2]]
  y1 y2
1  6  3
2  5  2
3  4  1

[[3]]
  y1 y2
1  9  8
2  9  8
3  9  8

Note, No entanto, que os quadros de dados da lista acima não são mais nomeados. Se quiser criar uma lista que contenha um subconjunto de molduras de dados e quiser preservar os seus nomes, pode tentar isto:

list.function <-  function() { 

     d1 <- data.frame(y1=c(1,2,3), y2=c(4,5,6))
     d2 <- data.frame(y1=c(3,2,1), y2=c(6,5,4))
     d3 <- data.frame(y1=c(6,5,4), y2=c(3,2,1))
     d4 <- data.frame(y1=c(9,9,9), y2=c(8,8,8))

     sapply(paste('d', seq(2,4,1), sep=''), get, environment(), simplify = FALSE) 
} 

my.list3 <- list.function()
my.list3

Que devolve:

> my.list3
$d2
  y1 y2
1  3  6
2  2  5
3  1  4

$d3
  y1 y2
1  6  3
2  5  2
3  4  1

$d4
  y1 y2
1  9  8
2  9  8
3  9  8

> str(my.list3)
List of 3
 $ d2:'data.frame':     3 obs. of  2 variables:
  ..$ y1: num [1:3] 3 2 1
  ..$ y2: num [1:3] 6 5 4
 $ d3:'data.frame':     3 obs. of  2 variables:
  ..$ y1: num [1:3] 6 5 4
  ..$ y2: num [1:3] 3 2 1
 $ d4:'data.frame':     3 obs. of  2 variables:
  ..$ y1: num [1:3] 9 9 9
  ..$ y2: num [1:3] 8 8 8

> my.list3[[1]]
  y1 y2
1  3  6
2  2  5
3  1  4

> my.list3$d4
  y1 y2
1  9  8
2  9  8
3  9  8
 12
Author: Mark Miller, 2013-07-06 04:17:14

Tomando como dado tem um grande número de dados.molduras com nomes semelhantes (aqui d# Onde # é algum inteiro positivo), o seguinte é uma ligeira melhoria do método de @mark-miller, na medida em que ele retorna automaticamente uma lista com nome de dados.molduras e é mais terse.

A chave está a usar mget em conjunto com ls. Se os quadros de dados d1 e d2 fornecidos na pergunta eram os únicos objetos com nomes D# no ambiente, então

my.list <- mget(ls(pattern="^d[0-9]+"))

O que faria return

my.list
$d1
  y1 y2
1  1  4
2  2  5
3  3  6

$d2
  y1 y2
1  3  6
2  2  5
3  1  4

Este método tira partido do argumento padrão em ls, que nos permite usar expressões regulares para fazer uma análise mais precisa dos nomes dos objectos no ambiente.

Como @gregor aponta , é um Geral melhor configurar o seu processo de construção de dados para que os dados.as molduras são colocadas em listas com nomes no início.

Dados

d1<-data.frame(y1 = c(1,2,3),y2 = c(4,5,6))
d2<-data.frame(y1 = c(3,2,1),y2 = c(6,5,4))
 8
Author: lmo, 2017-05-23 11:55:03
Isto pode ser um pouco tarde, mas voltando ao seu exemplo, pensei em estender um pouco a resposta.
 D1 <- data.frame(Y1=c(1,2,3), Y2=c(4,5,6))
 D2 <- data.frame(Y1=c(3,2,1), Y2=c(6,5,4))
 D3 <- data.frame(Y1=c(6,5,4), Y2=c(3,2,1))
 D4 <- data.frame(Y1=c(9,9,9), Y2=c(8,8,8))

Depois fazes a tua lista Facilmente:

mylist <- list(D1,D2,D3,D4)
Agora você tem uma lista, mas em vez de Acessar a lista da maneira antiga, como
mylist[[1]] # to access 'd1'

Pode usar esta função para obter e atribuir o nome de dados da sua escolha.

GETDF_FROMLIST <- function(DF_LIST, ITEM_LOC){
   DF_SELECTED <- DF_LIST[[ITEM_LOC]]
   return(DF_SELECTED)
}
Agora vai buscar o que quiseres.
D1 <- GETDF_FROMLIST(mylist, 1)
D2 <- GETDF_FROMLIST(mylist, 2)
D3 <- GETDF_FROMLIST(mylist, 3)
D4 <- GETDF_FROMLIST(mylist, 4)
Espero que essa parte extra ajude. Saúde!
 2
Author: ML_for_now, 2014-06-23 19:45:42
Muito simples ! Eis a minha sugestão:

Se quiser seleccionar os nomes de dados no seu espaço de trabalho, tente isto :

Filter(function(x) is.data.frame(get(x)) , ls())

Ou

ls()[sapply(ls(), function(x) is.data.frame(get(x)))]

Todos estes vão dar o mesmo resultado.

Você pode mudar is.data.frame para verificar outros tipos de variáveis como is.function

 0
Author: CHAMI Soufiane, 2018-05-22 11:16:22