计算另一列中相同名称时列的平均值

时间:2014-05-23 14:49:43

标签: awk

我有一个包含下一列的表格:

Probe Name Sec_Name Number
A_1 One Bla 2
A_2 One Bla 5
A_3 One Bla 2
B_1 Two bli 1
B_2 Third 6

我想检查第二列中的单元格是否重复,如果是,则打印第五列,其中第四列的平均值为第四列。 期望的输出:

Probe Name Sec_Name Number Average
A_1 One Bla 2
A_2 One Bla 5
A_3 One Bla 2 3
B_1 Two bli 1
B_2 Third 6

表格由制表符分隔。我尝试过类似的东西,但是...我希望输出中的列与输入文件中的列相同。

awk '
{
    lines[$2]++;     
    totals[$2] += $4; 
}
END {

    for (i in lines) {
        print i, lines[i], totals[i] totals[i]/lines[i];;
    }
}
' file.txt

我希望它或多或少清楚......

1 个答案:

答案 0 :(得分:2)

您可以在文件中循环两次:

 awk 'FNR==NR {a[$2]+=$4; b[$2]++; next}
     {printf "%s %s\n", $0, (b[$2]>1?a[$2]/b[$2]:"")}' file file

解释

    在第一个循环中
  • FNR==NR {a[$2]+=$4; b[$2]++; next},计算第二列(数组a[] - 您的totals[])的累计值。此外,还要计算它出现的次数(数组b[] - 您的lines[])。
  • 在第二个循环中
  • {printf "%s %s\n", $0, (b[$2]>1?a[$2]/b[$2]:"")},将这些行与结果一起打印出来。如果计数器b[]大于第二列的计数器,则打印平均值。

测试

$ awk 'FNR==NR {a[$2]+=$4; b[$2]++; next} {printf "%s %s\n", $0, (b[$2]>1?a[$2]/b[$2]:"")}' file file
Probe Name Sec_Name Number 
A_1 One Bla 2 3
A_2 One Bla 5 3
A_3 One Bla 2 3
B_1 Two bli 1 
B_2 Third 6 

更新

根据Kent's great recommendation,您可以使用以下方式打印上次第二列显示时的平均值:

awk 'FNR==NR {a[$2]+=$4; b[$2]++; c[$2]=FNR; next}
                                  ^^^^^^^^^^
     {printf "%s %s\n", $0, (b[$2]>1&&c[$2]==FNR?a[$2]/b[$2]:"")}' file file
                                    ^^^^^^^^^^^^

它在数组c[]中捕获上次第2个字段的行号。然后打印条件也检查它,以便它只打印平均值,如果它是最后一次出现第二列。

测试

$ awk 'FNR==NR {a[$2]+=$4; b[$2]++; c[$2]=FNR; next} {printf "%s %s\n", $0, (b[$2]>1&&c[$2]==FNR?a[$2]/b[$2]:"")}' a a
Probe Name Sec_Name Number 
A_1 One Bla 2 
A_2 One Bla 5 
A_3 One Bla 2 3
B_1 Two bli 1 
B_2 Third 6