Seite 1 von 1

Relative Zeit: konvertieren, berechnen und anzeigen

Verfasst: Dienstag 6. September 2022, 15:41
von Bussard
Hallo,

wie ist es möglich Daten in ein relatives Zeitformat zu konvertieren und die verstrichene Zeit (seit erstem Zeitpunkt) in dem Format [hh]:mm:ss zu plotten. Mit [hh] ist ein fortlaufendes Stundenformat gemeint, also auch grösser 24. Importiert wird aus einem xls file.
Der Variable Explorer zeigt x als Typ "Array of object" an. Der Inhalt sieht so aus:
2022-07-11 18:42:47
2022-07-11 18:42:53
2022-07-11 18:43:03
.
.
.

Code: Alles auswählen

import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
import os
import os.path

 
data_path   = "..."
export_path = "..."
data_file = "....xlsx"

mydata = pd.read_excel(data_path + data_file, skiprows=2)

x = mydata.iloc[17:30,0].values   # timestamp
y1 = mydata.iloc[17:30,1].values  # dataset 1
y3 = mydata.iloc[17:30,4].values  # dataset 2

# x = x - x[0] # calc ralative time

fig   = plt.figure(constrained_layout=True)
gs    = GridSpec(2, 2, figure=fig)
ax    = fig.add_subplot(gs[0, :])
twin1 = ax.twinx()

p1, = ax.plot(x, y1)
p2, = twin1.plot(x, y3)

plt.show()
Bei Verwendung von x = x - x[0] ergibt es einen Fehler "TypeError: float() argument must be a string or a number, not 'datetime.timedelta'.
Viele Versuche es zu konvertieren scheiterten. Wer weiss wie das funktioniert?
Danke

Re: Relative Zeit: konvertieren, berechnen und anzeigen

Verfasst: Dienstag 6. September 2022, 16:36
von __blackjack__
@Bussard: Da scheint doch schon was geklappt zu haben, denn Du hast da ja offenbar `timedelta`-Objekte. Die Frage ist wo die Ausnahme denn auftritt.

`os.path` muss man nicht importieren, das `os`-Modul importiert das für das System passende Modul schon selbst und bindet das an den Namen `path`. Und Du solltest das dann auch verwenden, statt Pfadteile per ``+`` zusammenzusetzen. Wobei man in neuem Code aber besser auf das `pathlib`-Modul setzen sollte.

Re: Relative Zeit: konvertieren, berechnen und anzeigen

Verfasst: Mittwoch 7. September 2022, 05:47
von Bussard
@__blackjack__
Die Ausnahme tritt beim plotten auf bei ax.plot(x, y1).

Code: Alles auswählen

runfile('yyy.py', wdir='C:/Users/xxx')
Traceback (most recent call last):

  File "C:\Users\xxx\yyy.py", line 27, in <module>
    p1, = ax.plot(x, y1)

  File "C:\Users\...\Anaconda3\lib\site-packages\matplotlib\axes\_axes.py", line 1607, in plot
    self.add_line(line)
  File "C:\Users\...\Anaconda3\lib\site-packages\matplotlib\axes\_base.py", line 2101, in add_line
    self._update_line_limits(line)
  File "C:\Users\...\Anaconda3\lib\site-packages\matplotlib\axes\_base.py", line 2123, in _update_line_limits
    path = line.get_path()
  File "C:\Users\...\Anaconda3\lib\site-packages\matplotlib\lines.py", line 1022, in get_path
    self.recache()
  File "C:\Users\...\Anaconda3\lib\site-packages\matplotlib\lines.py", line 663, in recache
    x = _to_unmasked_float_array(xconv).ravel()
  File "C:\Users\...\Anaconda3\lib\site-packages\matplotlib\cbook\__init__.py", line 1333, in _to_unmasked_float_array
    return np.asarray(x, float)
  File "C:\Users\...\Anaconda3\lib\site-packages\numpy\core\_asarray.py", line 102, in asarray
    return array(a, dtype, copy=False, order=order)

TypeError: float() argument must be a string or a number, not 'datetime.timedelta'

Warning
Figures now render in the Plots pane by default. To make them also appear inline in the Console, uncheck "Mute Inline Plotting" under the Plots pane options menu.
Vielen Dank auch noch für deine weiteren Ratschläge!
`os.path` muss man nicht importieren, das `os`-Modul importiert das für das System passende Modul schon selbst
Ja stimmt, das ist logisch ist mir gar nicht aufgefallen :-)
und bindet das an den Namen `path`. Und Du solltest das dann auch verwenden, statt Pfadteile per ``+`` zusammenzusetzen.
Ok, und wie würde man dann das nutzen im code?

Das mit pathlib kenne ich noch nicht. Werde ich mich mal ansehen.

Re: Relative Zeit: konvertieren, berechnen und anzeigen

Verfasst: Mittwoch 7. September 2022, 06:05
von Dennis89
Hallo,
Bussard hat geschrieben: Mittwoch 7. September 2022, 05:47 Ok, und wie würde man dann das nutzen im code?
Das mit pathlib kenne ich noch nicht. Werde ich mich mal ansehen.
Beides zusammengefasst:

Code: Alles auswählen

from pathlib import Path

DATA_PATH = Path('...')
DATA_FILE = '...'


def main():
    print(DATA_PATH / DATA_FILE)


if __name__ == '__main__':
    main()
Grüße
Dennis

Re: Relative Zeit: konvertieren, berechnen und anzeigen

