修复 .csv 文件中某些行缺少列的问题

修复 .csv 文件中某些行缺少列的问题

我目前正在处理许多合并的 .csv 文件的数据。不幸的是,这些合并有时是错误的。

这个例子可以最好地解释这一点:

“var1”,“var2”,“var3”,“var4”,“var5”
“2001”,“黄色”,“123”,“abc”,“bcdefg”
“2002”,“黄色”,“123”, “abw”、“asdfkl”
“2001”、“绿色”、“abe”
“2002”、“绿色”、“abp”
“2001”、“蓝色”、“324”、“abx”、“badsf”
“2002 ”、“蓝色”、“231”、“abl”、“cpq”

因此,在第 3 行和第 4 行中,缺少 var3 和 var5 的值。哪些变量(列)缺失的错误总是相同的。

我希望我的 csv 看起来像这样:

“var1”,“var2”,“var3”,“var4”,“var5”
“2001”,“黄色”,“123”,“abc”,“bcdefg”
“2002”,“黄色”,“123”, “abw”,“asdfkl”
“2001”,“绿色”,,“abe”,
“2002”,“绿色”,,“abp”,
“2001”,“蓝色”,“324”,“abx”,“ badsf”
“2002”、“蓝色”、“231”、“abl”、“cpq”

所以现在第 3 行和第 4 行实际上缺少 var3 和 var5 的值。错误并不总是发生在(在本例中)“绿色”上,但也可能发生在另一组上。

我的想法是扫描行中的列,如果列数与标题中的列数不同(“var1”、“var2”等),则添加新的空列。

我必须对许多不同的文件执行此操作,但是一旦我知道如何执行此操作,我想我可以使用 bash 脚本循环。

[编辑]:我想澄清一下,数据集相当大。至少有 19 个变量(列)。 (我需要检查的另一个文件有超过 60 个变量)

现在我正在考虑使用 awk 的解决方案。像这样的东西:

awk '{ if (NF<19) {$7=$7","#NA","#NA}}' 文件 1 > 文件 2

如果没有 19 列(它应该有),则应在第 7 列之后插入两列。稍后会尝试这个...

答案1

想到的最简单的事情就是用逗号分割行,并在只有两个逗号的地方插入额外的逗号。明显的限制是,如果实际值中有逗号,这就会中断。

$ cat test.csv | sed -r 's/^([^,]*),([^,]*),([^,]*)$/\1,\2, ,\3, /g'
"var1", "var2", "var3", "var4", "var5"
"2001", "yellow", "123", "abc", "bcdefg"
"2002", "yellow", "123", "abw", "asdfkl"
"2001", "green", , "abe", 
"2002", "green", , "abp", 
"2001", "blue", "324", "abx", "badsf"
"2002", "blue", "231", "abl", "cpq"

对于更一般的东西,我可能会编写一个Python脚本(它有CSV 功能内置)。例如,从 stdin 读取 CSV 并输出到 stdout:

#!/usr/bin/env python
import sys
import csv

missing = [3, 5]  # 1-indexed positions of missing values
missing.sort()  # enforce the increasing order
reader = csv.reader(sys.stdin, delimiter=',', skipinitialspace=True)
writer = csv.writer(sys.stdout)
header = next(reader)  # get first row (header)
writer.writerow(header)  # write it back
for row in reader:
    if len(row) < len(header):
        # row shorter than header -> insert empty strings
        # inserting changes indices so `missing` must be sorted
        for idx in missing:
            row.insert(idx - 1, '')
    writer.writerow(row)

使用真正的 CSV 解析器的好处是它可以正确处理值和其他边缘情况中的逗号或引号。输出格式也将是正确的 CSV,但与您的格式略有不同:

$ cat test.csv | python test.py 
var1,var2,var3,var4,var5
2001,yellow,123,abc,bcdefg
2002,yellow,123,abw,asdfkl
2001,green,,abe,
2002,green,,abp,
2001,blue,324,abx,badsf
2002,blue,231,abl,cpq

正如您所看到的,逗号后面没有多余的引号或空格。如果您确实需要它们,我可以考虑为编写器配置 CSV 方言。

相关内容