pandas DataFrame jedes Mal aufteilen, wenn eine Series True ist

English Deutsch

In unserem vorherigen Beitrag haben wir untersucht, wie man einen pandas DataFrame jedes Mal aufteilt, wenn eine Spalte True ist.

Diese leicht modifizierte Funktion funktioniert auch, wenn die angegebene Series keine Spalte im DataFrame ist:

split_dataframe_by_series.py
def split_dataframe_by_series(df, series):
    """
    DataFrame aufteilen, wenn die angegebene Series True ist. Ergibt mehrere DataFrames
    """
    previous_index = df.index[0]

    for split_point in df[series].index:
        yield df[previous_index:split_point]
        previous_index = split_point
    # Rest des Datensatzes ausgeben
    try:
        yield df[split_point:]
    except UnboundLocalError:
        pass # Es gibt keinen Aufteilungspunkt => Ignorieren

Vollständiges Beispiel

Wir verwenden die ZeroCrossing-Spalte, die wir in unserem vorherigen Beitrag über Wertwechsel in pandas-String-Spalte/Serie erkennen erstellt haben und die auf unserem Beitrag über pandas-Zeitreihen-DataFrame-Beispieldatensatz erstellen aufbaut. Basierend auf diesem Beispiel fügen wir die modifizierte Hilfsfunktion von oben hinzu:

split_dataframe_full_example.py
import pandas as pd

# Vorgefertigten Zeitreihen-Beispieldatensatz laden
df = pd.read_csv("https://techoverflow.net/datasets/timeseries-example.csv", parse_dates=["Timestamp"])
df.set_index("Timestamp", inplace=True)

# Neue Spalte mit "Positive" oder "Negative" erstellen
df["SinePositive"] = (df["Sine"] >= 0).map({True: "Positive", False: "Negative"})
# "Wechsel"-Spalte (boolesch) erstellen
df["ZeroCrossing"] = df["SinePositive"].shift() != df["SinePositive"]
# Ersten Eintrag auf False setzen
df["ZeroCrossing"].iloc[0] = False

def split_dataframe_by_series(df, series):
    """
    DataFrame aufteilen, wenn die angegebene Series True ist. Ergibt mehrere DataFrames
    """
    previous_index = df.index[0]

    for split_point in df[series].index:
        yield df[previous_index:split_point]
        previous_index = split_point
    # Rest des Datensatzes ausgeben
    try:
        yield df[split_point:]
    except UnboundLocalError:
        pass # Es gibt keinen Aufteilungspunkt => Ignorieren

# Ergebnis ausgeben
split_frames = list(split_dataframe_by_series(df, df["ZeroCrossing"]))
print(f"Split DataFrame into {len(split_frames)} separate frames by zero-crossing")

Beachten Sie, dass die Umwandlung des Ergebnisses von split_dataframe_to_series() in eine list je nach Anwendung nicht erforderlich sein könnte. Wenn möglich, empfehle ich, die DataFrames direkt mit einer for-Schleife zu iterieren, z.B.:

iterate_split_frames.py
for df_section in split_dataframe_by_series(df, df["ZeroCrossing"]):
    pass # TODO: Ihr Code kommt hier rein!

Check out similar posts by category: Pandas, Python