附加具有不同列数量和拼写的 csvs

Appending csvs with different column quantities and spellings

没什么太复杂的,在大量 csvs 上使用 rbindlist 会很有用,其中列名随时间略有变化(较小的拼写变化),列顺序保持不变,并且在某些时候,两个额外的列被添加到 csvs(我真的不需要)。


library(data.table)

csv1 <- data.table("apple" = 1:3, "orange" = 2:4, "dragonfruit" = 13:15)

csv2 <- data.table("appole" = 7:9, "orangina" = 6:8, "dragonificfruit" = 2:4, "pear" = 1:3)

l <- list(csv1, csv2)

当我运行

csv_append <- rbindlist(l, fill=TRUE) #which also forces use.names=TRUE

它给了我一个有 7 列的 data.table

     apple orange dragonfruit appole orangina dragonificfruit pear
1:     1      2          13     NA       NA              NA   NA
2:     2      3          14     NA       NA              NA   NA
3:     3      4          15     NA       NA              NA   NA
4:    NA     NA          NA      7        6               2    1
5:    NA     NA          NA      8        7               3    2
6:    NA     NA          NA      9        8               4    3

与我想要的相反,即:

       V1     V2         V3     V4
1:     1      2          13     NA
2:     2      3          14     NA
3:     3      4          15     NA
4:     7      6           2     1
5:     8      7           3     2
6:     9      8           4     3

我可以使用它,即使稍后我必须执行额外的步骤将列重命名回标准变量名称。

如果我改为尝试默认的 fill=FALSE 和 use.names=FALSE,它会抛出一个错误:

Error in rbindlist(l) : 
  Item 2 has 4 columns, inconsistent with item 1 which has 3 columns. To fill missing columns use fill=TRUE.

有没有一种简单的方法来管理这个问题,要么通过某种方式强制 fill=TRUE 和 use.names=FALSE,要么通过指定要附加的列向量来省略 csvs 中具有它们的附加列?

如果我们只需要前 3 列,则删除其余列并像往常一样绑定:

rbindlist(lapply(l, function(i) i[, 1:3]))
#    apple orange dragonfruit
# 1:     1      2          13
# 2:     2      3          14
# 3:     3      4          15
# 4:     7      6           2
# 5:     8      7           3
# 6:     9      8           4

另一种选择,来自评论:我们可以直接读取文件,并使用 fread 设置只保留前 3 列,然后绑定:

rbindlist(lapply(filenames, fread, select = c(1:3)))

这是一个使用 stringdist 中的 phonetic 进行名称匹配的选项。从data.tablelist中提取列名('nmlist'),unlist,使用phonetic分组,得到第一个元素,relist它到与 'nmlist' 相同的 list 结构,使用 Map 更改 data.table 的 list 的列名,然后应用 rbindlist

library(stringdist)
library(data.table)
nmlist <- lapply(l, names)
nm1 <- unlist(nmlist)
rbindlist(Map(setnames, l, relist(ave(nm1, phonetic(nm1), 
      FUN = function(x) x[1]), skeleton = nmlist)), fill = TRUE)

-输出

#    apple orange dragonfruit pear
#1:     1      2          13   NA
#2:     2      3          14   NA
#3:     3      4          15   NA
#4:     7      6           2    1
#5:     8      7           3    2
#6:     9      8           4    3