Strings aus Strings finde, zählen und Position speichern

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
marcel665
User
Beiträge: 2
Registriert: Freitag 22. November 2019, 21:34

Hallo zusammen,
ich würde gerne aus einer Datei lesen, Zeile für Zeile durchgehen und die gewisse Zeichen zählen. Soweit so gut. Jedoch muss ich auch Strings in einer Zeile finden (eine Zeile aus der Datei ist ein zusammenhängender String Länge 200 also z.B. ATGCTTACGATGC) und deren Position bestimmen, also sowas wie wo und wie oft kommt 'ATG' in diesem String vor, wobei das größere Problem das wo ist, da ich nicht nur das erste oder letzte finden muss, sondern mehrere. Am besten wäre, wenn ich ein Feld hätte mit den Anfangspositonen der Substings.
Mein Ansatz ist erstmal sehr naiv, würde aber reichen, jedoch spielt der Compiler nicht mit, da er denkt ich würde den String überschreiten.

Code: Alles auswählen

def open_file():
    base = [0,0,0,0]
    file = open("TIS-Ecoli.txt")
    possible_startCodons = []
    add_startCodon = []
    
    for i,row in enumerate(file):
        if i==400:
            break
        for j,char in enumerate(row):
            if char == 'A':
                base[0]+=1
                if j+2<201:
                    if char[j+1]=='T' and char[j+2]=='G':
                        add_startCodon = [j]
                        possible_startCodons[i] += add_startCodon 
            if char == 'G':
                base[1]+=1
            if char == 'C':
                base[2]+=1
            if char == 'T':
                base[3]+=1
    file.close()
    print(base)
Ich muss dazu sagen, ich probiere mich erst seit einer Woche mit Python und nehme gerne Verbesserungsvorschläge an. Vielleicht kann mir ja jemand helfen. Vielen Dank im Voraus.
Benutzeravatar
snafu
User
Beiträge: 6867
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Wenn du mehrere Vorkommen für eine Suche willst, dann kannst du find() oder index() in einer Schleife benutzen.

Hier eine Möglichkeit mit find():

Code: Alles auswählen

def find_indices(string, needle):
    indices = []
    i = string.find(needle)
    while i >= 0:
        indices.append(i)
        i = string.find(needle, i + 1)
    return indices
Alternativ könnte man auch die Regex-Engine bemühen:

Code: Alles auswählen

import re

[match.start() for match in re.finditer("X", string)]
Benutzeravatar
__blackjack__
User
Beiträge: 14050
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@marcel665: Ein paar mehr Leerzeichen täten der Lesbarkeit gut. Um Binäre Operatoren und nach Kommas beispielsweise.

Namen werden in Python per klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase).

Die Funktion `open_file()` macht deutlich mehr als nur eine Datei zu öffnen, der Name passt also nicht so ganz.

Wo möglich sollte man Dateien zusammen mit der ``with``-Anweisung verwenden und bei Textdatein immer eine explizite Kodierung angeben.

`base` ist ungewöhnlich weil man da ”magische” Indexwerte für die einzelnen Buchstaben hat. An der Stelle würde man eher ein Wörterbuch verwenden das die Buchstaben auf Anzahlen abbildet. Hier dann auch gleich eine spezialisiertere Ableitung: `collections.Counter()`.

Der Compiler hat kein Problem mit dem Quelltext, den kümmert das nicht ob zur Laufzeit vielleicht eine `IndexError` auftreten wird. Und wo ganz sicher ein Problem auftreten wird ist nicht eine Zeichenkette sondern beim Versuch mit dem Index `i` auf `possible_startCodons` zuzugreifen. Das ist eine leere Liste, es gibt keinen einzelnen Index bei dem *kein* `IndexError` ausgelöst werden würde. Elemente fangen das nicht einfach an zu existieren weil man an einem Index etwas zuweist. Da muss bereits etwas existieren was man neu zuweisen kann. Da würden sich sonst nämlich so fragen stellen was denn mit Indexpositionen passieren soll bei einer Zuweisung die vor dem Index liegen den man zuweist und an die vorher noch nichts zugewiesen wurde.

Dieser Fall kann in Deinem Code ja durchaus auftreten weil die Zuweisung durch ein ``if`` bedingt wird — wenn in einer Zeile gar kein "ATG" vorkommt, wird der Code dem Index auch nichts zuweisen. Wenn Du das am Ende wieder Zeilen zuordnen können möchtest, musst Du entweder auch für die Zeilen in denen "ATG" nicht vorkommt entsprechend eine leere Liste zuordnen/anhängen, oder Du musst statt einer Liste ein Wörterbuch nehmen das Zeilennummer auf "ATG"-Fundstellen abbildet. Was davon für Dich günstiger ist, dürfte von der erwarteten Häufigkeit von Zeilen ohne "ATG" und/oder davon abhängen wie die Daten weiterverarbeitet werden sollen.

``+=`` grundsätzlich mit einer Liste mit genau einem Element ist eine recht umständliche Art `append()` zu auszudrücken. Das ist die Methode um *ein* Element an eine Liste anzuhängen. Ohne das man zwischendurch noch eine temporäre Liste mit einem Element erzeugen müsste.

`add_startCodon` ist kein guter Name für etwas das keine Funktion oder Methode ist, denn es beschreibt eine Tätigkeit — wo der Leser dann eine Funktion oder Methode hinter erwartet. Die erste Zuweisung einer leeren Liste an den Namen ist überflüssig weil dieser Wert nie irgendwo verwendet wird.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
import re
from collections import Counter
from itertools import islice


def process_file():
    with open("TIS-Ecoli.txt", encoding="ascii") as file:
        base_to_count = Counter()
        possible_start_codons = []

        for row in islice(file, 400):
            row = row.strip()
            base_to_count.update(row)
            possible_start_codons.append(
                [match.start() for match in re.finditer("ATG", row)]
            )

    print(possible_start_codons)
    print(base_to_count)
Eventuell möchte man `base_to_count` hinterher noch bereinigen und/oder testen ob sich da etwas anderes als die vier Basen rein verirrt hat.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
marcel665
User
Beiträge: 2
Registriert: Freitag 22. November 2019, 21:34

Das sieht deutlich professioneller aus. Dankeschön, auch für die allgemeinen Vorgaben etc. Werde ich beim nächsten mal berücksichtigen. :) Hat übrigens super funktioniert!
Antworten