【问题标题】:sum rows based on unique columns awk根据唯一列 awk 对行求和
【发布时间】:2014-03-14 03:54:24
【问题描述】:

我正在寻找一种更优雅的方式来执行此操作(超过 100 列):

awk '{a[$1]+=$4}{b[$1]+=$5}{c[$1]+=$6}{d[$1]+=$7}{e[$1]+=$8}{f[$1]+=$9}{g[$1]+=$10}END{for(i in a) print i,a[i],b[i],c[i],d[i],e[i],f[i],g[i]}'

这是输入:

 a1 1   1   2   2
 a2 2   5   3   7
 a2 2   3   3   8
 a3 1   4   6   1
 a3 1   7   9   4
 a3 1   2   4   2

和输出:

 a1 1 1 2 2
 a2 4 8 6 15
 a3 3 13 19 7

谢谢:)

【问题讨论】:

    标签: awk count unique


    【解决方案1】:

    我将单行分成几行,以便于阅读。

    awk '{n[$1];for(i=2;i<=NF;i++)a[$1,i]+=$i}
        END{for(x in n){
            printf "%s ", x
            for(y=2;y<=NF;y++)printf "%s%s", a[x,y],(y==NF?ORS:FS)
            }
        }' file
    

    这个 awk 命令应该适用于您的 100 列文件。

    用你的文件测试:

    kent$  cat f
    a1 1   1   2   2
    a2 2   5   3   7
    a2 2   3   3   8
    a3 1   4   6   1
    a3 1   7   9   4
    a3 1   2   4   2
    
    kent$  awk '{n[$1];for(i=2;i<=NF;i++)a[$1,i]+=$i}END{for(x in n){printf "%s ", x;for(y=2;y<=NF;y++)printf "%s%s", a[x,y],(y==NF?ORS:OFS)}}' f
    a1 1 1 2 2
    a2 4 8 6 15
    a3 3 13 19 7
    

    【讨论】:

    • printf y==NF?"%s":"%s ",a[x,y] 会导致一些 awk 的语法错误(OSX 上的 BSD awk 可能?)。用括号括起来三元表达式应该可以解决它:printf (y==NF?"%s":"%s "),a[x,y] 虽然我有点惊讶它的工作原理,因为我认为在尝试在 printf 中的第一个逗号之前使用三元表达式之前我已经看到了语法错误,因此出于这个原因和恕我直言,我'd倾向于将其写为printf "%s%s", a[x,y], (y==NF?ORS:OFS),然后在循环之后没有单独的print ""
    • @EdMorton %s%s 是明智之举!谢谢.. 我总能从你的 cmets/answers 中学到东西
    • @Kent 您能否根据 EdMorton 的建议编辑您的答案,以便我接受答案? :)
    • 另外,此解决方案在每行之后插入空行
    • @user2904120 已更新。输出中不应有空行。确保您删除了print "",因为我们使用了ORS。检查我编辑的答案。
    【解决方案2】:

    在 gnu awk 版本 4 中使用数组数组

    awk '{for (i=2;i<=NF;i++) a[$1][i]+=$i}
    END{for (i in a) 
          { printf i FS;
            for (j in a[i]) printf a[i][j] FS 
            printf RS}
        }' file     
    
    a1 1 1 2 2
    a2 4 8 6 15
    a3 3 13 19 7
    

    【讨论】:

    • +1 也许你应该说它需要 Gnu awk 版本 4?
    • 看起来不错,但我无法执行它
    • @Håkon Hægland,当然,我更新了它。
    • @user2904120 ,您收到的错误信息是什么?是gnu awk v4的版本吗?
    • 它是nawk 不是gawk 所以它不支持.. 你可以下载并安装gawk 4 然后尝试BMW 的方法,否则使用提供的其他两种方法。
    【解决方案3】:

    如果你关心输出顺序,试试这个

    $ cat file
    a1 1   1   2   2
    a2 2   5   3   7
    a2 2   3   3   8
    a3 1   4   6   1
    a3 1   7   9   4
    a3 1   2   4   2
    

    Awk 代码:

    $ cat tester
    awk 'FNR==NR{
                  U[$1]                             # Array U with index being field1
                  for(i=2;i<=NF;i++)                # loop through columns thats is column2 to NF
                  A[$1,i]+=$i                       # Array A holds sum of columns
                  next                              # stop processing the current record and go on to the next record
                }
       ($1 in U){                                   # Here we read same file once again,if field1 is found in array U, then following statements
                  for(i=1;i<=NF;i++)
                  s = s ? s OFS A[$1,i] : A[$1,i]   # I am writing sum to variable s since I want to use only one print statement, here you can use printf also
                  print $1,s                        # print column1 and variable s
                  delete U[$1]                      # We have done, so delete array element
                  s = ""                            # reset variable s
                }' OFS='\t' file{,}                 # output field separator is tab you can set comma also
    

    结果

    $ bash tester
    a1  1   1   2   2
    a2  4   8   6   15
    a3  3   13  19  7
    

    如果您想在 Solaris/SunOS system 上尝试此操作,请将 awk 更改为 /usr/xpg4/bin/awk/usr/xpg6/bin/awknawk

    --编辑--

    根据评论中的要求,这里是一个衬里,为了更好地阅读,我在上面的帖子中发表了评论,它变成了几行。

    $ awk 'FNR==NR{U[$1];for(i=2;i<=NF;i++)A[$1,i]+=$i;next}($1 in U){for(i=1;i<=NF;i++)s = s ? s OFS A[$1,i] : A[$1,i];print $1,s;delete U[$1];s = ""}' OFS='\t' file{,}
    a1  1   1   2   2
    a2  4   8   6   15
    a3  3   13  19  7
    

    【讨论】:

    • 可以单行运行吗?
    猜你喜欢
    • 2016-01-16
    • 2019-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-05
    相关资源
    最近更新 更多