閱讀許多相關檔案

假設我們想要讀取和堆疊一堆類似格式的檔案。快速解決方案是:

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))))]