根据第2列AWK / BASH中的最小值对两个列文件进行重复数据删除

时间:2015-01-31 06:45:10

标签: bash shell awk

我手边有一个看起来像这样的文件(由标签,2个字段分隔):

    denovo0  90.2
    denovo1  97.7
    denovo1  97.7
    denovo1  96.9
    denovo10     93.8
    denovo10     92.2
    denovo10     91.5
    denovo100    95.3
    denovo100    95.3
    denovo100    94.6

我想在第一个字段中仅保留第二列中具有最低值的唯一字符串:

    denovo0  90.2
    denovo1  96.9
    denovo10     91.5
    denovo100    94.6

从上面的示例中可以看出,文件中的某些行可能与其他行完全重复,我不确定这会如何影响解决方案。

我在StackOverflow上查找了类似的解决方案,例如Uniq in awk; removing duplicate values in a column using awk,但无法采用它们。

如果有人可以提供帮助,我会很高兴。

我更喜欢使用AWK,但BASH也是一种选择。我正在与MacOSX Yosemite合作。

如果有人可以提供帮助,我会很高兴。

谢谢你,亲切的问候,

4 个答案:

答案 0 :(得分:1)

您可以通过以下方式获得结果:

awk '{if (!($1 in a)) a[$1] = $2} END { for (key in a) print key, a[key] }'

输出:

denovo0 90.2
denovo1 97.7
denovo10 93.8
denovo100 95.3

对于所描述的结果(第1列中每个键的第2列中的最小值),您可以使用:

awk '{ if (!($1 in a)) a[$1] = $2; else if (a[$1] > $2) a[$1] = $2 }
     END { for (key in a) print key, a[key] }'

输出:

denovo0 90.2
denovo1 96.9
denovo10 91.5
denovo100 94.6

您还可以通过查找每个键的最大值来获取问题中的示例输出;碰巧的是,最大值也是样本数据中每个键的第一个值。

awk '{ if (!($1 in a)) a[$1] = $2; else if (a[$1] < $2) a[$1] = $2 }
     END { for (key in a) print key, a[key] }'

输出:

denovo0 90.2
denovo1 97.7
denovo10 93.8
denovo100 95.3

答案 1 :(得分:1)

使用awk这应该很简单:

 awk '{if(!($1 in a)){print; a[$1]++}}' myfile

如果第一个字段($ 1)不在数组中,则打印该行并将第一个字段添加到a。下次我们看到该字段时,它将在数组中,因此不会被打印。

答案 2 :(得分:1)

我假设你打算让输出显示与第一列中出现的每个字符串相关联的最低值。我还假设第一列中的输入排序(如示例中所示)。

此方法使输出保持与输入中显示的顺序相同:

$ awk '$1==last{if ($2<min)min=$2;next} last{print last"\t"min} {last=$1;min=$2} END{print last"\t"min}' file
denovo0 90.2
denovo1 96.9
denovo10        91.5
denovo100       94.6

这将适用于大型数据集,因为它不需要将所有输出一次性保存在内存中。但是,如果您的输入文件未在第一列上排序,请使用Jonathan Leffler的方法。

答案 3 :(得分:0)

使用unix管道的解决方案更简单。

sort -k1,1 -k2,2n inputFile | awk '!seen[$1]++' > outputFile