根据第 2 列 AWK / BASH 中的最小值对两列文件进行重复数据删除
Deduplicate two column file based on minimum value in column 2 AWK / BASH
我手头有一个看起来像这样的文件(由制表符分隔,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
如上例所示,文件中的某些行可能与其他行完全重复,我不确定这将如何影响解决方案。
我在 Whosebug 上查找过类似的解决方案,例如:Uniq in awk; removing duplicate values in a column using awk,但未能采用它们。
如果有人能提供帮助,我会很高兴。
我更喜欢使用 AWK,但 BASH 也是一个选项。我正在使用 MacOSX Yosemite.
如果有人能帮上忙,我会很高兴。
谢谢你和亲切的问候,
保罗
您可以获得显示的结果:
awk '{if (!( in a)) a[] = } 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 (!( in a)) a[] = ; else if (a[] > ) a[] = }
END { for (key in a) print key, a[key] }'
输出:
denovo0 90.2
denovo1 96.9
denovo10 91.5
denovo100 94.6
您还可以通过查找每个键的最大值来获取问题中的示例输出;碰巧最大值也是样本数据中每个键的第一个。
awk '{ if (!( in a)) a[] = ; else if (a[] < ) a[] = }
END { for (key in a) print key, a[key] }'
输出:
denovo0 90.2
denovo1 97.7
denovo10 93.8
denovo100 95.3
使用 awk 应该很简单,例如:
awk '{if(!( in a)){print; a[]++}}' myfile
如果第一个字段($1)不在a数组中,打印该行并将第一个字段添加到a。下次我们看到该字段时,它将在数组中,因此不会被打印出来。
我假设您打算让输出显示与第一列中出现的每个字符串关联的最低值。我还假设第一列中的输入是 sorted(如您的示例所示)。
这种方法使输出的顺序与输入中的顺序相同:
$ awk '==last{if (<min)min=;next} last{print last"\t"min} {last=;min=} END{print last"\t"min}' file
denovo0 90.2
denovo1 96.9
denovo10 91.5
denovo100 94.6
这适用于大型数据集,因为它不需要将所有输出一次保存在内存中。但是,如果您的输入文件未按第一列排序,请使用 Jonathan Leffler 的方法。
使用 unix 管道的更简单的解决方案。
sort -k1,1 -k2,2n inputFile | awk '!seen[]++' > outputFile
我手头有一个看起来像这样的文件(由制表符分隔,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
如上例所示,文件中的某些行可能与其他行完全重复,我不确定这将如何影响解决方案。
我在 Whosebug 上查找过类似的解决方案,例如:Uniq in awk; removing duplicate values in a column using awk,但未能采用它们。
如果有人能提供帮助,我会很高兴。
我更喜欢使用 AWK,但 BASH 也是一个选项。我正在使用 MacOSX Yosemite.
如果有人能帮上忙,我会很高兴。
谢谢你和亲切的问候,
保罗
您可以获得显示的结果:
awk '{if (!( in a)) a[] = } 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 (!( in a)) a[] = ; else if (a[] > ) a[] = }
END { for (key in a) print key, a[key] }'
输出:
denovo0 90.2
denovo1 96.9
denovo10 91.5
denovo100 94.6
您还可以通过查找每个键的最大值来获取问题中的示例输出;碰巧最大值也是样本数据中每个键的第一个。
awk '{ if (!( in a)) a[] = ; else if (a[] < ) a[] = }
END { for (key in a) print key, a[key] }'
输出:
denovo0 90.2
denovo1 97.7
denovo10 93.8
denovo100 95.3
使用 awk 应该很简单,例如:
awk '{if(!( in a)){print; a[]++}}' myfile
如果第一个字段($1)不在a数组中,打印该行并将第一个字段添加到a。下次我们看到该字段时,它将在数组中,因此不会被打印出来。
我假设您打算让输出显示与第一列中出现的每个字符串关联的最低值。我还假设第一列中的输入是 sorted(如您的示例所示)。
这种方法使输出的顺序与输入中的顺序相同:
$ awk '==last{if (<min)min=;next} last{print last"\t"min} {last=;min=} END{print last"\t"min}' file
denovo0 90.2
denovo1 96.9
denovo10 91.5
denovo100 94.6
这适用于大型数据集,因为它不需要将所有输出一次保存在内存中。但是,如果您的输入文件未按第一列排序,请使用 Jonathan Leffler 的方法。
使用 unix 管道的更简单的解决方案。
sort -k1,1 -k2,2n inputFile | awk '!seen[]++' > outputFile