Transformando palavras repetidas curtas em colunas em números

4

Eu quero transformar as pequenas palavras repetidas em colunas em números.

No exemplo a seguir, desejo alterar as palavras (with ONLY 2 LETTERS) na coluna 3 para números, para que AA seja alterado para 2 , AB ou BA para 1 , BB para 0 .

A primeira e a segunda coluna também podem conter AA , BB , AB e BA . Estes não devem ser alterados.

Colunas são separadas por " " ().

Id_animal Id_SNP Allele
ID01 rs01 AB
ID02 rs01 BA
ID03 rs01 AA
ID04 rs01 BB

A saída desejada é:

Id_animal Id_SNP Allele
ID01 rs01 1
ID02 rs01 1
ID03 rs01 2
ID04 rs01 0
    
por Amanda Botelho Alvarenga 15.07.2016 / 17:44

3 respostas

6
sed -i.bak -r 's/ AA$/ 2/;s/ (AB|BA)$/ 1/;s/ BB$/ 0/' input
  • -i.bak no lugar editando e criando um backup do arquivo original como input.bak
  • -r sintaxe de regex estendida
  • s/ AA$/ 2/ substitui sequência de caracteres final de 'AA' por 2
  • (AB|BA) ou AB ou BA
  • ; separa as diferentes operações substitutas
por 15.07.2016 / 18:07
7

com awk :

awk 'BEGIN {                                     
        t["AA"] = 2
        t["AB"] = t["BA"] = 1
        t["BB"] = 0
    }       
    $3 ~ /^[AB][AB]$/ { $3 = t[$3] }
    1' data.txt
    
por 15.07.2016 / 18:06
5

Se você quiser buscar sua solução de perl tentada, uma maneira seria usar um hash como uma simples tabela de pesquisa, por exemplo

%table = ("AA" => 2,"AB" => 1,"BA" => 1,"BB" => 0)

e, em seguida, use o valor de @F[2] como chave. Então, por exemplo

perl -alne '
  %table = ("AA" => 2,"AB" => 1,"BA" => 1,"BB" => 0); 
  print $.==1? $_ : join " ", @F[0,1], $table{@F[2]}
' file
Id_animal Id_SNP Allele
ID01 rs01 1
ID02 rs01 1
ID03 rs01 2
ID04 rs01 0

Na verdade, é uma maneira de fazer o caso simples que você descreveu usando tr do perl - já que ele retorna o número de transliterações. Assim, você pode usar o valor de retorno de tr /A// para conta o número de As:

perl -alne 'print $.==1? $_ : join " ", @F[0,1], @F[2] =~ tr/A//' file
Id_animal Id_SNP Allele
ID01 rs01 1
ID02 rs01 1
ID03 rs01 2
ID04 rs01 0

ou ainda mais simples (usando um regex para identificar a string de destino, em vez de dividir e unir)

perl -pe 's/\b[AB]{2}\b/$& =~ tr{A}{}/ge' file


Você poderia usar o mesmo truque com awk , ou seja,

awk 'FNR>1 {$3 = gsub(/A/,"",$3)}1' file
    
por 15.07.2016 / 18:58