So zählen Sie das Auftreten eines Musters in einer Linie

8

Ich habe eine Datei mit drei Spalten. Spalte 3 enthält Namen von Genen und sieht folgendermaßen aus:

Rv0729,Rv0993,Rv1408  
Rv0162c,Rv0761c,Rv1862,Rv3086  
Rv2790c

Wie kann ich die Anzahl der Gene in jeder Zeile drucken?

Saisha
quelle
Eine vierte Spalte? Was soll passieren, wenn diese Spalte bereits belegt ist (zweite Zeile in Ihrem Beispiel) oder wenn die anderen Spalten leer sind (letzte Zeile)?
Kusalananda
@Kusalananda Dieses Kriterium wurde aus meiner Anfrage entfernt :)
Saisha
Bei einem kurzen Blick zählen alle Antworten die durch Kommas getrennten Felder oder Zeichenfolgen, die mit dem Rv*Muster an einer beliebigen Stelle in der Zeile übereinstimmen , nicht nur in einer bestimmten Spalte. Ich möchte nur darauf hinweisen, dass Sie die Lösungen möglicherweise entsprechend ändern müssen, wenn Sie tatsächlich andere Daten in der Datei haben, die in der Frage hier nicht aufgeführt sind. (Oder klären Sie die Frage.)
ilkkachu

Antworten:

10

Sie möchten einfach eine Spalte mit der Anzahl der darin enthaltenen Spalten hinzufügen. Dies kann erfolgen mit awk:

$ awk -F ',' '{ printf("%d,%s\n", NF, $0) }' data.in
3,Rv0729,Rv0993,Rv1408
4,Rv0162c,Rv0761c,Rv1862,Rv3086
1,Rv2790c

NFist eine awkVariable, die die Anzahl der Felder (Spalten) im aktuellen Datensatz (Zeile) enthält. Wir drucken diese Zahl gefolgt von einem Komma und dem Rest der Zeile für jede Zeile.

Eine Alternative (gleiches Ergebnis, sieht aber vielleicht etwas sauberer aus):

$ awk -F ',' 'BEGIN { OFS=FS } { print NF, $0 }' data.in

FSist das Feldtrennzeichen, awkmit dem jeder Datensatz in Felder aufgeteilt wird, und wir setzen dies auf ein Komma mit -F ','in der Befehlszeile (wie in der ersten Lösung). OFSist das Trennzeichen für das Ausgabefeld , und wir setzen es so, wie es FSvor dem Lesen der ersten Eingabezeile ist.

Kusalananda
quelle
5

Wenn Sie die Anzahl der Vorkommen des Rv[0-9]{4}c?Musters im Gegensatz zur Anzahl der durch Kommas getrennten Felder zählen möchten, wie das Thema Ihrer Frage vorschlägt, können Sie Folgendes tun:

 awk '{print gsub(/Rv[0-9]{4}c?/, "&"), $0}'
Stéphane Chazelas
quelle
4

Ein Perl-Ansatz:

$ perl -F, -pae 's/^/$#F+1 . ","/e' file
3,Rv0729,Rv0993,Rv1408  
4,Rv0162c,Rv0761c,Rv1862,Rv3086  
1,Rv2790c

Die -aMarken perlverhalten sich wie awkund teilen jede Eingabezeile in der von angegebenen Zeichenfolge auf -Fund speichern die resultierenden Felder im Array @F. Daher ist $#Fdies der höchste Array-Index in @Fund, da Arrays bei zu zählen beginnen 0, $#F+1die Gesamtzahl der Elemente im Array. Die -pMittel "jede Eingabezeile drucken, nachdem das von gegebene Skript angewendet wurde -e. Der s///ist der Substitutionsoperator und hier ersetzen Sie den Anfang der Zeile ( ^) durch die Anzahl der Felder + 1 und ein Komma ( $#F+1 . ",").

terdon
quelle
1

Ihre Frage besagt, dass Spalte 3 Namen von Genen enthält. Ich gehe davon aus, dass Ihre tatsächliche Eingabe wie folgt lautet:

column1 column2 Rv0729,Rv0993,Rv1408  
column1 column2 Rv0162c,Rv0761c,Rv1862,Rv3086  
column1 column2 Rv2790c

Jeder Genname in Spalte 3 enthält einen führenden RvTeilstring. So können wir sie in Python so zählen:

$ python -c  "import sys;print map(lambda x: x.split()[2].count('Rv'),sys.stdin.readlines())"  < input.txt               
[3, 4, 1]

Die resultierende Liste zeigt die Anzahl der Gene in jeder Zeile in ihrer jeweiligen Reihenfolge. Wenn wir es ausführlicher gestalten und die Möglichkeit einschließen möchten, dass Gene möglicherweise keine "Rv" -String enthalten (aber die Annahme beibehalten, dass Spalte3 eine durch Kommas getrennte Wertzeichenfolge ist), können wir auch Folgendes tun:

#!/usr/bin/env python
import sys
with open(sys.argv[1]) as fd:
    for index,line in enumerate(fd):
        columns = line.strip().split()
        num_genes=len(columns[2].split(","))
        print("Line "+str(index)+" contains "+str(num_genes))

Testlauf:

$ ./count_genes.py input.txt                                                                                             
Line 0 contains 3
Line 1 contains 4
Line 2 contains 1
Sergiy Kolodyazhnyy
quelle