如何使用awk选择基于一列的最大值和按第二列分组的行?

时间:2016-06-24 07:55:00

标签: bash awk gawk

我的数据如下:

1   161   a
1   48    b
1   30    c
2   199   d 
2   1306  d
2   1290  d
2   81    d
2   51    e
2   82    e
2   93    e
3   64    e
3   99    f
3   123   f

对于第三列中的每个值,我想在第2列中选择具有最大值的行,并在第1列中选择分组。 所以期望的输出是

1   161   a
1   48    b
1   30    c
2   1306  d
2   93    e
3   64    e
3   123   f

按第一列分组我的意思是我想要第1列中所有不同值的结果。我尝试使用的是

awk '$2>max[$3]{max[$3]=$2; row[$3]=$0} END{for (i in row) print row[i]}' file

我得到以下结果

1   161   a
1   48    b
1   30    c
2   1306  d
2   93    e
3   123   f

但我错过了结果中的以下行

3   64  e

这是因为这一个班轮正在为第3列中的不同值选择第2列中的最大值,如何按第1列对此进行分组以获得第1列中每个值的所需结果?

4 个答案:

答案 0 :(得分:4)

我认为您可以使用$1$3的复合键:

awk '$2 > max[$1$3] { max[$1$3]=$2;
                      row[$1$3]=$0 }
                END { for (i in row) print row[i] }' file

答案 1 :(得分:2)

在评论中对here的想法进行了肯定,通过一些额外的操作,下面的逻辑将按照OP的要求行事。

sort -r -n -k2 < file| awk '!x[$1 FS $3]++' | sort -k1
  • 想法是先按升序对文件进行排序(sort -n -k2)并将其反转(-r)在第2列(现在将按降序排列)
  • awk '!x[$1 FS $3]++通过第1列和第3列对该内容进行分组,sort -k1按第1列内容对其进行排序/分组

答案 2 :(得分:0)

在第二列中找到最大值和最小值的最简单命令分别是

sort -nrk2 data.txt | awk'NR == 1 {print $ 2}' sort -nk2 data.txt | awk'NR == 1 {print $ 2}'

答案 3 :(得分:0)

您可以在不awk的情况下执行此操作。我不得不使用tr -s " "来抑制字段/列之间的多个空格分隔符。下面的重要一行是第二行。

cat $file | tr -s " " \
| sort -k2nr,2 | sort -k1,1 -k3,3 -u | sort -k3,3 -k1,1 -k2nr,2 \
| tr " " "\t"

实际上,最后的-k2nr,2甚至不是必需的。您可以使用--stable保留初始排序顺序。所有的道路都通往罗马。