Verfasst: Mittwoch 7. September 2022, 08:11
von __blackjack__
@Bussard: Da scheint es noch nichts fertiges zu geben, also müsstest Du die `timedelta`-Werte zum Beispiel in Sekunden umwandeln und dir einen Tickformatter schreiben. Also beispielsweise einen `FuncFormatter` verwenden. Also im einfachsten Fall einfach eine Funktion als „tick formatter“ übergeben, die Sekunden in das von Dir gewünschte Anzeigeformat umwandelt.

Re: Relative Zeit: konvertieren, berechnen und anzeigen

Verfasst: Mittwoch 7. September 2022, 10:13
von Bussard
Dennis89 hat geschrieben: Mittwoch 7. September 2022, 06:05 Hallo,
Bussard hat geschrieben: Mittwoch 7. September 2022, 05:47 Ok, und wie würde man dann das nutzen im code?
Das mit pathlib kenne ich noch nicht. Werde ich mich mal ansehen.
Beides zusammengefasst:

Code: Alles auswählen

from pathlib import Path

DATA_PATH = Path('...')
DATA_FILE = '...'


def main():
    print(DATA_PATH / DATA_FILE)


if __name__ == '__main__':
    main()
Grüße
Dennis
Besten Dank für dein Beispiel.

Re: Relative Zeit: konvertieren, berechnen und anzeigen

Verfasst: Mittwoch 7. September 2022, 10:21
von Bussard
__blackjack__ hat geschrieben: Mittwoch 7. September 2022, 08:11 @Bussard: Da scheint es noch nichts fertiges zu geben, also müsstest Du die `timedelta`-Werte zum Beispiel in Sekunden umwandeln und dir einen Tickformatter schreiben. Also beispielsweise einen `FuncFormatter` verwenden. Also im einfachsten Fall einfach eine Funktion als „tick formatter“ übergeben, die Sekunden in das von Dir gewünschte Anzeigeformat umwandelt.
Das wundert mich ein wenig. Aufgezeichnete Daten über der Zeit zu plotten ist eigentlich nicht ungewöhnlich. Ok, ich versuche jetzt das in Sekunden zu wandeln. nach der Zeile x = x - x[0] habe ich die Differenz. Eigentlich sollte ich es dann mit x = x.total_seconds() wandeln können. Jedoch sagt mir die Fehlermeldung (AttributeError: 'numpy.ndarray' object has no attribute 'total_seconds') das ich anscheinend doch kein timedelta vorliegen haben...?

Im Variable Explorer zeigt es mir für x an:
0:00:00
0:00:06
0:00:16
0:00:26
0:00:36
0:00:46
Dies ist eigentlich schon das was ich will, nur sollte es eben auch so auf der x-Achse im Plot sein.

Re: Relative Zeit: konvertieren, berechnen und anzeigen

Verfasst: Mittwoch 7. September 2022, 10:54
von __deets__
Das total_seconds ist verfuegbar auf time_delta. Also einer Zelle deines Arrays. Nicht dem ganzen Sack. Und was du willst, ist klar, aber augenscheinlich eben so nicht direkt verfuegbar, sondern muss duch einen eigenen Formatter zur Verfuegung gestellt werden.

Re: Relative Zeit: konvertieren, berechnen und anzeigen

Verfasst: Mittwoch 7. September 2022, 11:54
von Bussard
__deets__ hat geschrieben: Mittwoch 7. September 2022, 10:54 Das total_seconds ist verfuegbar auf time_delta. Also einer Zelle deines Arrays. Nicht dem ganzen Sack. Und was du willst, ist klar, aber augenscheinlich eben so nicht direkt verfuegbar, sondern muss duch einen eigenen Formatter zur Verfuegung gestellt werden.
Ach ja richtig. Ich denke damit komme ich nun weiter.
Super, vielen Dank!

Re: Relative Zeit: konvertieren, berechnen und anzeigen

Verfasst: Mittwoch 7. September 2022, 12:00
von __blackjack__
@Bussard: Ja das kommt häufiger vor, und dann ist das Problem wie genau die Zeit denn dargestellt werden soll. Da hat dann jeder wieder seine eigenen Vorstellungen und es wird kompliziert eine allgemeine, flexible Darstellung zu implementieren. Auf der anderen Seite ist es auch nicht so wirklich schwer sich das in ein paar Zeilen selbst zu schreiben.

Ein Numpy-Array hat diese Methode nicht, aber ein Pandas `Series`-Objekt hat ein `dt`-Attribut das eine `total_seconds()`-Methode hat. Du wirfst zu früh die Funktionalität von Pandas weg. Oder man könnte das Array auch einfach in `float` umwandeln (und die Werte durch den entsprechenden Faktor teilen, je nach `dtype` den das vorher hatte).

Randbemerkung: ich finde das ein bisschen ungünstig das hier zum Beispiel ``17:30`` so oft wiederholt wird:

Code: Alles auswählen

x = mydata.iloc[17:30,0].values   # timestamp
y1 = mydata.iloc[17:30,1].values  # dataset 1
y3 = mydata.iloc[17:30,4].values  # dataset 2
Ausserdem sollte man bessere Variablennamen verwenden. Wenn man einen Kommentar dran schreibt, der mit einem oder zwei Worten beschreibt was ein total kryptischer Name bedeuten soll, dann sollte der Kommentar der Name sein. Damit braucht man dann den Kommentar nicht mehr und das Programm ist gleich leichter verständlich.

Man könnte auch die Spalten schon beim einlesen selektieren, also nur einlesen was man auch braucht.

Re: Relative Zeit: konvertieren, berechnen und anzeigen

Verfasst: Mittwoch 7. September 2022, 18:21
von Bussard
Vieeelen Dank für deine weiteren Tipps!