Ich habe eine Datendatei A.tsv
(Feldtrennzeichen = \t
):
id mutation
243 siti,toto,mumu
254
267 lala,siti,sojo
289 lala
und eine Vorlagedatei B.txt
(Feldtrennzeichen = nicht wichtig, da nur eine Zeile und eine Spalte):
lala,siti,mumu
Ich möchte eine neue Spalte in A.tsv
(aber in einer neuen Datei C.tsv
) mit dem Namen erstellen, in der nur die in der Spalte mutation_not
vorhandenen Mutationen gedruckt werden , die nicht in der Liste von vorhanden sind .mutation
A.tsv
B.txt
C.tsv
sieht aus wie das:
id mutation mutation_not
243 siti,toto,mumu toto
254
267 lala,siti,sojo sojo
289 lala
Ich habe es mit Exclude versucht:
awk 'NR==FNR {exclude[$0];next} !($0 in exclude)' file2 file1
aber ich habe kein gutes Ergebnis. Hast du eine Idee? Danke
Antwort1
awk ' BEGIN{OFS="\t"}
NR==FNR{ for(i=1; i<=NF; i++) muts[$i]; next }
FNR>1 { len=split($2, tmp, ",");
for(i=1; i<=len; i++) buf= buf (tmp[i] in muts?"":(buf==""?"":",") tmp[i])
}
{ print $0, (FNR==1?"mutation_not":buf); buf="" }' FS=',' fileB FS='\t' fileA
Antwort2
Verwendung von gawk
:
awk 'BEGIN{OFS="\t"; }
NR==FNR{ar[$1]=$1;next}
FNR==1{$(NF+1) = "mutation_not"}
FNR>1{split($2,a,",");
for(i in a) if (a[i] in ar) ;
else ncol[$1] = (ncol[$1])? ncol[$1] "," a[i] : a[i];
$(NF+1) = ncol[$1]}1'
RS="," B.txt RS="\n" FS="\t" A.tsv
Vorausgesetzt, alle Felder sind durch Kommas getrennt und bestehen nur aus einer Zeile, RS
wird Record Separator( ) für die Datei auf Komma gesetzt B.txt
.
NR==FNR{ar[$1]=$1;next
Erstellt ein Array, ar
das auf dem ersten Feld der ersten Datei indiziert ist.
FNR==1{$(NF+1) = "mutation_not"
Erstellt eine weitere Spalte im Kopfnamen.
FNR>1{split($2,a,",")
teilt das zweite Feld in A.tsv
ein Array auf a
.
Der nächste nicht vorhandene Eintrag B.txt
wird im ncol
Array gespeichert.
$(NF+1) = ncol[$1]
Erstellt eine weitere Spalte mit Elementen des Arrays ncol
.
Antwort3
Wir bilden ein set
s2 aus den kommagetrennten Elementen der Datei B.txt
Dann konvertieren wir für jede Zeile von A.tsv das zweite Feld in einen Satz und subtrahieren den s2-Satz davon. Dadurch erhalten wir die in A.tsv vorhandenen Mutationen, die in B.txt nicht zu finden sind. Dann fügen wir die resultierenden Elemente zusammen und drucken sie zusammen mit der Originalzeile aus.
python3 -c 'import sys
tsv,txt = sys.argv[1:]
fs,rs = "\t","\n"
ofs,dlm = fs,","
with open(txt) as fh, open(tsv) as f:
s2 = set(*list(map(lambda x:x.rstrip(rs).split(dlm),fh.readlines())))
for nr,ln in enumerate(f,1):
l = ln.rstrip(rs)
if nr == 1: print(l,"mutation_not",sep=ofs)
else:
F = l.split(ofs)
if len(F) < 2: print(l)
else: print(l,
dlm.join({*F[1].split(dlm)}-s2),sep=ofs)
' A.tsv B.txt
Ergebnis:
id mutation mutation_not
243 siti,toto,mumu toto
254
267 lala,siti,sojo sojo
289 lala
Dieses Mal verwenden wir den Gnu-Sed-Editor, um die Ergebnisse zu erhalten:
sed -Ee '
1{h;d;}
2s/\tmutation$/&&_not/;t
s/\t\S+$/&&,/;T;G
s/\t/\n/2;ta
:a
s/\n([^,]+),(.*\n(.*,)?\1(,|$))/\n\2/;ta
s/\n([^,\n]+),/\t\1\n/;ta
s/\n.*//
' B.txt A.tsv
Die Idee ist, dass die Btxt-Datei in hold gespeichert wird (vorausgesetzt, sie ist eine Zeile) und jede Zeile von A.tsv mit dem Inhalt von B.txt ergänzt wird. Die in B.txt gefundenen Mutationen werden abgehakt. Nachdem alle Mutationen überprüft wurden, wird die Zeile ausgedruckt.