Heute war ich positiv überrascht, dass beim Lesen von Daten aus einer Datendatei (zum Beispiel) pandas) Arten von Werten erkannt werden können:
df = pandas.read_csv('test.dat', delimiter=r"\s+", names=['col1','col2','col3'])
Zum Beispiel kann dies folgendermaßen überprüft werden:
for i, r in df.iterrows():
print type(r['col1']), type(r['col2']), type(r['col3'])
Insbesondere Integer, Floats und Strings wurden korrekt erkannt. Ich habe jedoch eine Spalte mit Datumsangaben im folgenden Format: 2013-6-4
. Diese Daten wurden als Zeichenfolgen erkannt (nicht als python date-objects). Gibt es eine Möglichkeit, zu "lernen" pandas zu erkannten Daten?
Sie sollten hinzufügen parse_dates=True
, oder parse_dates=['column name']
beim lesen reicht das normalerweise aus, um es magisch zu analysieren. Es gibt aber immer komische Formate, die manuell definiert werden müssen. In einem solchen Fall können Sie auch eine Datumsparser-Funktion hinzufügen, die die flexibelste Möglichkeit darstellt.
Angenommen, Sie haben eine Spalte 'datetime' mit Ihrer Zeichenfolge, dann:
dateparse = lambda x: pd.datetime.strptime(x, '%Y-%m-%d %H:%M:%S')
df = pd.read_csv(infile, parse_dates=['datetime'], date_parser=dateparse)
Auf diese Weise können Sie sogar mehrere Spalten zu einer einzigen Datums-/Uhrzeitspalte kombinieren. Dabei werden eine Datums- und eine Uhrzeitspalte zu einer einzigen Datums-/Uhrzeitspalte zusammengeführt:
dateparse = lambda x: pd.datetime.strptime(x, '%Y-%m-%d %H:%M:%S')
df = pd.read_csv(infile, parse_dates={'datetime': ['date', 'time']}, date_parser=dateparse)
Sie finden Anweisungen (d. H. Die Buchstaben, die für verschiedene Formate verwendet werden sollen) für strptime
und strftime
auf dieser Seite .
Vielleicht hat sich die pandas Schnittstelle geändert, seit @Rutger geantwortet hat, aber in der Version, die ich verwende (0.15.2), erhält die date_parser
- Funktion eine Liste von Daten anstelle von a In diesem Fall sollte sein Code folgendermaßen aktualisiert werden:
dateparse = lambda dates: [pd.datetime.strptime(d, '%Y-%m-%d %H:%M:%S') for d in dates]
df = pd.read_csv(infile, parse_dates=['datetime'], date_parser=dateparse)
die pandas read_csv-Methode eignet sich hervorragend zum Parsen von Daten. Vollständige Dokumentation unter http://pandas.pydata.org/pandas-docs/stable/generated/pandas.io.parsers.read_csv.html
sie können sogar die verschiedenen Datumsteile in verschiedenen Spalten haben und den Parameter übergeben:
parse_dates : boolean, list of ints or names, list of lists, or dict
If True -> try parsing the index. If [1, 2, 3] -> try parsing columns 1, 2, 3 each as a
separate date column. If [[1, 3]] -> combine columns 1 and 3 and parse as a single date
column. {‘foo’ : [1, 3]} -> parse columns 1, 3 as date and call result ‘foo’
Die Standarderkennung von Datumsangaben funktioniert einwandfrei, scheint jedoch auf nordamerikanische Datumsformate ausgerichtet zu sein. Wenn Sie anderswo wohnen, werden Sie gelegentlich von den Ergebnissen überrascht. Soweit ich mich erinnern kann, bedeutet der 6. Juni 2000 den 6. Januar in den USA im Gegensatz zum 1. Juni, an dem ich wohne. Es ist klug genug, sie herumzudrehen, wenn Daten wie 23/6/2000 verwendet werden. Wahrscheinlich sicherer bei JJJJMMTT Variationen des Datums zu bleiben. Entschuldigung an pandas Entwickler, hier, aber ich habe es nicht mit lokalen Daten in letzter Zeit getestet.
mit dem Parameter date_parser können Sie eine Funktion zum Konvertieren Ihres Formats übergeben.
date_parser : function
Function to use for converting a sequence of string columns to an array of datetime
instances. The default uses dateutil.parser.parser to do the conversion.
Beim Zusammenführen von zwei Spalten zu einer einzelnen datetime-Spalte generiert die akzeptierte Antwort einen Fehler (Pandas-Version 0.20.3), da die Spalten separat an die date_parser-Funktion gesendet werden.
Die folgenden Arbeiten:
def dateparse(d,t):
dt = d + " " + t
return pd.datetime.strptime(dt, '%d/%m/%Y %H:%M:%S')
df = pd.read_csv(infile, parse_dates={'datetime': ['date', 'time']}, date_parser=dateparse)
Ja - laut pandas.read_csv
Dokumentation :
Hinweis: Für iso8601-formatierte Daten existiert ein schneller Pfad.
Wenn Ihre CSV also eine Spalte mit dem Namen datetime
hat und das Datum beispielsweise wie 2013-01-01T01:01
Aussieht, führt dies zu pandas (I'm on v0.19.2 ) Datum und Uhrzeit automatisch abholen:
df = pd.read_csv('test.csv', parse_dates=['datetime'])
Beachten Sie, dass Sie explizit parse_dates
Übergeben müssen, ohne das es nicht funktioniert.
Überprüfen Sie mit:
df.dtypes
Sie sollten sehen, dass der Datentyp der Spalte datetime64[ns]
Ist.
Sie können pandas.to_datetime()
verwenden, wie in der Dokumentation für pandas.read_csv()
empfohlen:
Wenn eine Spalte oder ein Index ein nicht analysierbares Datum enthält, wird die gesamte Spalte oder der Index unverändert als Objektdatentyp zurückgegeben. Verwenden Sie für nicht standardmäßiges Datetime-Parsing
pd.to_datetime
nachpd.read_csv
.
Demo:
>>> D = {'date': '2013-6-4'}
>>> df = pd.DataFrame(D, index=[0])
>>> df
date
0 2013-6-4
>>> df.dtypes
date object
dtype: object
>>> df['date'] = pd.to_datetime(df.date, format='%Y-%m-%d')
>>> df
date
0 2013-06-04
>>> df.dtypes
date datetime64[ns]
dtype: object
Wenn Leistung für Sie wichtig ist, stellen Sie sicher, dass Sie Zeit haben:
import sys
import timeit
import pandas as pd
print('Python %s on %s' % (sys.version, sys.platform))
print('Pandas version %s' % pd.__version__)
repeat = 3
numbers = 100
def time(statement, _setup=None):
print (min(
timeit.Timer(statement, setup=_setup or setup).repeat(
repeat, numbers)))
print("Format %m/%d/%y")
setup = """import pandas as pd
import io
data = io.StringIO('''\
ProductCode,Date
''' + '''\
x1,07/29/15
x2,07/29/15
x3,07/29/15
x4,07/30/15
x5,07/29/15
x6,07/29/15
x7,07/29/15
y7,08/05/15
x8,08/05/15
z3,08/05/15
''' * 100)"""
time('pd.read_csv(data); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"]); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"],'
'infer_datetime_format=True); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"],'
'date_parser=lambda x: pd.datetime.strptime(x, "%m/%d/%y")); data.seek(0)')
print("Format %Y-%m-%d %H:%M:%S")
setup = """import pandas as pd
import io
data = io.StringIO('''\
ProductCode,Date
''' + '''\
x1,2016-10-15 00:00:43
x2,2016-10-15 00:00:56
x3,2016-10-15 00:00:56
x4,2016-10-15 00:00:12
x5,2016-10-15 00:00:34
x6,2016-10-15 00:00:55
x7,2016-10-15 00:00:06
y7,2016-10-15 00:00:01
x8,2016-10-15 00:00:00
z3,2016-10-15 00:00:02
''' * 1000)"""
time('pd.read_csv(data); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"]); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"],'
'infer_datetime_format=True); data.seek(0)')
time('pd.read_csv(data, parse_dates=["Date"],'
'date_parser=lambda x: pd.datetime.strptime(x, "%Y-%m-%d %H:%M:%S")); data.seek(0)')
druckt:
Python 3.7.1 (v3.7.1:260ec2c36a, Oct 20 2018, 03:13:28)
[Clang 6.0 (clang-600.0.57)] on darwin
Pandas version 0.23.4
Format %m/%d/%y
0.19123052499999993
8.20691274
8.143124389
1.2384357139999977
Format %Y-%m-%d %H:%M:%S
0.5238807110000039
0.9202787830000005
0.9832778819999959
12.002349824999996
Also mit iso8601-formatiertem Datum (%Y-%m-%d %H:%M:%S
Ist anscheinend ein iso8601-formatiertes Datum, ich denke das T kann fallengelassen werden und durch ein Leerzeichen ersetzt werden) sollten Sie Geben Sie nicht infer_datetime_format
an (was anscheinend auch keinen Unterschied zu häufigeren macht) und übergeben Sie Ihren eigenen Parser in der Leistung, die nur lähmt. Auf der anderen Seite macht date_parser
Einen Unterschied bei nicht so üblichen Tagesformaten. Nehmen Sie sich bitte die Zeit, bevor Sie wie gewohnt optimieren.