我的csv文件中的第二列有重复项。我想根据这些重复项添加第1列中的关联值。
示例csv:
56, cc=DK
49, cc=US
34, cc=GB
32, cc=DE
32, cc=NZ
31, cc=DK
31, cc=GB
31, cc=GB
示例结果:
96, cc=GB # where 96 = 34+31+31
87, cc=DK # where 87 = 56+31
32, cc=DE
32, cc=NZ
答案 0 :(得分:2)
您可以在awk
中使用关联数组:
awk '{s[$2]+=$1}END{for(k in s)print s[k]", ",k}' inFile
为了便于阅读而扩展,并使用sum/key
而不是s/k
:
{ # Do for each line.
sum[$2] += $1 # Add first field to accumulator,
# indexed by second field.
# initial value is zero.
}
END { # Do this bit when whole file processed.
for (key in sum) # For each key like cc=US:
print sum[key] ", " key # Output the sum and key.
}
这是我的盒子上的示例:
pax$ echo;echo '56, cc=DK
49, cc=US
34, cc=GB
32, cc=DE
32, cc=NZ
31, cc=DK
31, cc=GB
31, cc=GB' | awk '{s[$2]+=$1}END{for(k in s)print s[k]", "k}'
32, cc=DE
96, cc=GB
32, cc=NZ
49, cc=US
87, cc=DK
尽管第一列的格式为999,
(注意末尾的逗号),但这只是因为awk
在评估数字上下文中的字符串时仅使用前缀这在上下文中是有效的。因此45xyzzy
将变为45
,更重要的是49,
变为49
。
答案 1 :(得分:1)
Perl解决方案:
perl -ane '$h{ $F[1] } += $F[0] }{ print "$h{$_}\t$_\n" for keys %h' input.csv
说明:
-n
逐行处理输入行-a
将空格上的输入行拆分为@F数组}{
(称为" Eskimo greeting")将每行(-n
)执行的内容与处理完整输入后要运行的代码分开/ LI>
答案 2 :(得分:0)
使用awk
来完成这么简单的任务是可以的,但是如果你有很多类似的任务,而且将来可能需要更改它,那么很容易搞砸了。
由于它是典型的数据库问题,请考虑使用sqlite
。
你可以:
添加行名并删除多余的空格:
$ cat <(echo "num, name") originalInput.txt | tr -d ' ' > input.csv
将数据导入临时sqlite db:
$ sqlite3 --batch temp.db <<EOF!
.mode csv
.import input.csv input
EOF!
从db:
中选择$sqlite3 temp.db 'SELECT sum(num), name FROM input GROUP BY name'
32|cc=DE
87|cc=DK
96|cc=GB
32|cc=NZ
49|cc=US
稍微多一些代码并使用外部sqlite3
命令,但它显着不易出错,更强灵活。您可以轻松地连接多个csv文件,使用花式排序等。
另外,想象一下你自己在六个月后查看代码,试图快速了解它的作用。