Ich habe Datei1 wie folgt:
CHR SNP TEST A1 A2 GENO O(HET) E(HET) P
0 AFFX-SNP-000541 ALL 0 0 0/0/0 nan nan 1
0 AFFX-SNP-000541 AFF 0 0 0/0/0 nan nan NA
0 AFFX-SNP-000541 UNAFF 0 0 0/0/0 nan nan NA
0 AFFX-SNP-002255 ALL 0 0 0/0/0 nan nan 1
0 AFFX-SNP-002255 AFF 0 0 0/0/0 nan nan NA
0 AFFX-SNP-002255 UNAFF 0 0 0/0/0 nan nan NA
1 rs12103 ALL C T 55/250/317 0.4019 0.4113 0.5596
1 rs12103 AFF C T 0/0/0 nan nan NA
1 rs12103 UNAFF C T 0/0/0 nan nan NA
1 rs12103_1247494 ALL C T 55/250/321 0.3994 0.4097 0.5581
1 rs12103_1247494 AFF C T 0/0/0 nan nan NA
1 rs12103_1247494 UNAFF C T 0/0/0 nan nan NA
Und file2 wie:
CHR SNP A1 A2 MAF NCHROBS
0 AFFX-SNP-000541 0 0 NA 0
0 AFFX-SNP-002255 0 0 NA 0
1 rs12103 C T 0.2894 1244
1 rs12103_1247494 C T 0.2875 1252
Ich möchte Datei2 mit Datei1 basierend auf dem SNP-Namen und dem TEST == ALL zusammenführen und CHR, SNP, P und MAF in der Ausgabedatei3 behalten. Kennt jemand den besten Weg dafür in der Terminal (Unix) Shell?
Eine gewünschte Ausgabe wäre:
CHR SNP MAF P
0 AFFX-SNP-000541 NA 1
0 AFFX-SNP-002255 NA 1
1 rs12103 0.2894 0.5596
1 rs12103_1247494 0.2875 0.5581
shell
terminal
join
bioinformatics
Dadong Zhang
quelle
quelle
Antworten:
Mit Hilfe dieser Antwort
Um auch den Header zu erhalten, fügen Sie diesen einfach am Anfang des Skripts hinzu:
Erläuterung:
Wenn zwei Dateien an awk übergeben werden, werden sie zunächst nacheinander verarbeitet. Hier sind zwei Variablen wichtig:
NR
Ist die Zeilennummer vom Anfang desawk
Befehls undFNR
die Zeilennummer vom Anfang der aktuellen Datei. Das heißt, wenn die erste Datei verarbeitet wird (hier Datei2)NR
undFNR
denselben Wert hat, der der Wert der aktuell verarbeiteten Zeile ist. Aber wenn awk zur zweiten Datei übergeht,FNR
wird auf 1 zurückgesetzt, so dassNR
undFNR
nicht mehr gleich sind. Damit ist der TestFNR==NR
ein Trick, um zu wissen, ob die verarbeitete Datei die erste ist oder nicht.Schauen wir uns also den Code an. Die Bedingung
FNR==NR && FNR>1
testet, ob wir die erste Datei und nicht die erste Zeile verarbeiten. Wenn dies der Fall ist, speichern wir den Wert der fünften Spalte (MAF
) in einem Array, das durch die zweite Spalte ( ) indiziert ist,SNP
und dienext
Anweisung besagt, dass an die folgende Zeile übergeben werden soll.Wenn awk die zweite Datei (die Datei1 ist) verarbeitet, ist der erste Test falsch, so dass awk den zweiten Test versucht:
FNR > 1 && ($2 in a) && $3 == "ALL"
Das heißt: Nicht die erste Zeile der Datei + zweiter Spaltenwert (SNP
) ist in Tabellea
+ dritter Spaltenwert vorhanden (TEST
) ist"ALL"
. Wenn dies der Fall ist, werden die Spalten 1 (CHR
) und 2 (SNP
) gedruckt , derMAF
Wert aus dem Array mit abgerufena[$2]
und anschließend die Spalte 9 (P
) gedruckt .Durch Hinzufügen einer
BEGIN{...}
Anweisung am Anfang wird ein Befehl hinzugefügt, der erst ausgeführt wird, bevor die erste Zeile verarbeitet wird.quelle
BEGIN{print "CHR SNP MAF P"}
am Anfang hinzufügen .terdon erwähnt es nur mit coreutils, ein bescheidener vorschlag:
Ausgabe:
quelle
Hier ist eine Möglichkeit, dies zu tun (kopieren Sie diese direkt in Ihr Terminal):
Die Ausgabe sieht folgendermaßen aus:
Anmerkungen:
coreutils
, vielleicht eine Kombination aussort
,paste
undjoin
doch kann ich es nicht herausgefunden .-v OFS="\t"
wenn Sie dies nicht möchten.Erläuterung
awk
Zeile wird nur das erste, zweite und fünfte Feld des Headers von Datei 2 gedruckt, gefolgt vonP
. Dies ist der Header der neuen Datei.awk
druckt das 2. und das letzte ($NF
) Feld jeder Zeile von Datei1, in der sich das 3. Feld befindetALL
.while
Schleife geleitet, die die beiden Felder in die Variablen$snp
und einliest$p
.awk
mit der-v
Option bis zum letzten gegeben und drucken dann für jede Zeile der Datei2, wenn das zweite Feld ist$snp
, die Felder 1,2,5 und den aktuellen Wert von$p
.Hier ist ein Perl-Skript, das dasselbe tut:
quelle
Hier ist eine andere Möglichkeit:
Ausgabe:
Wie es funktioniert:
grep -F ALL file1 | sort -k2
druckt die mit der Zeichenfolge übereinstimmenden Zeilen ausALL
, diese werden dannsort
im 2. Feld bearbeitet:Dies wird dann im 2. Feld (
-j2
) mit Datei2 (ebenfalls im 2. Feld sortiert) verbunden,-o 2.1,2.2,2.5,1.9
um das 1., 2. und 5. Feld aus Datei2 und das 9. Feld aus der verarbeiteten Datei1 auszugeben:Da dies gruppiert wurde,
{...}
mitprintf %s\\n "CHR SNP MAF P"
dem der Header gedruckt wird, wird die gesamte Ausgabe mit verschönertcolumn -t
.Beachten Sie, dass bei dieser Lösung die Zeilenreihenfolge (aus Datei2) in der Ausgabe nicht beibehalten wird. Es kommt einfach vor, dass Ihre Datei2 bereits im 2. Feld sortiert wurde, aber wenn nicht, z.
und wenn Sie die Zeilenreihenfolge beibehalten möchten, können Sie die Zeilen in Datei2 nummerieren mit
nl -ba -nrz file2
:Bevor Sie sortieren und verbinden, passen Sie den Befehl an: Verbinden Sie das 2. Feld der (verarbeiteten) Datei1 und das 3. Feld der (verarbeiteten) Datei2 und geben Sie das Zeilennummernfeld + die gleichen Felder wie die erste Lösung aus.
join -1 2 -2 3 -o 2.1,2.2,2.3,2.6,1.9
Sortieren Sie dann die Ausgabe mitsort -k1n
und löschen Sie sie erneut Das erste Feld mitcut -d' ' -f2-
vor dem Weiterleiten der gesamten Ausgabe ancolumn -t
:Ausgabe:
Beachten Sie, dass beide Lösungen davon ausgehen, dass
ALL
in jeder Zeile nur ein Vorkommen vorkommt , nämlich das 3. Feld (daher dasgrep -F ALL
). Wenn dies nicht der Fall ist, müssen Sie einen regulären Ausdruck verwenden, um nur die relevanten Zeilen zu filtern.quelle