代码之家  ›  专栏  ›  技术社区  ›  user2300940

由其他两列分组的文件的一列合计

  •  -1
  • user2300940  · 技术社区  · 7 年前

    我想根据第一个“-”号之前的类似字符串对行求和。我试过R,但文件太大了。

    在里面

    URS0000001D42-antisense_ATTTCGGTTGGGGAA 208
    URS0000001D42-antisense_CATGCTCATAAGGAA 24
    URS0000003804-lncRNA_GAGATCCTGGGTTTT    6
    URS0000003CBA-antisense_CTGGGCTAGTGAACGCGGCGAAGT        14
    URS0000003F61-antisense_AAAGTGCACTTGGACG        55
    URS0000003F61-antisense_AAAGTGCACTTGGACGAA      4
    

    出来

    URS0000001D42-antisense 232
    URS0000003804-lncRNA 6
    URS0000003CBA-antisense 14
    URS0000003F61-antisense 59
    
    3 回复  |  直到 7 年前
        1
  •  1
  •   Juan Diego Godoy Robles    7 年前

    使用 awk :

    awk '{a[$1]+=$NF}END{for (i in a){print i,a[i]}}' FS='_| ' file
    

    后果

    URS0000003804-lncRNA 6
    URS0000001D42-antisense 232
    URS0000003CBA-antisense 14
    URS0000003F61-antisense 59
    
        2
  •  1
  •   pitseeker    7 年前

    使用perl哈希:

    脚本:

    #!/usr/bin/env perl
    
    while (my ($key, $value) = <> =~ /^(.+)_.+\s+(\d+)/) {
      $hash{$key} += $value;
    }
    
    while(my($k, $v) = each %hash) { 
      print "$k\t$v\n";
    }
    

    称之为:

    $ script.pl < file
    URS0000003CBA-antisense:  14
    URS0000003F61-antisense:  59
    URS0000003804-lncRNA:  6
    URS0000001D42-antisense:  232
    $
    

    可能也可以做得更短。;-)

    here's 这是一个非常相似的任务的另一个问题,有很多答案。

        3
  •  0
  •   Borodin    7 年前

    下面是一个Perl解决方案

    use strict;
    use warnings 'all';
    
    my %data;
    
    while ( <DATA> ) {
        my ( $f1, $f2, $seq, $n ) = m/[^-_\s]+/g;
        $data{$f1}{$f2} += $fields[3];
    }
    
    for my $f1 ( keys %data ) {
    
        for my $f2 ( keys %{ $data{$f1} } ) {
            printf "%s-%s %d\n", $f1, $f2, $data{$f1}{$f2};
        }
    }
    
    __DATA__
    URS0000001D42-antisense_ATTTCGGTTGGGGAA 208
    URS0000001D42-antisense_CATGCTCATAAGGAA 24
    URS0000003804-lncRNA_GAGATCCTGGGTTTT    6
    URS0000003CBA-antisense_CTGGGCTAGTGAACGCGGCGAAGT        14
    URS0000003F61-antisense_AAAGTGCACTTGGACG        55
    URS0000003F61-antisense_AAAGTGCACTTGGACGAA      4
    

    输出

    URS0000003CBA-antisense 14
    URS0000001D42-antisense 232
    URS0000003804-lncRNA 6
    URS0000003F61-antisense 59
    

    输出是无序的,因为Perl哈希没有固有的顺序。要将输出保持在与输入数据相同的顺序上有点困难,因为有必要为每个哈希保留一个数组,以跟踪密钥创建的顺序

    use strict;
    use warnings 'all';
    
    my ( %data, @keys );
    
    while ( <DATA> ) {
    
        my ( $f1, $f2, $seq, $n ) =/ [^-_\s]+/g;
    
        push @keys, $f1 unless $data{$f1};
    
        my $h2 = $data{$f1} //= {};
    
        push @{ $h2->{''} }, $f2 unless $h2->{$f2};
    
        $h2->{$f2} += $n;
    }
    
    for my $f1 ( @keys ) {
    
        for my $f2 ( @{ $data{$f1}{''} } ) {
            printf "%s-%s %d\n", $f1, $f2, $data{$f1}{$f2};
        }
    }
    
    __DATA__
    URS0000001D42-antisense_ATTTCGGTTGGGGAA 208
    URS0000001D42-antisense_CATGCTCATAAGGAA 24
    URS0000003804-lncRNA_GAGATCCTGGGTTTT    6
    URS0000003CBA-antisense_CTGGGCTAGTGAACGCGGCGAAGT        14
    URS0000003F61-antisense_AAAGTGCACTTGGACG        55
    URS0000003F61-antisense_AAAGTGCACTTGGACGAA      4
    

    输出

    URS0000001D42-antisense 232
    URS0000003804-lncRNA 6
    URS0000003CBA-antisense 14
    URS0000003F61-antisense 59