Agrupando dados e atribuindo valores alfabéticos e numéricos para novas categorias

0

Eu tenho 4 colunas em meus dados delimitados por guias, preciso executar duas etapas.

  1. Agrupe os dados de acordo com as combinações das duas primeiras colunas.
  2. Toda vez que uma nova combinação de valores aparecer nos valores concatenados (col 4) para um grupo específico (col2), preciso atribuir uma nova categoria para essa linha, tanto alfabética quanto numericamente. Se essa combinação tiver sido encontrada anteriormente, a categoria correspondente será atribuída.

O arquivo de entrada se parece com

Line    Group   Name    Value
L1  G1  AX27    A
L1  G1  AX25    T
L1  G1  AX356   G
L1  G2  1X87    C
L1  G2  AX78    A
L1  G2  AX987   A
L1  G2  AX001B  A
L1  G3  A2XTR1  A
L1  G3  A2XTR2  T
L2  G1  AX27    A
L2  G1  AX25    T
L2  G1  AX356   C
L2  G2  1X87    G
L2  G2  AX78    T
L2  G2  AX987   A
L2  G2  AX001B  A
L2  G3  A2XTR1  A
L2  G3  A2XTR2  T
L3  G1  AX25    T
L3  G1  AX356   G
L3  G2  AX987   A
L3  G2  AX001B  A
L3  G3  A2XTR1  A
L3  G3  A2XTR2  C
L4  G1  AX27    A
L4  G1  AX25    T
L4  G1  AX356   G
L4  G3  A2XTR1  A
L4  G3  A2XTR2  C
L5  G3  A2XTR1  A
L5  G3  A2XTR2  T

O arquivo de saída intermediário parece

Line    Group   Collapsednames  Collapsedvalues
L1  G1  AX27 AX25 AX356 A T G 
L2  G1  AX27 AX25 AX356 A T C
L3  G1  AX25 AX356  T G
L4  G1  AX27 AX25 AX356 A T G 
L1  G2  1X87 AX78 AX987 AX001B  C A A A
L2  G2  1X87 AX78 AX987 AX001B  G T A A 
L3  G2  AX987 AX001B    A A
L1  G3  A2XTR1 A2XTR2   A T
L2  G3  A2XTR1 A2XTR2   A T
L3  G3  A2XTR1 A2XTR2   A C
L4  G3  A2XTR1 A2XTR2   A C
L5  G3  A2XTR1 A2XTR2   A T

Para todas as linhas (L1 a L4), G1 possui 3 combinações distintas (A T G, A T C, TG) onde a combinação (A T G) é duplicada. Assim, podemos atribuir as categorias alfabéticas A, B nad C a cada uma dessas combinações, onde A aparece duas vezes.

Assim, o resultado final será parecido com

Line    Group   Collapsednames  Collapsedvalues Alpha_Category  Number_Category
L1  G1  AX27 AX25 AX356 A T G   A   1
L2  G1  AX27 AX25 AX356 A T C   B   2
L3  G1  AX25 AX356  T G C   3
L4  G1  AX27 AX25 AX356 A T G   A   1
L1  G2  1X87 AX78 AX987 AX001B  C A A A A   1
L2  G2  1X87 AX78 AX987 AX001B  G T A A     B   2
L3  G2  AX987 AX001B    A A C   3
L1  G3  A2XTR1 A2XTR2   A T A   1
L2  G3  A2XTR1 A2XTR2   A T A   1
L3  G3  A2XTR1 A2XTR2   A C B   2
L4  G3  A2XTR1 A2XTR2   A C B   2
L5  G3  A2XTR1 A2XTR2   A T A   1

Aqui está o que eu tentei para o passo 1, mas não está funcionando. Não tenho a menor ideia de como proceder para o passo 2, depois de descobrir o primeiro passo.

awk -F"\t" '{if(a[$1$2]){a[$1$2]=a[$1$2]" "$3" "$4} else { a[$1$2]=$3"\t$4}} END {for (i in a) {print i"|"a[i]}}' file
    
por Hia Sen 31.10.2014 / 22:13

2 respostas

1

Não é tão fácil quanto parece. Solução Perl, tentei ser um pouco mais detalhado para tornar o código compreensível. O conhecimento básico de estruturas de dados aninhadas (hashes de hashes, hashes de matrizes) é necessário.

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

my (%collapsed, %groups);

<>;  # Skip header.
while (<>) {
    my ($line, $group, $name, $value) = split;
    push @{ $collapsed{$line}{$group}{names}  }, $name;
    push @{ $collapsed{$line}{$group}{values} }, $value;
    undef $groups{$group};
}

for my $group (sort keys %groups) {
    for my $line (sort keys %collapsed) {
        next unless $collapsed{$line}{$group};
        my $value = join q(), @{ $collapsed{$line}{$group}{values} };
        $groups{$group}{$value} ||= keys %{ $groups{$group} };
    }
}

for my $group (sort keys %groups) {
    for my $line (sort keys %collapsed) {
        next unless $collapsed{$line}{$group};
        my $value = join q(), @{ $collapsed{$line}{$group}{values} };
        say join "\t", $line, $group,
            join(' ', @{ $collapsed{$line}{$group}{names}  }),
            join(' ', @{ $collapsed{$line}{$group}{values} }),
            chr $groups{$group}{$value} - 1 + ord 'A',
            $groups{$group}{$value},
    }
}
    
por 31.10.2014 / 22:40
1

Awk solutions (muitas matrizes de associação), mas:

#!/usr/bin/awk

BEGIN {
SUBSEP=" "
split("A1^B2^C3^D4^E5",c,"^")
}

NR != 1 {
L[$1]=1
G[$2]=1
a[$1,$2]=a[$1,$2]" "$3
b[$1,$2]=b[$1,$2]" "$4
}

END {
for (g in G)
  {
  i=1
  for (l in L)
    {
    idx=b[l,g]
    if(d[idx]=="")
      d[idx]=c[i++]
    }
  } 
for (k in a)
  print k a[k] b[k],d[b[k]]
}

E faça o script acima:

awk -f script.awk tab.data | sort -k2,2 -k1,1

Se alguma explicação for necessária, por favor, pergunte nos comentários.

    
por 01.11.2014 / 02:37

Tags