data.table
Verwenden von Listenspalten zum Speichern von Daten
Suche…
Einführung
list
Klasse.
Bemerkungen
Wenn es komisch aussieht, dass wir über Listen sprechen, ohne dieses Wort im Code zu verwenden, beachten Sie, dass .()
Ein Alias für list()
wenn er in einem DT[...]
Aufruf DT[...]
.
Lesen in vielen verwandten Dateien
Angenommen, wir möchten eine Reihe ähnlich formatierter Dateien lesen und stapeln. Die schnelle Lösung ist:
rbindlist(lapply(list.files(patt="csv$"), fread), id=TRUE)
Wir sind aus einigen Gründen nicht zufrieden damit:
- Beim Lesen mit
fread
oder beim Stapeln mitrbindlist
aufgrund inkonsistenter oderrbindlist
fread
Fehler auftreten. - Wir möchten die Metadaten für jede Datei verfolgen, die aus dem Dateinamen oder aus einigen Kopfzeilen in den (nicht ganz tabellarischen) Dateien entnommen wurde.
Eine Möglichkeit, dies zu behandeln, besteht darin, eine "Dateitabelle" zu erstellen und den Inhalt jeder Datei als Listenspalteneintrag in der zugehörigen Zeile zu speichern.
Beispieldaten
Stellen Sie vor dem Erstellen der Beispieldaten sicher, dass Sie sich in einem leeren Ordner befinden, in den Sie schreiben können. Führen Sie getwd()
und lesen Sie ?setwd
wenn Sie Ordner wechseln müssen.
# 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))
Identifizieren Sie Dateien und Datei-Metadaten
Dieser Teil ist ziemlich einfach:
# 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
Dateien einlesen
Lesen Sie die Dateien als Listenspalte ein:
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>
Wenn es bei der Lektüre einer der Dateien ein Haken ist oder müssen Sie die Argumente ändern fread
auf der Datei - Attribute abhängig, kann dieser Schritt leicht erweitert werden, die aussehen wie:
fileDT[, contents := {
cat(fn, "\n")
dat = if (year %in% 2011:2012){
fread(fn, some_args)
} else {
fread(fn)
}
.(.(dat))
}, by=fn]
Weitere Informationen zu den Optionen zum Einlesen von CSV-Dateien und ähnlichen Dateien finden ?fread
.
Daten stapeln
Von hier aus wollen wir die Daten stapeln:
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
Wenn beim Stapeln Probleme auftreten (z. B. Spaltennamen oder nicht übereinstimmende Klassen), können wir zu den einzelnen Tabellen in fileDT
, um zu überprüfen, wo das Problem entstanden ist. Zum Beispiel,
fileDT[id == "2", contents[[1]]]
# id v
# 1: 1 o
# 2: 2 w
Erweiterungen
Wenn sich die Dateien nicht in Ihrem aktuellen Arbeitsverzeichnis befinden, verwenden Sie
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))))]