String im Dataframe auslesen, ergänzen und zurückschreiben

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
krischanb
User
Beiträge: 12
Registriert: Samstag 9. Januar 2021, 18:38

Hallo,

ich habe in einem Pandas Dataframe einen String. In diesem String möchte ich ein Teil ergänzen. Der String sieht folgendermaßen aus:

ist: "ölkasdöjfasdkölnfaös 20.12 14:58 asdssa"

Soll: "ölkasdöjfasdkölnfaös 20.12.2019 14:58 asdssa"

Mein Ansatz war der folgende:

Code: Alles auswählen

%config Completer.use_jedi = False
import pandas as pd


df = pd.DataFrame([["asdfasdf 10.02 10:31 Meas", "10.02.2021"],
                  ["ölkasdöjfasdkölnfaös 20.12 14:58 asdssa", "20.12.2019"],
                  ["01234Abcde15.11 12:01 Uhr","08.09.2015"]],columns=["Text", "Fälligkeit"])
df["Fälligkeit"] = pd.to_datetime(df["Fälligkeit"])


pat = r"([0-9]{2}.[0-9]{2} [0-9]{2}:[0-9]{2})"
df["Text"] = df["Text"].replace(df["Text"].str.extract(pat), 
                               df["Text"].str.extract(pat)[0:5] +  str(df["Fälligkeit"].dt.year) + df["Text"].str.extract(pat)[-5:],
                               regex = True)

An dieser Stelle komme ich nicht weiter. Das Erkennen des Pattern funktioniert wie erwartet. Jedoch tue ich mich schwer damit den String entsprechend mit der Jahreszahl zu ergänzen. Hat jemand einen Tip für mich.


So stelle ich mir das Ergebnis vor (hier von mir manuell ergänzt):

Code: Alles auswählen

df = pd.DataFrame([["asdfasdf 10.02.2021 10:31 Meas", "10.02.2021"],
                  ["ölkasdöjfasdkölnfaös 20.12.2019 14:58 asdssa", "20.12.2019"],
                  ["01234Abcde15.11.2015 12:01 Uhr","08.09.2015"]],columns=["Text", "Fälligkeit"])
df["Fälligkeit"] = pd.to_datetime(df["Fälligkeit"])
krischanb
User
Beiträge: 12
Registriert: Samstag 9. Januar 2021, 18:38

Hallo,
Ich bin einen kleinen Schritt weiter gekommen. Jedoch habe ich wohl ein Problem mit Regular Expressions.

Code: Alles auswählen

df = pd.DataFrame([["asdfasdf1003 10.02 10.31 Meas", "10.02.2021"],
                  ["ölkasdöjfasdkölnfaös 20.12 14:58 asdssa", "20.12.2019"],
                  ["01234Abcde0256447 15.11 12.01 Uhr","08.09.2015"]],columns=["Text", "Fälligkeit"])
df["Fälligkeit"] = pd.to_datetime(df["Fälligkeit"])

pat = r"([0-9]{2}.[0-9]{2} [0-9]{2}.[0-9]{2})"
df["Text"] = (df["Text"].str.split(pat).str[0] + 
             (df["Text"].str.split(pat).str[1].str[:5] + "." + str(df["Fälligkeit"][1].year) + " " + 
              df["Text"].str.split(pat).str[1].str[-5:]) +
            df["Text"].str.split(pat).str[2])
liefert als Resultat:
Text Fälligkeit
0 asdfasdf1003 10.02.2019 10.31 Meas 2021-10-02
1 ölkasdöjfasdkölnfaös 20.12.2019 14:58 asdssa 2019-12-20
2 01234Abcde0256447.2019 15.11 12.01 Uhr 2015-08-09

erwartet habe ich:
Text Fälligkeit
0 asdfasdf1003 10.02.2021 10:31 Meas 2021-10-02
1 ölkasdöjfasdkölnfaös 20.12 14:58 asdssa 2019-12-20
2 01234Abcde0256447 15.11.2015 12:01 Uhr 2015-08-09

