csv 列中的总和值

csv 列中的总和值

我有几个相当大的 csv 文件,我需要对其中每列的值求和并转置列标题。

示例 csv:

col1,col2,col3
enabled,disabled,active
disabled,disabled,enabled
N/A,enabled,active
enabled,N/A,disabled

期望的输出:

col1,2 enabled,1 disabled,1 N/A
col2,1 enabled,2 disabled,1 N/A
col3,1 enabled,1 disabled,2 active

实际的 csv 有更多的列和行,因此最好能够自动迭代文件。我可能会想出一些 awk 程序的 hack 工作来一次完成一列,但更希望能够一次处理整个文件,并且不知道从哪里开始。输出不需要采用我所包含的确切格式,但至少是相似的。

答案1

$ cat tst.awk
BEGIN { FS=OFS="," }
NR==1 { numRows = split($0,keys); next }
{
    for (i=1; i<=NF; i++) {
        sum[i,$i]++
        vals[$i]
    }
}
END {
    for (rowNr=1; rowNr<=numRows; rowNr++) {
        printf "%s", keys[rowNr]
        for (val in vals) {
            printf "%s%d %s", OFS, sum[rowNr,val], val
        }
        print ""
    }
}

$ awk -f tst.awk file
col1,1 disabled,2 enabled,1 N/A,0 active
col2,2 disabled,1 enabled,1 N/A,0 active
col3,1 disabled,1 enabled,0 N/A,2 active

或者可能更有用:

$ cat tst.awk
BEGIN { FS=OFS="," }
NR==1 { numRows = split($0,keys); next }
{
    for (i=1; i<=NF; i++) {
        sum[i,$i]++
        vals[$i]
    }
}
END {
    printf "%s", "key"
    for (val in vals) {
        printf "%s%s", OFS, val
    }
    print ""

    for (rowNr=1; rowNr<=numRows; rowNr++) {
        printf "%s", keys[rowNr]
        for (val in vals) {
            printf "%s%d", OFS, sum[rowNr,val]
        }
        print ""
    }
}

$ awk -f tst.awk file
key,disabled,enabled,N/A,active
col1,1,2,1,0
col2,2,1,1,0
col3,1,1,0,2

答案2

你可以和米勒非常接近:

mlr --icsvlite --odkvp put -q 'for(k,v in $*) { @count[k][v] += 1; } end {emit @count,"col"}' sample.csv
col=col1,enabled=2,disabled=1,N/A=1
col=col2,disabled=2,enabled=1,N/A=1
col=col3,active=2,enabled=1,disabled=1

相关内容