我有一个巨大的数据文件,看起来像这样(但有~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
答案 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