awk--对于第一列中的每个键,搜索所有其他列并找到最小条目

时间:2014-07-20 02:50:45

标签: perl awk

我有一个巨大的数据文件,看起来像这样(但有~115列,超过400行):

testing.txt

    agg10.cov   agg11.cov   agg12.cov   agg13.cov   
1:12418403  1.85E-01    4.20E-01    1.13E-01    3.27E-03    
1:23941533  3.07E-02    5.89E-04    1.92E-02    7.25E-01    
MC5R    3.32E-03    9.29E-02    3.89E-02    3.08E-01    
MC5R    1.80E-02    4.08E-02    3.51E-02    2.33E-01    
MC5R    1.17E-03    4.25E-03    2.88E-03    1.22E-02    
1:34128320  2.37E-02    1.64E-01    8.19E-03    2.88E-01    
1:35547072  2.18E-02    6.34E-02    3.47E-02    3.32E-02    
1:56    5.49E-02    6.14E-01    8.07E-01    1.82E-01    
1:56    2.98E-02    1.59E-02    2.60E-02    7.06E-01    

对于第一列中的每个条目,我需要搜索其余每个列,并为以该条目开头的所有行取最小值。它需要按行数和列数进行扩展,如果可能的话,不需要过多地重新输入每个列标识符。

除了excel中的min(if)之外,我还没有尝试过任何东西。这往往会很快打破,因为我的计算机处理的数据太多了。我知道一点点perl和一点点awk。

我正在玩这个,但我不知道如何让它可以扩展到可变数量的列

awk 'NR==1{print;next}
{s[$1]=!s[$1]||$2<s[$1]?$2:s[$1];t[$1]=!t[$1]||$3<t[$1]?$3:t[$1];u[$1]=!u[$1]||$4<u[$1]?$4:u[$1]}
END{for(x in s)print x,s[x],t[x],u[x]}' testing.txt

2 个答案:

答案 0 :(得分:1)

NF会返回一行中的列数,您可以使用i引用行$i。如果你使用gawk,那么有多维数组(最小[column1] [column_number])。如果没有,您可以通过连接column1和column_number(在下面实现)来模拟它。

{
    if (NR == 1) {
        print
        next;
    }

    column1s[$1] = 1;
    for(i=2; i<=NF; i++) {
        key = i "::" $1
        if (!(key in min) || $i < min[key]) {
            min[key] = $i;
        }
    }
}

END {
    for (k in column1s) {
        row = k;

        for (i=2; i<=5; i++) {
            key = i "::" k;
            row = row "\t" min[key];
        }

        print row;
    }
}

由于它有点长,你可以把它放在一个文件中并像下面那样调用它:

awk -f script.awk testing.txt

答案 1 :(得分:0)

这是一个可能的Perl解决方案。

#!/usr/bin/perl
use strict;
use warnings;
use List::Util 'min';

my $file = 'testing.txt';
open my $fh, "<", $file or die "Unable to open '$file' $!";

my @cols = split ' ', <$fh>;

my %data;
while (<$fh>) {
    my ($key, @vals) = split;
    push @{ $data{$key} }, @vals;
}
close $fh or die $!;

while ( my ($key, $aref) = each %data) {
    printf "%-12s %s\n", $key, min(@$aref);
}

自v 5.08以来,List :: Util已成为perl核心的一部分。

此数据集的输出为

1:56         1.59E-02
1:34128320   8.19E-03
1:23941533   5.89E-04
1:35547072   2.18E-02
MC5R         1.17E-03
1:12418403   3.27E-03