生成包含输入csv的唯一行的输出csv,其中column1和column5值是重复的

lc8prwob  于 2023-07-31  发布在  其他
关注(0)|答案(2)|浏览(71)

我想写一个bash命令(也可以接受纯python-没有pandas,numpy等),它接受一个csv输入,比如说input.csv,选择column1和column5的值的元组重复的行,并将它们保存到另一个csv中,比如说output.csv。
然后从该列表中删除重复的行(所有列的值具有相同元组的行)
需要说明的是,* 向输出csv添加一行的条件 * 是:

IF 
    the current row (row1) value of col1 is equal to the value of col1 of a row already parsed  (row2)
    AND
    the current row (row1) value of col5 is equal to the value of col5 of the already-parsed row I am considering (row2) 

        IF row1 is not already in output.csv:
            THEN 
            add row1 in output.csv       

        if row2 is not already in output.csv:
            THEN 
            add row2 in output.csv

字符串

部分数据信息

  • 这些csv中的数据未排序。输出不必排序。
  • 列之间用分号;分隔
  • Col1和col5的所有值具有相同的长度。
  • 数据来自postgresql DB表,其中列定义为:
col1 TEXT,          -- only digits, all values have the same length 

col2 TEXT,          -- only digits, all values have the same length        
col3 TEXT,          -- only digits, all values have the same length        
col4 TEXT,          -- only digits, all values have the same length  

col5 TEXT,          -- only digits, all values have the same length        

col6 TEXT,          -- dates: yyyy-mm-dd, digits and dashes "-", all values have the same length 
col7 TEXT,          -- dates: yyyy-mm-dd, digits and dashes "-", all values have the same length
col8 NUMERIC,       -- digits and sometimes point: i.e. 1.99, 4.8, 30
col9 SMALLINT,      -- only digits, all values have the same length


我拥有的我想要的
所以让我们假设我的input.csv是这样的:
(The第一列是行索引,但它们不在csv中,这只是为了澄清这个问题)

col1 ...  col5 ... col9

1   10   ...  01   ... 1001
2   10   ...  02   ... 1002 
3   10   ...  03   ... 1003 
4   11   ...  04   ... 1004 
5   11   ...  03   ... 1005 
6   11   ...  04   ... 1001 
7   10   ...  01   ... 1001 
8   12   ...  05   ... 1003 
9   12   ...  05   ... 1004 
10  10   ...  01   ... 1001


其他列中的内容并不重要,csv有9列。
我希望我的输出. csv为

col1 ...  col5 ... col9
 
11   ...  04   ... 1004 
11   ...  04   ... 1001 
10   ...  01   ... 1001
12   ...  05   ... 1003
12   ...  05   ... 1004


输出顺序无关紧要
实施例2:
如果在input.csv中有这两行:
1 a a a 1 a a a a
1 b b b 1 b b b b
两者都必须出现在输出. csv中

我所尝试的

我尝试用awk构建这样一个命令。
1.初审:
我确信,如果我必须生成一个记录列表,其中只有col1的值是重复的,我可以运行以下命令

awk -F';' 'NR==FNR{count[$1]++; next} count[$1]>1 && !visited[$1]++' input.csv input.csv >> output.csv


基于这个命令,我尝试了

awk -F';' 'NR==FNR{count[$1]++; next} count[$1]>1 && !visited[$1]++ && NR==FNR{count[$5]++; next} count[$5]>1 && !visited[$5]++' input.csv input.csv >> output.csv


但看起来好像不起作用。
1.二审:
我猜“column1和column5中的值都重复的行”等价于“column1和column5的连接值重复的行”。
基于这个假设,我尝试了

# concatenate valuesm of col 1 and 5 in col 10
awk -F ';' '{ $NF = $1 $5 } 1' OFS=';' input.csv input.csv >> output_10.csv

# extract unique list of rows where the col10 is duplicate
awk -F';' 'NR==FNR{count[$10]++; next} count[$10]>1 && !visited[$10]++' input_10.csv input_10.csv >> output_duplicated_10.csv

# remove the 10th column
awk 'BEGIN {FS = OFS = ";"} {for (i=1; i<=NF; i++) if (i != 10) printf "%s%s", $i, (i==NF?ORS:OFS)}' {{ output_duplicated_10.csv >> output_duplicated.csv


但它不起作用。
我做错了什么?

qlvxas9a

qlvxas9a1#

你说这只适用于第1列:

awk -F';' '
    NR==FNR{count[$1]++; next}
    count[$1]>1 && !visited[$1]++
' input.csv input.csv >> output.csv

字符串
您说测试连接列会起作用。
因此,只需将第1列值($1)替换为新键:

awk -F';' '
    {k = $1 FS $5}
    NR==FNR{count[k]++; next}
    count[k]>1 && !visited[k]++
' input.csv input.csv >> output.csv


看起来你需要阅读一个关于awk的教程来理解模式/动作格式以及如何解释换行符。当你用&&连接两个程序时,结果不是运行两个程序,然后“和”每个部分的结果在一起。
要将标题复制到输出,请为第1行添加一个测试:

awk -F';' '
    {k = $1 FS $5}
    NR==FNR{count[k]++; next}
    count[k]>1 && !visited[k]++ || FNR==1
' input.csv input.csv >> output.csv

s6fujrry

s6fujrry2#

如果您的输入是

col1,col2,col3
11,00,04
10,13,01
10,13,01
13,20,01
11,01,04
23,20,07

字符串
您可以使用Miller并运行

mlr --csv count-similar -g col1,col3 \
then filter '$count>1' \
then cut -x -f count input.csv


获取col1和col3值重复的所有行(在我的示例文件中)

col1,col2,col3
11,00,04
11,01,04
10,13,01
10,13,01


要过滤此输出并仅获取唯一值,可以添加uniq predicate 并运行

mlr --csv count-similar -g col1,col3 \
then filter '$count>1' \
then uniq -a \
then cut -x -f count input.csv


得到

col1,col2,col3
11,00,04
11,01,04
10,13,01


如果只想提取col1和col3重复的第一行,可以运行

mlr --csv cat -n \
then count-similar -g col1,col3 \
then filter '$count>1' \
then sort -f n \
then head -n 1 -g col1,col3 \
then cut -x -f n,count input.csv


得到

col1,col2,col3
11,00,04
10,13,01

相关问题