【问题标题】:How to process duplicate columns with conditions如何处理有条件的重复列
【发布时间】:2011-09-26 17:16:52
【问题描述】:

如果第 2 列为空,我需要跳过具有相同第一列的所有行,然后对于其他列,我需要计算第 4 列相对于第 3 列的百分比?

输入:

T75PA       2   0   
T75PA   kk  4   1   
T240P       4   3   
T240P   test    3   3   
T240P   test2   3   1   
T245P   rr  8   1   
T245P   rr  33  1   
T226PA  fg  4   2   
T226PA  g   51  38  
T226PA  e   41  34

输出

T245P   rr  8   1   0.125
T245P   rr  33  1   0.03030303
T226PA  fg  4   2   0.5
T226PA  g   51  38  0.745098039
T226PA  e   41  34  0.829268293

【问题讨论】:

  • awk '{hsh[$1]=hsh[$0]}END{for (i in hsh){split(i, a, "\t");if (a[2]!= "") 打印 a[4] a[3] }}'

标签: perl shell awk


【解决方案1】:
awk '
    NR==FNR {if (NF < 4) blank[$1]; next}
    $1 in blank {next}
    {$(NF+1) = $4/$3; print}
' datafile datafile | column -t

既然你现在说字段分隔符是制表符:

awk '
    BEGIN {OFS = FS = "\t"}
    NR==FNR {if ($2 == "") blank[$1]; next}
    $1 in blank {next}
    {$5 = $4/$3; print}
' datafile datafile

【讨论】:

  • 感谢:我稍作修改,只检查第二列awk -F"\t" ' NR==FNR {if ($2==""){ blank[$1]; next}} $1 in blank {next} {$(NF+1) = $4/$3; print} '
【解决方案2】:

我假设您的数据是制表符分隔的。类似这样的 perl 脚本(我还没有测试过)...

my @data;
my %counts;
my %blanks;
while( my $line = <STDIN> )
{
    chop($line);
    my @rec = split( "\t", $line );
    push( @data, \@rec );
    $counts{$rec[0]}++;
    if( $rec[1] eq '' )
    {
        $blanks{$rec[0]}++;
    }
}
foreach my $rec ( @data )
{
    if( $counts{$rec->[0]} <= 1 || !$blanks{$rec->[0]} )
    {
        print join( "\t", @$rec, $rec->[3] / $rec->[2] ) . "\n";
    }
}

【讨论】:

    【解决方案3】:

    怎么样:

    #!/usr/bin/perl
    use Modern::Perl;
    
    
    my $re = qr/^([A-Z0-9]+)\s+?(\S+|\s+)\s+(\d+)\s+(\d+)\s*$/;
    my $skip = '';
    while (<DATA>) {
        chomp;
        if (my @l = $_ =~ /$re/) {
            if ($l[1] =~ /^\s+$/ || $skip eq $l[0]) {
                $skip = $l[0];
                next;
            }
            $skip = '';
            my $r = $l[3] / $l[2];
            say "$_\t$r";
        }
    }
    
    __DATA__
    T75PA       2   0   
    T75PA   kk  4   1   
    T240P       4   3   
    T240P   test    3   3   
    T240P   test2   3   1   
    T245P   rr  8   1   
    T245P   rr  33  1   
    T226PA  fg  4   2   
    T226PA  g   51  38  
    T226PA  e   41  34
    

    输出:

    T245P   rr  8   1       0.125
    T245P   rr  33  1       0.0303030303030303
    T226PA  fg  4   2       0.5
    T226PA  g   51  38      0.745098039215686
    T226PA  e   41  34  0.829268292682927
    

    【讨论】:

      【解决方案4】:

      尝试:

      awk '$2 ~ /[0-9]+/{for(i in res){if ($1 ~ res[i])delete res[i]};\
      rm[$1]=$1;next}\
      {if($1 in rm)next;ratio=$4/$3;res[NR]=$0"\t"ratio}\
      END{for (i in res)print res[i]}' file
      

      这将忽略所有少于四个条目的行, 对于所有其他条目,计算并连接配给 与条目并保存在数组 res 中。处理完后 文件,res 的条目被打印到标准输出。

      输出:

      T245P   rr  8   1       0.125
      T245P   rr  33  1       0.030303
      T226PA  fg  4   2       0.5
      T226PA  g   51  38      0.745098
      T226PA  e   41  34          0.829268
      

      HTH 克里斯

      【讨论】:

      • 这将包括应该排除的行,如果带有空白的行出现在匹配行之前。
      • 是否可以专门寻找第二列空白?
      • @Newbiee:是的,我改变了答案。现在它检查第二列是否包含数字。如果是这样,则必须缺少第二列。
      猜你喜欢
      • 2021-12-07
      • 2018-04-03
      • 2011-03-09
      • 2018-02-04
      • 2018-05-19
      • 1970-01-01
      • 2020-05-29
      • 1970-01-01
      相关资源
      最近更新 更多