2016-06-29 18 views
0

Ich schreibe ein Skript für bioinformatische Verwendung. Ich habe eine Datei mit 2 Spalten, in der Spalte A zeigt eine Nummer und Spalte B eine bestimmte Zeichenfolge. Ich brauche ein Skript, das die Datei nach der Zeichenfolge in Spalte B durchsucht. Wenn Duplikate gefunden werden, sollte die Zahl in Spalte A addiert werden, Duplikate sollten entfernt werden, und nur eine Zeile mit Spalte A mit der Summe und Spalte B String sollte bleiben.Duplikate finden und Summe der Werte in Spalte daneben geben (UNIX) (mit Lösung -> brauche schneller Weg)

Ich habe etwas geschrieben, das genau das tut, aber weil ich nicht wirklich ein Programmierer bin, bin ich sicher, dass es einen viel schnelleren Weg gibt. Meine Dateien enthalten manchmal 500k Zeilen und mein Code braucht solche Dateien. Bitte sehen Sie es sich an und sehen Sie, was ich ändern könnte, um die Dinge zu beschleunigen. Auch kann ich nicht uniq verwenden, weil für diese ID muss auch sort verwenden, aber die Reihenfolge der Zeilen müssen so bleiben, wie sie sind!

13 ABCD 
15 BGDA 
12 ABCD 
10 BGDA 
10 KLMN 
17 BGDA 

sollte

25 ABCD 
42 BGDA 
10 KLMN 

Dies macht es sich aber für eine Datei mit 500k Zeilen zu lange dauert:

for AASEQUENCE in file.txt; 
do 

    #see how many lines the file has and save that number in $LN 
    LN="$(wc -l $AASEQUENCE | cut -d " " -f 1)" 

    for ((i=1;i<=${LN};i++)); 
    do 
    #Create a variable that will have just the string from column B 
    #save it in $STRING 

    STRING="$(cut -f2 $AASEQUENCE | head -n $i| tail -n 1 | cut -f1)"; 

    #create $UNIQ: a variable that will have number+string of that   
    #line. This will be used in the ELSE-statement, IF there are no 
    #duplicates of the string, it will just be added to the 
    # output file without further processing 

    UNIQ="$(head -n $i $AASEQUENCE | tail -n 1)" 

    for DUPLICATE in $AASEQUENCE; 
    do 
     #create variable that will display the number of lines 
     #of duplicates. IF its 1 the IF-statement will jump to the ELSE 
     #part as there are no duplicates 

     VAR="$(grep -w "${STRING}" $DUPLICATE | wc -l)" 

     #Now add up all the numbers from column A that have $STRING in 
     #column B 

     TOTALCOUNT="$(grep -w "${STRING}" $DUPLICATE | cut -f1 | awk 
     '{SUM += $1} END {print SUM}')" 

     #Create a file that the single line can be put into it 

     touch MERGED_`basename $AASEQUENCE` 

     #The IF-statement checks if the AA occurs more than once 
     #If it does a second IF-statement checks if this AA-sequence has 
     #already been added. 
     #If it hasnt been added, it will be, if not nothing happens. 

     ALREADYMATCHED="$(grep -w "${STRING}" MERGED_`basename 
     $AASEQUENCE` | wc -l)" 

     if [[ "$VAR" > 1 ]]; 
     then if [[ "$ALREADYMATCHED" != 0 ]]; then paste <(echo 
     "$TOTALCOUNT") <(echo "$STRING") --delimiters ' '>> 
     MERGED_`basename $AASEQUENCE` ;fi; 
     else echo $UNIQ >> MERGED_`basename $AASEQUENCE` ;fi 
    done; 
    done; 
done; 

PS: Wenn ich DateiA.txt fileB.txt haben. .. und benutze Datei * Die Schleife bleibt immer nach der ersten Datei stehen. Irgendwelche Vorschläge warum?

Antwort

0

vielleicht pure awk lösung?

$ cat > in 
13 ABCD 
15 BGDA 
12 ABCD 
10 BGDA 
10 KLMN 
17 BGDA 

$ awk '{dc[$2] += $1} END{for (seq in dc) {print dc[seq], seq}}' in 
25 ABCD 
42 BGDA 
10 KLMN 

$ 
+0

Ich hätte hier erst nachfragen sollen, bevor ich dieses (für mich) extrem komplexe Skript schreibe. Vielen Dank! Ich muss den Befehl 'awk' mehr kennenlernen. – Vaxin

+0

lassen Sie mich wissen, wie schnell es für Ihre 500k Linien ist! – Jerzyk

+0

@ Vaxin auf einer Randnotiz - Python ist schön, mit DNA-Sequenzen zu spielen: http://pythonforbiologists.com/ – Jerzyk