data.table
Używanie kolumn listy do przechowywania danych
Szukaj…
Wprowadzenie
list
R.
Uwagi
W przypadku, gdy wygląda dziwnie, że mówimy o listach bez użycia tego słowa w kodzie, zauważ, że .()
Jest aliasem dla list()
gdy jest używany w wywołaniu DT[...]
.
Czytanie w wielu powiązanych plikach
Załóżmy, że chcemy odczytać i ułożyć stos plików o podobnym formacie. Szybkie rozwiązanie to:
rbindlist(lapply(list.files(patt="csv$"), fread), id=TRUE)
Możemy nie być z tego zadowoleni z kilku powodów:
- Może
rbindlist
błędy podczas czytania zfread
lub podczas układania w stos zrbindlist
z powodu niespójnego lubrbindlist
formatowania danych. - Możemy chcieć śledzić metadane dla każdego pliku, pobrane z nazwy pliku lub być może z niektórych wierszy nagłówka w plikach (niezupełnie tabelarycznych).
Jednym ze sposobów poradzenia sobie z tym jest utworzenie „tabeli plików” i zapisanie zawartości każdego pliku jako pozycji kolumny listy w wierszu z nim powiązanym.
Przykładowe dane
Przed wykonaniem poniższych przykładowych danych upewnij się, że znajdujesz się w pustym folderze, w którym możesz pisać. Uruchom getwd()
i przeczytaj ?setwd
jeśli chcesz zmienić foldery.
# 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))
Zidentyfikuj pliki i metadane plików
Ta część jest dość prosta:
# 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
Wczytaj pliki
Wczytaj pliki jako kolumnę listy:
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>
Jeśli w czytaniu jednego z plików pojawi się problem lub konieczna będzie zmiana argumentów na fread
zależności od atrybutów pliku, ten krok można łatwo przedłużyć, wyglądając:
fileDT[, contents := {
cat(fn, "\n")
dat = if (year %in% 2011:2012){
fread(fn, some_args)
} else {
fread(fn)
}
.(.(dat))
}, by=fn]
Aby uzyskać szczegółowe informacje na temat opcji odczytu w plikach CSV i podobnych plikach, zobacz ?fread
.
Stos danych
Stąd chcemy ułożyć dane w stos:
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
Jeśli wystąpi jakiś problem w stosie (np. fileDT
nazwy kolumn lub klasy), możemy wrócić do poszczególnych tabel w fileDT
aby sprawdzić, skąd problem się fileDT
. Na przykład,
fileDT[id == "2", contents[[1]]]
# id v
# 1: 1 o
# 2: 2 w
Rozszerzenia
Jeśli plików nie ma w bieżącym katalogu roboczym, użyj
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))))]