Compare as linhas em um arquivo com a última coluna comum, mas diferente em outra coluna

0

Como comparar linhas consecutivas de um arquivo de texto onde a última coluna deve ser a mesma? E pelo menos um valor na 2ª última coluna deve ser incompatível.

  1. Primeiramente, a coluna 6 deve ser comparada no arquivo, se correspondida
  2. Em seguida, compare a coluna 4 para as linhas correspondentes. Na coluna 4, todos os valores não devem ser iguais, pelo menos um deve ser diferente. Aqui HSF1 e HIF1AN na linha número 1,2,3.

ARQUIVO DE ENTRADA

chr10   102979  103832  HSF1        305
chr10   102979  103832  HIF1AN  1   305
chr10   102979  103832  HSF1        305
chr10   103124438   103124851   HSF1        471
chr10   103124438   103124851   EGLN1   2   471
chr10   103969896   103970503   HSF1        472
chr10   103969896   103970503   HSF1        472
chr10   39135037    39142175    HSF1        335
chr10   4191461 4191936 HSF1        309
chr10   4191461 4191936 HSF1        309
chr10   42423355    42424014    HSF1        336

ARQUIVO DE SAÍDA

chr10   102979  103832  HSF1        305
chr10   102979  103832  HIF1AN  1   305
chr10   102979  103832  HSF1        305
chr10   103124438   103124851   HSF1        471
chr10   103124438   103124851   EGLN1   2   471
    
por Himanshu Singh 06.09.2018 / 17:29

2 respostas

2

Assumindo um arquivo separado por tabulação, você pode usar o GNU awk:

gawk -F'\t' 'NR == FNR {count[$6][$4]++; next} length(count[$6]) > 1' file file
chr10   102979  103832  HSF1        305
chr10   102979  103832  HIF1AN  1   305
chr10   102979  103832  HSF1        305
chr10   103124438   103124851   HSF1        471
chr10   103124438   103124851   EGLN1   2   471

Isso passa pelo arquivo duas vezes: a primeira vez que conta quantos valores de $ 4 ocorrem para cada $ 6; a segunda vez para produzir um registro se houver mais de 1 $ 4 valores para esse $ 6.

Provavelmente, isso poderia ser feito em uma única passagem, às custas da complexidade, do uso da memória e possivelmente da perda da ordem original.

Mesma lógica em perl

perl -Mautodie -e '
    open $f, "<", shift;
    while (<$f>) {
        @F = split /\t/;
        $c{ $F[5] }{ $F[3] }++;
    }
    # re-process the file
    seek $f, 0, 0;
    while (<$f>) {
        @F = split /\t/;
        print if scalar keys %{ $c{$F[5]} } > 1;
    }
' file
    
por 06.09.2018 / 18:12
0

Leia o arquivo linha por linha, armazene a linha em um buffer se a última coluna tiver o mesmo valor que todas as outras linhas no buffer, caso contrário, processe o buffer e esvazie-o.

Processar o buffer significa tentar encontrar pelo menos um par de linhas consecutivas que não compartilham o valor da quarta coluna e imprimir o buffer se for bem-sucedido.

Eu armazenei as linhas exatas no buffer junto com as colunas individuais para uma saída mais agradável e acesso mais fácil aos valores.

#!/usr/bin/perl
use warnings;
use strict;

sub process {
    my (@rows) = @_;
    my $different;
    for my $i (1 .. $#rows) {
        $different = 1, last if $rows[ $i - 1 ][4] ne $rows[$i][4];
    }
    print map "$_->[0]\n", @rows if $different;
}

my @buffer;
while (<>) {
    chomp;
    my @columns = split;
    if (! @buffer || $buffer[0][-1] == $columns[-1]) {
        push @buffer, [$_, @columns];
    } else {
        process(@buffer);
        @buffer = [$_, split];
    }
}
process(@buffer);
    
por 06.09.2018 / 17:57