data.table
Utilizzo delle colonne elenco per memorizzare i dati
Ricerca…
introduzione
list
di R.
Osservazioni
Nel caso in cui sembri strano che stiamo parlando di liste senza usare quella parola nel codice, nota che .()
È un alias per list()
se usato all'interno di una chiamata DT[...]
.
Lettura in molti file correlati
Supponiamo di voler leggere e impilare un gruppo di file formattati in modo simile. La soluzione rapida è:
rbindlist(lapply(list.files(patt="csv$"), fread), id=TRUE)
Potremmo non essere soddisfatti di questo per un paio di motivi:
- Potrebbe verificarsi errori durante la lettura con
fread
o quando si impila conrbindlist
causa della formattazione dei dati incoerente orbindlist
. - Potremmo voler tenere traccia dei metadati per ogni file, afferrati dal nome del file o forse da alcune righe di intestazione all'interno dei file (non del tutto tabulari).
Un modo per gestire ciò è creare una "tabella di file" e memorizzare il contenuto di ciascun file come una voce della colonna di elenco sulla riga associata.
Dati di esempio
Prima di inserire i dati di esempio qui sotto, assicurati di essere in una cartella vuota su cui scrivere. Esegui getwd()
e leggi ?setwd
se hai bisogno di cambiare cartella.
# example data
set.seed(1)
for (i in 1:3)
fwrite(data.table(id = 1:2, v = sample(letters, 2)), file = sprintf("file201%s.csv", i))
Identifica i file e i metadati dei file
Questa parte è abbastanza semplice:
# First, identify the files you want:
fileDT = data.table(fn = list.files(pattern="csv$"))
# Next, optionally parse the names for metadata using regex:
fileDT[, year := type.convert(sub(".*([0-9]{4}).*", "\\1", fn))]
# Finally construct a string file-ID column:
fileDT[, id := as.character(.I)]
# fn year id
# 1: file2011.csv 2011 1
# 2: file2012.csv 2012 2
# 3: file2013.csv 2013 3
Leggi nei file
Leggi nei file come una colonna di lista:
fileDT[, contents := .(lapply(fn, fread))]
# fn year id contents
# 1: file2011.csv 2011 1 <data.table>
# 2: file2012.csv 2012 2 <data.table>
# 3: file2013.csv 2013 3 <data.table>
Se c'è un intoppo nel leggere uno dei file o è necessario modificare gli argomenti fread
seconda attributi del file, questo passaggio può essere facilmente esteso, guardando come:
fileDT[, contents := {
cat(fn, "\n")
dat = if (year %in% 2011:2012){
fread(fn, some_args)
} else {
fread(fn)
}
.(.(dat))
}, by=fn]
Per i dettagli sulle opzioni di lettura in file CSV e file simili, vedere ?fread
Impila i dati
Da qui, vogliamo impilare i dati:
fileDT[, rbindlist(setNames(contents, id), idcol="file_id")]
# file_id id v
# 1: 1 1 g
# 2: 1 2 j
# 3: 2 1 o
# 4: 2 2 w
# 5: 3 1 f
# 6: 3 2 w
Se si verificano alcuni problemi nello stacking (come i nomi delle colonne o le classi che non corrispondono), possiamo tornare alle singole tabelle in fileDT
per verificare dove ha avuto origine il problema. Per esempio,
fileDT[id == "2", contents[[1]]]
# id v
# 1: 1 o
# 2: 2 w
estensioni
Se i file non si trovano nella directory di lavoro corrente, utilizzare
my_dir = "whatever"
fileDT = data.table(fn = list.files(my_dir, pattern="*.csv"))
# and when reading
fileDT[, contents := .(lapply(fn, function(n) fread(file.path(my_dir, n))))]