แพนด้าสามารถจดจำวันที่ได้โดยอัตโนมัติหรือไม่


151

วันนี้ฉันรู้สึกประหลาดใจในเชิงบวกจากความจริงที่ว่าในขณะที่การอ่านข้อมูลจากไฟล์ข้อมูล (ตัวอย่าง) หมีแพนด้าสามารถรับรู้ชนิดของค่า:

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แต่ผมมีคอลัมน์ที่มีวันที่ในรูปแบบต่อไปนี้: วันที่เหล่านี้ถูกจดจำเป็นสตริง (ไม่ใช่ python date-objects) มีวิธีที่จะ "เรียนรู้" หมีแพนด้าถึงวันที่ได้รับการยอมรับหรือไม่?


โปรดระบุเวอร์ชันของหมีแพนด้าเสมอสำหรับคำถามประเภทนี้ขึ้นอยู่กับรุ่น ในเดือนกรกฎาคม 2013 สิ่งนี้จะเป็น v0.11
smci

และ dtypes ที่มีการแก้ไขในแต่ละคอลัมน์คุณไม่จำเป็นต้องย้ำกว่าdf.iterrows()และดูพวกเขาสำหรับแถวเดียวทุกเพียงทำdf.info()ครั้งเดียว
smci

คำตอบ:


326

คุณควรเพิ่มparse_dates=Trueหรือparse_dates=['column name']เมื่ออ่านมักจะเพียงพอที่จะแยกวิเคราะห์ได้อย่างน่าอัศจรรย์ แต่มีรูปแบบแปลก ๆ อยู่เสมอซึ่งจำเป็นต้องกำหนดด้วยตนเอง ในกรณีเช่นนี้คุณสามารถเพิ่มฟังก์ชันตัวแยกวิเคราะห์วันที่ซึ่งเป็นวิธีที่ยืดหยุ่นที่สุด

สมมติว่าคุณมีคอลัมน์ 'datetime' กับสตริงของคุณแล้ว:

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 ในหน้านี้


8
ใช้งานไม่ได้สำหรับฉันฉันได้รับข้อผิดพลาดต่อไปนี้:TypeError: strptime() argument 1 must be str, not float
Jean Paul

6
ฉันได้รับข้อผิดพลาดนี้เนื่องจากมีน่านอยู่ในกรอบข้อมูลของฉัน
Jean Paul

คุณสามารถเพิ่มรายการที่มีเนื้อหาที่ไม่สามารถแยกวิเคราะห์หรือ NaN หรือ / Ns ได้เช่นกัน ทำให้ดูเหมือนว่าตัวแยกวิเคราะห์นี้ข้ามคอลัมน์ทั้งหมดหากมีสิ่งที่เป็นเช่นนี้อยู่
Amir

มีตัวเลือกinfer_datetime_format: "แพนด้าจะพยายามอนุมานรูปแบบของสตริงวันที่และเวลาในคอลัมน์" date_parserนี้สามารถนำมาใช้แทน
Winand

1
โปรดทราบว่าหากวันที่ของคุณอยู่ในISO 8601รูปแบบที่คุณไม่ควรผ่านinfer_datetime_formatหรือฟังก์ชั่นแยกวิเคราะห์ - มันช้ากว่าปล่อยให้แพนด้าจัดการมัน (โดยเฉพาะอย่างยิ่งหลัง) รูปแบบวันที่ในคำตอบนี้ตรงกับหมวดหมู่นี้เช่นกัน
Mr_and_Mrs_D

20

บางทีอินเทอร์เฟซแพนด้ามีการเปลี่ยนแปลงตั้งแต่ @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)

11

วิธี 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.

2
คุณสามารถระบุdayfirstเป็น True สำหรับวันที่ในยุโรป / ต่างประเทศ pandas.pydata.org/pandas-docs/stable/generated/…
Will Gordon

10

คุณสามารถใช้pandas.to_datetime()ตามที่แนะนำในเอกสารประกอบสำหรับpandas.read_csv():

