pd Dataframe als Queue: Wie bekommt man das am effizientesten hin? Alternativen?
Verfasst: Mittwoch 2. Februar 2022, 18:56
Hallo, ich habe eine Klasse, die ein Pandas-Dataframe verwaltet. Index ist die Spalte 'time' vom Typ datetime. Das Dataframe hat eine maximale Größe, die über __init__ gesetzt wird.
In einer Methode "push" wird eine Zeile übergeben und vorne (also Index = 0) an das Dataframe angehängt, diese Methode folgt dabei diesem Schema:
- Ist die Zeit der neuen Zeile gleich der Zeit der aktuellen Zeile mit Index 0: entferne die Zeile mit Index 0 (diese wird durch die neue ersetzt)
- Entferne am Ende des Dataframes so viele Zeilen, dass nur noch max_size - 1 übrig sind
- füge die neue Zeile vorne an
Da meine Index-Spalte vom Typ datetime ist, ich aber mit den Indizes arbeiten will muss ich jedesmal erst reset_index aufrufen und nach der Bearbeitung set_index, da ich iloc/loc so nicht verwenden kann (korrekt?). Ich wäre allerdings auch nicht abgeneigt zu sagen, dass ich auf time als Index verzichte und index als int definiere. Allerdings bekomme ich das nicht hin, da durch das ständige Zeilen hinzufügen (diese neuen Zeilen haben jeweils einen int als Index und zwar immer 0) die Numerierung nicht richtig passt, bzw. immer irgendwelche Spalten "index" bzw. "level_0" eingefügt werden, bis das Programm mit einem Fehler abbricht. Insgesamt habe ich jedenfalls das Gefühl, dass meine jetzige Implementierung zwar tut was sie soll., dabei aber nicht sonderlich effizient ist. Gleiches gilt für folgende zwei Methoden:
Insgesamt würde das vermutlich alles durch einen int-index und die Möglichkeit Zeilen per iloc zu bekommen verbessert werden. Allerdings bekomme ich das - wie schon erwähnt - nicht hin.
Eine zweite Frage die sich mir stellt ist, ob der Ansatz mittels pd.DataFrame überhaupt der Richtige ist, oder ob ich das nicht lieber komplett anders umsetzten sollte.
Vielen Dank
Code: Alles auswählen
class TimeDataManager():
def __init__(self, max_size):
self.max_size = max_size
self.data = pd.DataFrame(columns=["time", "...", "...", "...",])
self.data.set_index("time", inplace=True)
- Ist die Zeit der neuen Zeile gleich der Zeit der aktuellen Zeile mit Index 0: entferne die Zeile mit Index 0 (diese wird durch die neue ersetzt)
- Entferne am Ende des Dataframes so viele Zeilen, dass nur noch max_size - 1 übrig sind
- füge die neue Zeile vorne an
Code: Alles auswählen
def push(self, row: pd.DataFrame):
assert len(row) == 1
self.data.reset_index(inplace=True)
if(len(self.data) > 0 and row.iloc[0]['time'] == self.data.at[0, 'time']):
self.data = self.data.tail(self.max_size - 1)
self.data = self.data.head(self.max_size - 1)
self.data = pd.concat([row, self.data], ignore_index=True)
self.data.set_index("time", inplace=True)
Code: Alles auswählen
def to_dict(self, index) -> dict:
"""Returns the values of the row with the specified index as dict. \n
Input:
index -- The row-index of data that will be returned. It must be >= 0 and < len(data)."""
assert index >= 0 and index < len(self.data)
res = self.data[index:index+1].reset_index()
return res.to_dict('records')[0]
def at(self, index, field):
"""Returns the value in column field of the row with the specified index. \n
Input:
index -- The row-index of data that will be returned. It must be >= 0 and < len(data).\n
field -- The column name from which the value should be returned. """
return self.to_dict(index)[field]
Eine zweite Frage die sich mir stellt ist, ob der Ansatz mittels pd.DataFrame überhaupt der Richtige ist, oder ob ich das nicht lieber komplett anders umsetzten sollte.
Vielen Dank