it-swarm.dev

يمكن الباندا التعرف على التواريخ تلقائيا؟

لقد فوجئت اليوم إيجابيا بحقيقة أنه أثناء قراءة البيانات من ملف البيانات (على سبيل المثال) ، تستطيع الباندا التعرف على أنواع القيم:

df = pandas.read_csv('test.dat', delimiter=r"\s+", names=['col1','col2','col3'])

على سبيل المثال ، يمكن التحقق من ذلك بهذه الطريقة:

for i, r in df.iterrows():
    print type(r['col1']), type(r['col2']), type(r['col3'])

في عدد صحيح معين ، تم التعرف على العوامات والسلاسل بشكل صحيح. ومع ذلك ، لدي عمود له تواريخ بالتنسيق التالي: 2013-6-4. تم التعرف على هذه التواريخ كسلسلة (وليس ككائنات تاريخ بيثون). هل هناك طريقة "لتعلم" الباندا إلى التواريخ المعترف بها؟

97
Roman

يجب عليك إضافة parse_dates=True أو parse_dates=['column name'] عند القراءة ، وهذا يكفي عادة لتحليله بطريقة سحرية. ولكن هناك دائمًا تنسيقات غريبة تحتاج إلى تعريف يدويًا. في مثل هذه الحالة ، يمكنك أيضًا إضافة وظيفة محلل تاريخ ، وهي الطريقة الأكثر مرونة ممكنة.

افترض أن لديك عمود "تاريخ" مع السلسلة الخاصة بك ، ثم:

dateparse = lambda x: pd.datetime.strptime(x, '%Y-%m-%d %H:%M:%S')

df = pd.read_csv(infile, parse_dates=['datetime'], date_parser=dateparse)

وبهذه الطريقة ، يمكنك حتى دمج عدة أعمدة في عمود وقت واحد ، وهذا يدمج "التاريخ" وعمود "الوقت" في عمود "وقت زمني" واحد:

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)

يمكنك العثور على توجيهات (مثل الحروف المراد استخدامها لتنسيقات مختلفة) لـ strptime و strftimeفي هذه الصفحة .

230
Rutger Kassies

ربما تغيرت واجهة الباندا منذ إجابةRutger ، لكن في الإصدار الذي أستخدمه (0.15.2) ، تتلقى الدالة date_parser قائمة بالتواريخ بدلاً من قيمة واحدة. في هذه الحالة ، يجب تحديث الكود الخاص به كما يلي:

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

طريقة pandas read_csv رائعة لتحليل التواريخ. وثائق كاملة في http://pandas.pydata.org/pandas-docs/stable/generated/pandas.io.parsers.read_csv.html

يمكنك حتى الحصول على أجزاء التاريخ المختلفة في أعمدة مختلفة وتمرير المعلمة:

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’

يعمل الاستشعار الافتراضي للتواريخ بشكل رائع ، ولكن يبدو أنه منحاز تجاه تنسيقات تاريخ أمريكا الشمالية. إذا كنت تعيش في مكان آخر ، فربما تكتشف النتائج أحيانًا. بقدر ما أستطيع أن أتذكر 1/6/2000 يعني 6 يناير في الولايات المتحدة الأمريكية بدلا من 1 يونيو حيث أعيش. إنه ذكي بما يكفي للتأرجح حولهم في حالة استخدام تواريخ مثل 23/6/2000. ربما أكثر أمانًا للبقاء مع أشكال YYYYMMDD من التاريخ رغم ذلك. أعتذر لمطوري الباندا ، لكنني لم أختبرها بالتواريخ المحلية مؤخرًا.

يمكنك استخدام المعلمة date_parser لتمرير دالة لتحويل التنسيق الخاص بك.

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

عند دمج عمودين في عمود تاريخ واحد ، تنشئ الإجابة المقبولة خطأ (إصدار الباندا 0.20.3) ، حيث يتم إرسال الأعمدة إلى دالة date_parser بشكل منفصل.

الأعمال التالية:

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

نعم - وفقًا لـ pandas.read_csvdocumentation :

ملاحظة: يوجد مسار سريع لـ تنسيق iso8601 التواريخ.

لذلك إذا كان ملف CSV الخاص بك يحتوي على عمود باسم datetime وكانت التواريخ تبدو مثل 2013-01-01T01:01 على سبيل المثال ، فإن تشغيل هذا سيجعل الباندا (أنا في الإصدار 19.19) تلتقط التاريخ والوقت تلقائيًا:

df = pd.read_csv('test.csv', parse_dates=['datetime'])

لاحظ أنك تحتاج إلى تمرير parse_dates صراحة ، لا يعمل بدونه.

تحقق مع:

df.dtypes

يجب أن تشاهد نوع بيانات العمود هو datetime64[ns]

7
Gaurav

يمكنك استخدام pandas.to_datetime() كما هو موصى به في وثائق pandas.read_csv() :

إذا كان عمود أو فهرس يحتوي على تاريخ غير قابل للتغيير ، فسيتم إرجاع العمود أو الفهرس بالكامل دون تغيير كنوع بيانات كائن. لتحليل وقت غير قياسي ، استخدم pd.to_datetime بعد pd.read_csv.

عرض:

>>> 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
6
Eugene Yarmash

إذا كان الأداء مهمًا لك ، فتأكد من وقتك:

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)')

مطبوعات:

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

لذلك مع التاريخ المنسق iso8601 (%Y-%m-%d %H:%M:%S هو على ما يبدو تاريخ منسق iso8601 ، أعتقد أن T يمكن إسقاطه واستبداله بمسافة) يجب عليك لا تحديد infer_datetime_format (الذي لا تحدث فرقًا مع الأنواع الأكثر شيوعًا سواء على ما يبدو) وتمرير المحلل اللغوي الخاص بك في أداء معطل فقط. من ناحية أخرى ، فإن date_parser تحدث فرقًا مع تنسيقات اليوم غير القياسية. تأكد من الوقت قبل التحسين ، كالمعتاد.

1
Mr_and_Mrs_D