separe un dato de una columna mediante caracteres repetidos en tantas columnas como caracteres únicos

separe un dato de una columna mediante caracteres repetidos en tantas columnas como caracteres únicos

Entonces tengo un archivo así:

  • file1: tres columnas

    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
    . . .
    . . .
    . . .
    

y necesito un archivo como ese:

  • file2: tantas columnas como números de DNI con sus genotipos

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

Respuesta1

Este script no es delgado ni legible, pero funciona y, a diferencia de la awksolución ya publicada, también genera la línea de encabezado:

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

Sin ser un awkusuario, supongo que puedes expandir la awksolución dada de esta manera para generar también la línea de encabezado:

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

Respuesta2

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

O para preservar el orden:

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 el encabezado "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

Respuesta3

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

Aquí almacene el tercer campo $F[2]en un AoA (array_of_array). Al final, ordenamos las claves hash numéricamente e imprimimos los datos.

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

información relacionada