我有几个相当大的 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