Seite 1 von 1

pd.to_datetime Problem

Verfasst: Samstag 1. Dezember 2018, 21:18
von SautaRoc
Hallo,

Ich hole mir Daten aus der Zwischenablage in einen DataFrame:

Code: Alles auswählen

data = pd.read_clipboard(delimiter='\t')
data.columns = ['Datum', 'Zeit', 'B/S', 'Menge', 'Preis']

Ergebnis:

Code: Alles auswählen

      Datum           Zeit B/S  Menge    Preis
0   15Nov18  12:21:48:423    B      1  11414.0
1   15Nov18  12:21:28:278    B      1  11411.5
2   15Nov18  12:21:17:498    B      1  11410.5
3   15Nov18  12:21:17:495    B      1  11411.0

dann wandele ich in der Spalte 'Zeit' den String um, damit ich ihn in das Zeitformat umwandeln kann:

Code: Alles auswählen

data['Zeit'] = data['Zeit'].str.replace(':','.')
data['Zeit'] = data['Zeit'].str.replace('.',':',2)

Ergebnis:

Code: Alles auswählen

      Datum           Zeit B/S  Menge    Preis
0   15Nov18  12:21:48.423    B      1  11414.0
1   15Nov18  12:21:28.278    B      1  11411.5
2   15Nov18  12:21:17.498    B      1  11410.5
3   15Nov18  12:21:17.495    B      1  11411.0

(es wird also nur der letrzte Doppelpunkt duch einen Punkt ersetzt)


dann möchte ich die Spalte 'Zeit' in den Objekttyp 'datetime' umwandeln:

Code: Alles auswählen

