separe um dado de uma coluna por caracteres repetidos em tantas colunas quanto os caracteres uniq

separe um dado de uma coluna por caracteres repetidos em tantas colunas quanto os caracteres uniq

Então, eu tenho um arquivo assim:

  • file1: três colunas

    SNP Id Geno
    1 a AB
    2 a AB
    3 a BB
    . . .
    . . .
    . . .
    1 b AB
    2 b BB
    3 b AB
    . . .
    . . .
    . . .
    1 c AA
    2 c AB
    3 c AA
    . . .
    . . .
    . . .
    

e preciso de um arquivo como esse:

  • file2: tantas colunas quantos os números de ID com seus genótipos

    SNP Genoa Genob Genoc . . .
    1 AB AB AA
    2 AB BB AB
    3 BB AB AA
    . . . .
    . . . .
    . . . .
    

Responder1

Este script não é fino nem legível, mas funciona e ao contrário da awksolução já postada também gera a linha de cabeçalho:

sed 'G;s/^SNP.*/SNP/
/^1 /s/ \([^ ]*\) .*SNP[^[:cntrl:]]*/& Geno\1/
s/^\([0-9]*\) [^ ]*\( [AB]*\)\n\(.*\n\1 [AB ]*\)/\3\2/
s/^\([0-9]*\) [^ ]*\( [AB]*\)\(\n\)\(.*\)/\4\3\1\2/
h
$!d' file1 > file2

Sem ser um awkusuário, acho que você pode expandir a awksolução fornecida assim para gerar a linha de cabeçalho também:

awk '{if ($1==1) h=h" Geno"$2
if ($1!="SNP") g[$1]=g[$1]" "$3}
END {print "SNP"h; for (i in g) print i g[i]}' file1 > file2

Responder2

awk '{g[$1] = g[$1] " " $3}
     END {for (i in g) print i g[i]}' < file1 > file2

Ou para preservar a ordem:

awk '! ($1 in g) {snp[n++] = $1}
     {g[$1] = g[$1] " " $3}
     END {for (i = 0; i < n; i++) print snp[i] g[snp[i]]}' < file1 > file2

Para incluir o cabeçalho "SNP Genoa Genob...":

awk 'NR == 1 {header = $1; prefix = $3; next}
     first == "" {first = "" $1}
     $1 == first {header = header " " prefix $2}
     ! ($1 in g) {snp[n++] = $1}
     {g[$1] = g[$1] " " $3}
     END {
       print header
       for (i = 0; i < n; i++) print snp[i] g[snp[i]]
     }' < file1 > file2

Responder3

perl -lane '
   next if $. == 1;                                     # skip header
   $A[@A] = $F[1] if /^1\h/;                            # populate new header
   push @{$h{$F[0]}}, $F[2]}{$,="\t";                   # OFS = tab
   print q/SNP/, map { "Geno$_" } @A;                   # new header print
   print $_, @{$h{$_}} for sort { $a <=> $b } keys %h;  # result
' gene.data

Armazene aqui o terceiro campo $F[2]em um AoA (array_of_array). No final, classificamos numericamente as chaves hash e imprimimos os dados.

sed -e '
   1d; # monospace lines
   s/[[:blank:]]\{1,\}/\t/g;s/^[[:blank:]]*//;s/[[:blank:]]*$//
   H;g
   #  1   2                            3                     4
   s/\(\n\(.*\n\)\{0,1\}\)1[[:blank:]]\([^[:space:]]\{1,\}\)\([[:blank:]][^[:space:]]\{1,\}\)$/\tGeno\3\1\n1\4/
   /\(\n[^[:space:]]\{1,\}[[:blank:]]\)[^[:space:]]\{1,\}[[:blank:]]\([^[:space:]]\{1,\}\)$/s//\1\2/
   y/\n_/_\n/
   s/_\([0-9]\{1,\}\)\([^_]*\)_\(.*_\)\{0,1\}\1\([[:blank:]][^_]*\)/_\1\2\4_\3/
   y/\n_/_\n/
   h;$!d
   s/\n*$//
   s/\n\(\n\)/\1/
   s/^[[:blank:]]/SNP&/
' gene.data

Resultado

SNP     Genoa   Genob   Genoc
1       AB      AB      AA
2       AB      BB      AB
3       BB      AB      AA

informação relacionada