หากคอลัมน์หรือดัชนีมีวันที่ไม่สามารถตรวจสอบได้คอลัมน์หรือดัชนีทั้งหมดจะถูกส่งคืนโดยไม่เปลี่ยนแปลงว่าเป็นชนิดข้อมูลวัตถุ สำหรับการแยก datetime ที่ไม่ได้มาตรฐานการใช้งานหลังจากที่pd.to_datetimepd.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

มันกำลังแปลงคอลัมน์อื่น ๆ ให้ทันสมัยด้วยซึ่งเป็นประเภทวัตถุ
ratnesh

10

เมื่อรวมสองคอลัมน์เข้าในคอลัมน์ datetime เดียวคำตอบที่ยอมรับจะสร้างข้อผิดพลาด (pandas เวอร์ชั่น 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)

1
ฉันใช้หมีแพนด้า 0.22 และยอมรับว่าคำตอบที่ยอมรับแล้วใช้ไม่ได้อีกต่อไป
Dai

สิ่งนี้จะสร้าง "TypeError: สามารถเชื่อม str เท่านั้น (ไม่ใช่" float ") กับ str" สำหรับฉัน คอลัมน์วันที่คือ d / m / y และคอลัมน์เวลาคือ H: M: 00
IceQueeny

8

ใช่ - ตามpandas.read_csv เอกสาร :

หมายเหตุ: มีพา ธด่วนสำหรับวันที่จัดรูปแบบ iso8601

ดังนั้นหาก csv ของคุณมีชื่อคอลัมน์datetimeและวันที่2013-01-01T01:01เป็นเช่นนี้การเรียกใช้งานจะทำให้นุ่น (ฉันใช้ v0.19.2) รับวันที่และเวลาโดยอัตโนมัติ:

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

โปรดทราบว่าคุณต้องผ่านอย่างชัดเจนparse_datesมันจะไม่ทำงานหากไม่มี

ยืนยันด้วย:

df.dtypes

คุณควรเห็นประเภทข้อมูลของคอลัมน์คือ datetime64[ns]


ฉันคิดว่าคุณเข้าใจผิดคำถาม ผู้ใช้อยากรู้ว่าตัวเลือกสามารถเปิดใช้งานสำหรับรูปแบบของสตริงได้หรือไม่
Arya McCarthy

@AryaMcCarthy อืมเขาต้องการให้วันที่ได้รับการยอมรับอย่างถูกต้องดังนั้นฉันจึงพูดถึงว่าเขาสามารถแปลงแหล่งข้อมูลเพื่อให้เป็นที่รู้จักโดยธรรมชาติของแพนด้า เขาไม่พูดถึงว่าเขาไม่สามารถเปลี่ยนรูปแบบของข้อมูลต้นฉบับได้
Gaurav

1

หากประสิทธิภาพของคุณสำคัญกับเวลา

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

ในขณะที่กำลังโหลดไฟล์ csv มีคอลัมน์วันที่เรามีสองวิธีที่จะทำให้แพนด้ารู้จักคอลัมน์วันที่เช่น

  1. นุ่นชัดเจนรับรู้รูปแบบโดยหาเรื่อง date_parser=mydateparser

  2. โดยนัย Pandas รู้จักรูปแบบโดย agr infer_datetime_format=True

ข้อมูลคอลัมน์วันที่บางส่วน

01/01/18

01/02/18

ที่นี่เราไม่รู้สองสิ่งแรกมันอาจเป็นเดือนหรือวัน ดังนั้นในกรณีนี้เราต้องใช้วิธีที่ 1: - ผ่านรูปแบบที่ชัดเจน

    mydateparser = lambda x: pd.datetime.strptime(x, "%m/%d/%y")
    df = pd.read_csv(file_name, parse_dates=['date_col_name'],
date_parser=mydateparser)

วิธีที่ 2: - นัยหรือจดจำรูปแบบโดยอัตโนมัติ

df = pd.read_csv(file_name, parse_dates=[date_col_name],infer_datetime_format=True)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.