Neue Spalte basierend auf den Daten einer anderen Spalte erstellen (Pandas, DataFrame, Datetime)

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
NinoBaumann
User
Beiträge: 72
Registriert: Samstag 25. April 2020, 19:03

Hallo,

ich habe ein DataFrame (dfData_NTMR018) mit Prozessdaten, welches ich gerne bearbeiten möchte. Eine Spalte enthält den Zeitstempel. Im ersten Schritt habe ich der Uhrzeit die passende Schicht zugewiesen. Frühschicht von 6 Uhr bis 14 Uhr, Spätschicht von 14 bis 22 Uhr und Nachtschicht von 22 Uhr bis 6 Uhr. Die Nachtschicht geht vom Datum her über zwei Tage. Als Beispiel:
Die Nachtschicht vom 28.02.2024 geht von 22 Uhr am 28.02.2024 bis 6 Uhr am 29.02.2024.
In einer neuen Spalte möchte ich jetzt das Schichtdatum haben. Das bedeutet, wenn in der Zeile beim Zeitstempel 2024-02-29 03:25:23 steht, soll beim Schichtdatum 2024-02-28 stehen, da es sich ja um die Nachtschicht vom 28.02.2024 handelt. Bisher habe ich das folgendermaßen gelöst:

Code: Alles auswählen

times = dfData_NTMR018['Frenco_Zeitstempel'].dt.time
dfData_NTMR018['Schicht'] = "" 
dfData_NTMR018['Schicht'][(times >= datetime.time(6, 0)) & (times < datetime.time(14, 0))] = 'FS'
dfData_NTMR018['Schicht'][(times >= datetime.time(14, 0)) & (times < datetime.time(22, 0))] = 'SS'
dfData_NTMR018['Schicht'][(times >= datetime.time(22, 0)) | (times < datetime.time(6, 0))] = 'NS'
dfData_NTMR018['Schicht_Datum'] = dfData_NTMR018['Frenco_Zeitstempel'].dt.date
dfData_NTMR018['Schicht_Datum'][times < datetime.time(6, 0)] -= datetime.timedelta(days=1)
Seit neustem kommt aber folgende Fehlermeldung/Hinweis:
You are setting values through chained assignment. Currently this works in certain cases, but when using Copy-on-Write (which will become the default behaviour in pandas 3.0) this will never work to update the original DataFrame or Series,
because the intermediate object on which we are setting values will behave as a copy.
A typical example is when you are setting values in a column of a DataFrame, like:
df["col"][row_indexer] = value
Use `df.loc[row_indexer, "col"] = values` instead, to perform the assignment in a single step and ensure this keeps updating the original `df`.
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/s ... sus-a-copy
dfData_NTMR018['Schicht_Datum'][times < datetime.time(6, 0)] -= datetime.timedelta(days=1)

Deswegen ermittle ich jetzt die Früh-, Spät und Nachtschicht mit einer Funktion und apply. Für das Schichtdatum wollte ich dasselbe machen mit der Funktion Nachtschicht_Zuweisung. Genau hier hänge ich jetzt auch. Ich weiß nicht genau, wie ich den Zeitstempel (Datum_Zeit) in Form '%d.%m.%Y %H:%M:%S' in der Funktion Nachtschicht_Zuweisung einmal als Uhrzeit und einmal in ein Datum konvertiere.
Kann mir hier jemand behilflich sein?

Code: Alles auswählen

import datetime
.
.
.
.
def Schichtzuweisung(Zeit):
    if Zeit >= datetime.time(6, 0) and  Zeit < datetime.time(14, 0):
        return 'FS'
    elif Zeit >= datetime.time(14, 0) and  Zeit < datetime.time(22, 0):
        return 'SS'
    else:
        return 'NS'

def Nachtschicht_Zuweisung(Datum_Zeit):
    if Datum_Zeit(als Uhrzeit) < datetime.time(6, 0):
    	return Datum_Zeit(als Datum) - datetime.timedelta(days=1)

times = dfData_NTMR018['Frenco_Zeitstempel'].dt.time

dfData_NTMR018['Schicht'] = times.apply(Schichtzuweisung)

dfData_NTMR018['Schicht_Datum'] = dfData_NTMR018['Frenco_Zeitstempel'].apply(Nachtschicht_Zuweisung)
Sirius3
User
Beiträge: 17754
Registriert: Sonntag 21. Oktober 2012, 17:20

Du hast die Zeitstempel nicht in einem Format als String, sondern als datetime-Objekte. Daher existiert Dein Problem doch gar nicht?

Das richtige Vorgehen wäre im Übrigen, die Werte in einem Schritt zu schreiben, und apply zu vermeiden:

Code: Alles auswählen

shifts = {
    **{h: 'FS' for h in [6,7,8,9,10,11,12,13]},
    **{h: 'SS' for h in [14,15,16,17,18,19,20,21]},
    **{h: 'NS' for h in [22,23,0,1,2,3,4,5]},
}
df['Schicht'] = df['Frenco_Zeitstempel'].dt.hour.map(shifts)
df['Schicht_Datum'] = (df['Frenco_Zeitstempel'] - datetime.timedelta(hours=6)).dt.date
NinoBaumann
User
Beiträge: 72
Registriert: Samstag 25. April 2020, 19:03

Sirius3 hat geschrieben: Donnerstag 29. Februar 2024, 15:47 Du hast die Zeitstempel nicht in einem Format als String, sondern als datetime-Objekte. Daher existiert Dein Problem doch gar nicht?

Das richtige Vorgehen wäre im Übrigen, die Werte in einem Schritt zu schreiben, und apply zu vermeiden:

Code: Alles auswählen

shifts = {
    **{h: 'FS' for h in [6,7,8,9,10,11,12,13]},
    **{h: 'SS' for h in [14,15,16,17,18,19,20,21]},
    **{h: 'NS' for h in [22,23,0,1,2,3,4,5]},
}
df['Schicht'] = df['Frenco_Zeitstempel'].dt.hour.map(shifts)
df['Schicht_Datum'] = (df['Frenco_Zeitstempel'] - datetime.timedelta(hours=6)).dt.date

Hallo Sirius,

danke für Deine Anmerkung und die Hilfe.

VG
Nino
Antworten