【问题标题】:groupby/sum all columns in first column identical awkgroupby / sum 第一列中的所有列相同的awk
【发布时间】:2014-01-15 14:29:28
【问题描述】:

我有一个包含 n 列的文件(不知道提前多少列)。我需要对具有相同 column1 值的列求和并打印它们。除第一列外,所有列都是数字。例如

file1.txt

col1 col2 col3 ... colN
val1 3000 1000 ... 5000 
val2 3000 1000 ... 5000
val1 1000 2000 ... 3000

预期输出:

col1 col2 col3 ... colN
val1 4000 3000 ... 8000 
val2 3000 1000 ... 5000

我试过了:

awk '{sums[$1] += $2} END { for (i in sums) printf("%s %s\n", i, sums[i])}' file1.txt | sort 

这仅打印前两列。我需要添加并打印所有列。

【问题讨论】:

  • 在我看来这完全是正确的想法,但您需要遍历每个字段并为每个字段计算总和。您可以使用sums[$1,i](假设您的循环变量是i)根据$1 的值和字段编号创建一个数组索引。然后你的 END 循环只需要从 1 走到 X (在某个点保存 NF 并使用它假设你所有的行都是相同的长度)并打印出顺序字段。

标签: awk


【解决方案1】:

这应该可行:

awk 'NR==1{print;next}
    {b[$1];for(i=2;i<=NF;i++)a[$1,i]+=$i}
    END{for(x in b){
            printf "%s ",x;
            for(i=2;i<=NF;i++)
                printf "%s" (i==NF?"\n":" "),a[x,i]}}' file

使用您的数据:

kent$  cat f
col1 col2 col3 colN
val1 3000 1000 5000 
val2 3000 1000 5000
val1 1000 2000 3000

kent$  awk 'NR==1{print;next}
        {b[$1];for(i=2;i<=NF;i++)a[$1,i]+=$i}
        END{for(x in b){printf "%s ",x;
                        for(i=2;i<=NF;i++)
                           printf "%s" (i==NF?"\n":" "),a[x,i]}}' f
col1 col2 col3 colN
val1 4000 3000 8000
val2 3000 1000 5000

【讨论】:

  • 感谢 Kent,它在结果文件中使用了一些意外的格式。值为“42713877753”的列被格式化为“4.27139e+10”。如果它们未被触及,我想按原样保留列值。有什么想法吗?
  • 嗨,肯特,谢谢!!通过放置 %d 而不是 %s,我得到了正确的格式。感谢您在这方面的帮助。
  • printf "%s" (i==NF?"\n":" "),a[x,i] 是非常奇怪的语法。为什么不printf "%s%s", a[x,i], (i==NF?"\n":" ")?恕我直言,这更清楚,因为分隔符字符出现在脚本中的数据之后,就像它在输出中一样,并且您明确/清楚地使用了 printf 格式化字符串。我实际上会使用printf "%s%s", a[x,i], (i&lt;NF?OFS:ORS),而不是对值进行硬编码,恕我直言,在 ORS 之前使用 OFS 编写比使用 nbd 的其他方式更有意义。无论如何 +1。
  • @EdMorton 谢谢。你是对的。当我再次阅读代码时,我也感到很奇怪。我想我为什么会这样,首先测试没有那些格式的东西,然后检查输出,哦,我需要一些东西,把奇怪的东西放在那里.... :(%s%s 变体是明智的方式。跨度>
【解决方案2】:

如果您的 GNU awk 高于 4.1 版,请使用 arrays of arrays 的 awk

awk 'NR==1{print;next}
{for (i=2;i<=NF;i++) a[$1][i]+=$i}
END { for (i in a) 
        {  printf i
          for (j=2;j<=length(a[i])+1;j++) 
              printf FS a[i][j]
          printf RS
        }
    }' file 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    • 2016-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多