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

Posted

技术标签:

【中文标题】附加具有不同列数量和拼写的 csv【英文标题】:Appending csvs with different column quantities and spellings 【发布时间】:2021-02-24 22:09:48 【问题描述】:

没什么太复杂的,在大量 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,或者通过指定要追加的列向量来省略 csv 中包含它们的其他列?

【问题讨论】:

【参考方案1】:

如果我们只需要前 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

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

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

【讨论】:

这是否适用于使用 fread 读取实际的 csv 文件?我对上面的问题进行了缩写,但我正在运行的完整嵌套 rbindlist 将是:rbindlist(lapply(filenames,fread)),其中 filenames 是我所有 csv 文件的列表。那么这会变成 rbindlist(lapply(filenames,fread(i) i[, 1:3])) 吗?我现在就试试这个来测试自己。 编辑:我自己对此进行了测试,并给出了 lapply,有效的代码是:rbindlist(lapply(filenames,fread, select = c(1:3)))。有趣的是,它并没有像我预期的那样返回列名作为 V1 等,而是返回在最后导入的 csv 中拼写的列名。默认 use.names 是 FALSE,所以我不确定它为什么这样做,但现在我也不必替换列名。 @fuzzydata 已编辑,直接从文件中读取,绑定前选择3列。【参考方案2】:

这是一个使用来自stringdistphonetic 进行名称匹配的选项。从data.table('nmlist')的list中提取列名,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

【讨论】:

我从未见过语音,但在这里看到你的实现,这对于搞乱附加、合并和命名约定非常有用。谢谢! @fuzzydata 谢谢,你的预期输出是什么。你需要'梨'的列 我不需要这个应用程序中的“梨”列,但一般来说,提供一个版本的 rbindlist(lapply(filenames,fread, select = c (1:3))) 代码实际上允许使用 NA 添加新列(即 fill=TRUE)选项,同时使用列 #s 而不是名称,以免在拼写存在的地方创建重复列略有不同(假设所有列在 CSV 文件中的顺序相同)。您上面的代码似乎可以做到这一点,所以我注意到这一点以备将来使用,以防我需要添加的变量。

以上是关于附加具有不同列数量和拼写的 csv的主要内容,如果未能解决你的问题,请参考以下文章

Azure 数据工厂附加大量与 csv 文件具有不同架构的文件

导入具有动态列的文件

在python中通过多个条件合并不同数量的行和列

kafka主题分区的数量和数据中不同键的数量

使用 pyspark 读取多个 csv 文件

Pyspark 从具有不同列的行/数据创建 DataFrame