Die Jahreszahl 2019 entsteht durch

Code: Alles auswählen

str(df["Fälligkeit"][1].year)
Wie komme ich hier an die richtige Zeile. dt.year liefert alle Ergebnisse in einem String zurück.

Schwerwiegender als die Jahreszahlen ist für das Problem mit der Regular Expression. Für mich hat es den Anschein, als ob nicht nach der ganzen Regular Expression gesucht wird. Was mache ich hier falsch?

Gruß
Krischanb
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Wenn Du die Jahreszahl immer vom Eintrag mit dem Index 1 nimmst, was erwartest Du dann?
Dir ist bewußt, dass . in regulären Ausdrücken einem beliebigen Zeichen entspricht?

Bei pd.to_datetime fehlt dayfirst=True.

Warum überhaupt reguläre Ausdrücke?

Code: Alles auswählen

df = pd.DataFrame([
    ["asdfasdf1003 10.02 10.31 Meas", "10.02.2021"],
    ["ölkasdöjfasdkölnfaös 20.12 14:58 asdssa", "20.12.2019"],
    ["01234Abcde0256447 15.11 12.01 Uhr","08.09.2015"]
],columns=["Text", "Fälligkeit"])
df["Fälligkeit"] = pd.to_datetime(df["Fälligkeit"], dayfirst=True)
df.apply(lambda row: row['Text'].replace(row['Fälligkeit'].strftime('%d.%m'), row['Fälligkeit'].strftime('%d.%m.%Y')), axis=1)
Das kann natürlich immer noch bei so kaputten Formaten zu Problemen führen. Z.B. beim letzten Eintrag stimmt ja das Datum gar nicht, und woher kommt die Uhrzeit? Und warum wird Stunde und Minute mit . getrennt?
krischanb
User
Beiträge: 12
Registriert: Samstag 9. Januar 2021, 18:38

Hallo Sirius3,
Wenn Du die Jahreszahl immer vom Eintrag mit dem Index 1 nimmst, was erwartest Du dann?
Das genau die Jahreszahl aus der Zeile 1 (2019) genommen wird. Ist so vielleicht nicht klar rüber gekommen. Hier steckte ich an dem Punkt fest, dass ich das nicht Zeilenweise anwenden konnte, ohne eine Schleife zu bemühen.
Dir ist bewußt, dass . in regulären Ausdrücken einem beliebigen Zeichen entspricht?
Nein, das war mir nicht bewusst. Habe ich übersehen. Das erklärt mir jetzt aber das Verhalten meines Codes. Vielleicht kann ich an dieser Stelle mit Auslassungszeichen arbeiten.
Warum überhaupt reguläre Ausdrücke?
Weil ich damit auch die "kaputten" Uhrzeiten erfassen wollte.
Das kann natürlich immer noch bei so kaputten Formaten zu Problemen führen. Z.B. beim letzten Eintrag stimmt ja das Datum gar nicht, und woher kommt die Uhrzeit? Und warum wird Stunde und Minute mit . getrennt?

Das Datum war tatsächlich von mir falsch in dem Beispiel eingetragen.
Warum die Uhrzeit mit einem "." formatiert ist kann ich dir nicht beatworten und leider auch nicht beinflussen. Ich bekomme die Daten (Kontoauszug) so von einer Bank so zur Verfügung gestellt. Ich muss diesen Weg gehen, da das "Buchungsdatum" != "Tag des Ereignisses" ist und auch nur dort die Uhrzeit verzeichnet ist.
In einem weiteren Datensatz sind ist der "Tag des Ereignisses" und auch der Betrag zu finden. Dort möchte ich die Uhrzeit ergänzen, um die Daten auch tageszeitabhängig zu untersuchen.
Ja, mir ist bewusst, dass diese Vorgehensweise für den Fall, dass an einem Tag zwei identische Kontobewegungen existieren, ein falsches Ergebnis liefern kann.

Gruß
Krischanb
Antworten