data.table
Использование столбцов списка для хранения данных
Поиск…
Вступление
list
R.
замечания
В случае, если странно, что мы говорим о списках без использования этого слова в коде, обратите внимание, что .()
Является псевдонимом для list()
когда используется внутри вызова DT[...]
.
Чтение во многих связанных файлах
Предположим, мы хотим читать и складывать кучу файлов с одинаковым форматированием. Быстрое решение:
rbindlist(lapply(list.files(patt="csv$"), fread), id=TRUE)
Мы не можем быть удовлетворены этим по нескольким причинам:
- Это может привести к ошибкам при чтении с помощью
fread
или при укладке с помощьюrbindlist
из-за несогласованного или ошибочного форматирования данных. - Мы можем отслеживать метаданные для каждого файла, извлекать их из имени файла или, возможно, из некоторых строк заголовка в (не совсем табличных) файлах.
Один из способов справиться с этим - создать «таблицу файлов» и сохранить содержимое каждого файла в виде записи в столбце списка в связанной с ним строке.
Примеры данных
Прежде чем приводить приведенные ниже примеры данных, убедитесь, что вы находитесь в пустой папке, в которую вы можете писать. Запустите getwd()
и прочитайте ?setwd
если вам нужно сменить папки.
# 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))
Идентификация файлов и метаданных файлов
Эта часть довольно проста:
# 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
Чтение в файлах
Чтение в файлах в виде столбца списка:
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>
Если есть необходимость в чтении одного из файлов или вам нужно изменить аргументы на fread
зависимости от атрибутов файла, этот шаг можно легко расширить, выглядя так:
fileDT[, contents := {
cat(fn, "\n")
dat = if (year %in% 2011:2012){
fread(fn, some_args)
} else {
fread(fn)
}
.(.(dat))
}, by=fn]
Подробнее о параметрах чтения в CSV-файлах и подобных файлах см. « ?fread
.
Данные стека
Отсюда мы хотим собрать данные:
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
Если в стеке возникает некоторая проблема (например, имена столбцов или классы не совпадают), мы можем вернуться к отдельным таблицам в fileDT
чтобы проверить, где возникла проблема. Например,
fileDT[id == "2", contents[[1]]]
# id v
# 1: 1 o
# 2: 2 w
расширения
Если файлы не находятся в текущем рабочем каталоге, используйте
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))))]