Trennen Sie einen Datensatz aus einer Spalte durch wiederholte Zeichen in so viele Spalten wie die Anzahl der eindeutigen Zeichen

Trennen Sie einen Datensatz aus einer Spalte durch wiederholte Zeichen in so viele Spalten wie die Anzahl der eindeutigen Zeichen

Also, ich habe eine Datei wie diese:

  • file1: drei Spalten

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

und ich brauche eine Datei wie diese:

  • file2: so viele Spalten wie ID-Nummern mit ihren Genotypen

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

Antwort1

Dieses Skript ist weder schlank noch lesbar, aber es funktioniert und erzeugt im Gegensatz zur awkbereits geposteten Lösung auch die Kopfzeile:

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

Ich schätze, dass Sie als awkBenutzer die angegebene Lösung wie folgt erweitern können awk, um auch die Kopfzeile zu generieren:

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

Antwort2

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

Oder um die Reihenfolge beizubehalten:

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

So schließen Sie die Kopfzeile „SNP Genoa Genob...“ ein:

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

Antwort3

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

Hier speichern wir das 3. Feld $F[2]in einem AoA (Array_of_Array). Am Ende sortieren wir die Hash-Schlüssel numerisch und drucken die Daten aus.

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

Ergebnis

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

verwandte Informationen