data['Zeit'] = pd.to_datetime(data['Zeit']
Ergebnis:

Code: Alles auswählen

0   15Nov18 2018-12-01 12:21:48.423   B      1  11414.0
1   15Nov18 2018-12-01 12:21:28.278   B      1  11411.5
2   15Nov18 2018-12-01 12:21:17.498   B      1  11410.5
3   15Nov18 2018-12-01 12:21:17.495   B      1  11411.0

jetzt wurde das heutige Datum mit eingefügt, was leider falsch ist. Man könnte jetzt natürlich hingehen und vorher die Spalten Datum und Zeit kombinieren, damit das richtige Datum drinsteht, aber das ist auch nicht was ich wollte.

Ich habe zunächst probiert:

Code: Alles auswählen

data['Zeit'] = pd.to_datetime(data['Zeit'], format='%I:%M:%S')
Ergebnis:

Code: Alles auswählen

ValueError: unconverted data remains: .423 
Da dachte ich mir, ok du hast die Millisekunden nicht beachtet:

aber:

Code: Alles auswählen

data['Zeit'] = pd.to_datetime(data['Zeit'], format='%I:%M:%S.%f')
liefert: unconverted data remains:

dann dachte ich mir, ok der hat das Datum da reingepackt, nimms mal mit:

Code: Alles auswählen

data['Zeit'] = pd.to_datetime(data['Zeit'], format='%y-%m-%d %I:%M:%S.%f')
aber da kommt: ValueError: time data '12:21:48.423 ' does not match format '%y-%m-%d %I:%M:%S.%f' (match)


Jetzt gehen mir die Ideen aus. Kann mir bitte jemand weiterhelfen, danke?

Re: pd.to_datetime Problem

Verfasst: Samstag 1. Dezember 2018, 21:55
von __blackjack__
Also erst einmal `to_datetime()` sagt ja schon irgendwie das da Datum *und* Zeit als Ergebnis heraus kommen. Wenn das Datum in den Daten nicht enthalten ist, dann wird das aktuelle Datum angenommen. An der Stelle solltest Du noch mal genau überlegen warum Du die Datumsspalte da nicht für verwenden willst.

Bei ``format='%I:%M:%S.%f'`` hast Du auch vorher die Sache mit dem Punkt gemacht? Oder müsstest Du dann das %f nicht vielleicht durch einen : trennen statt eines Punktes?

Das ``format='%y-%m-%d %I:%M:%S.%f'`` nicht geht, sollte ja eigentlich klar sein: In den 'Zeit'-Daten ist kein Datum enthalten, also kann man da logischerweise auch keine Platzhalter für in das Format packen.

Ist %I überhaupt richtig? Ich würde da ja ein %p mit im Format erwarten. Sonst ist %H das richtige für Stunden.

Re: pd.to_datetime Problem

Verfasst: Samstag 1. Dezember 2018, 22:13
von Sirius3
Das ist das Problem, wenn man kaputte Datenformate hat, mit denen man arbeiten muß. Zum Glück bietet Pandas tausend Optionen, wie man Daten lesen kann.

Code: Alles auswählen

data = pandas.read_clipboard(delimiter='\t',
    header=None, index_col=['Datum', 'Zeit', 'B/S', 'Menge', 'Preis'],
    parse_dates=[['Datum', 'Zeit']], date_parser=lambda d:dateutil.parser.parse('.'.join(d.rsplit(':',1))))

Re: pd.to_datetime Problem

Verfasst: Samstag 1. Dezember 2018, 22:33
von SautaRoc
also,

die strftime Referenz sagt

Code: Alles auswählen

%I    Hour (12-hour clock) as a zero-padded decimal number.    07
(http://strftime.org/). Das sollte also passen


ursprünglich ist in der Zeitspalte natürlich kein Datum drin, aber

Code: Alles auswählen

pd.to_datetime
hat ja nun ein Datum angenommen, daher ist es doch nun da?

den '.' hatte ich ja schon vorher in dem ursprünglichen String geändert, damit

Code: Alles auswählen

pd.to_datetime
überhaupt geht, da die ursprüngliche Version mit dem ':' nicht erkannt wird.

Ich werde jetzt mal versuchen die Datum Spalte mit der Zeitspalte zu kombinieren.

Code: Alles auswählen

data['DatumZeit'] = data['Datum']+' '+data['Zeit']
data['DatumZeit'] = pd.to_datetime(data['DatumZeit'])
data.drop(['Datum', 'Zeit'], axis=1, inplace = True)
print(data)
print(data.dtypes)

das gibt nun:

Code: Alles auswählen

   Art  Menge    Preis               DatumZeit
0    B      1  11414.0 2018-11-15 12:21:48.423
1    B      1  11411.5 2018-11-15 12:21:28.278
2    B      1  11410.5 2018-11-15 12:21:17.498
3    B      1  11411.0 2018-11-15 12:21:17.495

Code: Alles auswählen

[72 rows x 4 columns]
Art                  object
Menge                 int64
Preis               float64
DatumZeit    datetime64[ns]
dtype: object
Ich habe nun also tatsächlich eine Spalte 'DatumZeit', welche die String- Spalten 'Datum' und 'Zeit' ersetzt mit einer datetime Spalte, mit der man jetzt auch rechen kann.

Re: pd.to_datetime Problem

Verfasst: Samstag 1. Dezember 2018, 23:04
von Sirius3
Warum ignorierst Du die Antworten von ThomasL und mir, die Dir zeigen, dass alles, was Du hier so kompliziert in vielen Zeilen erledigst auch im Aufruf von read_clipboard gemacht werden kann?

Re: pd.to_datetime Problem

Verfasst: Samstag 1. Dezember 2018, 23:22
von ThomasL
Sirius3 hat geschrieben: Samstag 1. Dezember 2018, 22:13 Das ist das Problem, wenn man kaputte Datenformate hat, mit denen man arbeiten muß. Zum Glück bietet Pandas tausend Optionen, wie man Daten lesen kann.

Code: Alles auswählen

data = pandas.read_clipboard(delimiter='\t',
    header=None, index_col=['Datum', 'Zeit', 'B/S', 'Menge', 'Preis'],
    parse_dates=[['Datum', 'Zeit']], date_parser=lambda d:dateutil.parser.parse('.'.join(d.rsplit(':',1))))
Hallo Sirius,
fand deine Lösung sehr elegant und wollte sie als Snippet ablegen, aber dein date_parser funzt so bei mir nicht.
Habe einiges ausprobiert und bin jetzt bei diesem Code gelandet, kann man das noch optimieren?

Code: Alles auswählen

dateparse = lambda d: dateutil.parser.parse(d.replace(':','.').replace('.',':',2))
df = pd.read_clipboard(delimiter='\t', header=None, names=['Datum', 'Zeit', 'B/S', 'Menge', 'Preis'],
                      parse_dates=[['Datum', 'Zeit']], date_parser=dateparse)

Re: pd.to_datetime Problem

Verfasst: Sonntag 2. Dezember 2018, 00:53
von SautaRoc
@Sirius und ThomasL, ich ignoriere eure Antworten keineswegs. Sie sind wohl nur eingetroffen während ich an meinem letzten Post sass. Dadurch hat sich das überschnitten. Vielen Dank für die Hinweise. Das Problem für einen Anfänger wie mich ist halt, dass man den Wald vor lauter Bäumen nicht sieht. Ich versuche immer erst alles alleine, nur wenn es stundenlang nicht weitergeht frage ich nach. Daher sind meine Erstlösungen sicher nicht elegant, aber oft sind es Lösungen. Trotzdem bin ich sehr dankbar, wenn mir dann jemand zeigt wie man es mit zwei Zeilen elegant lösen kann - Dann verstehe ich es wenigstens....

Re: pd.to_datetime Problem

Verfasst: Sonntag 2. Dezember 2018, 01:29
von SautaRoc
Noch eine kleine Ergänzug, die mir gerade aufgefallen ist:

beim einlesen der Daten aus dem Clipboard muss noch header = None ergänzt werden, sonst wird beim setzen der Spaltenüberschriften die erste Datenzeile überschrieben.

Code: Alles auswählen

data = pd.read_clipboard(delimiter='\t', header = None)

Re: pd.to_datetime Problem

Verfasst: Sonntag 2. Dezember 2018, 15:40
von __blackjack__
SautaRoc hat geschrieben: Samstag 1. Dezember 2018, 22:33 also,

die strftime Referenz sagt

Code: Alles auswählen

%I    Hour (12-hour clock) as a zero-padded decimal number.    07
(http://strftime.org/). Das sollte also passen
Nein das sollte nicht passen, jedenfalls nicht wenn Du jede beliebige Zeit am Tag in den Daten haben kannst. Denn ein Tag hat nicht 12 sondern 24 Stunden. Wenn man also das 12 Stunden-Format nimmt, muss man ja noch irgendwo die Information her bekommen ob die Zeitangabe vor oder nach Mittags ist. Und da die Information nirgends in Deinen Daten zu stehen scheint, hast Du entweder dort schon ein Problem, oder Du hast grundsätzlich nur Zeiten von Mitternacht bis Mittags, oder das funktioniert so nicht.

Falls die Information vor oder nach Mittags doch in den Daten steht, dann müsstest Du die noch zusätzlich verarbeiten. Davon ist aber weder in Deiner Zeichenkette für das Zeitformat noch im Code etwas zu sehen.