web-dev-qa-db-de.com

Kann pandas automatisch Daten erkennen?

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?

114
Roman

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 strftimeauf dieser Seite .

253
Rutger Kassies

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)
15
Sean

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.
11
Joop

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)
8
IamTheWalrus

Ja - laut pandas.read_csvDokumentation :

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.

7
Gaurav

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 nach pd.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
7
Eugene Yarmash

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.

1
Mr_and_Mrs_D