2013-01-04 39 views
8

Tôi có các tệp dữ liệu chứa danh sách các chuỗi đại diện cho ngày được định dạng ISO. Hiện nay, tôi đang đọc chúng trong việc sử dụng:Chuyển đổi danh sách các chuỗi dữ liệu thành datetime rất chậm với Python strptime

mydates = [ datetime.datetime.strptime(timdata[x], "%Y-%m-%dT%H:%M:%S") for x in range(len(timedata)) ] 

này trông khá đơn giản, nhưng là ridiculously chậm khi hoạt động trên danh sách khổng lồ ~ 25000 ngày -> khoảng 0,34 giây cho mỗi danh sách chuyển đổi. Vì tôi có hàng ngàn danh sách như vậy, tôi đang tìm kiếm một cách nhanh hơn. Tuy nhiên, tôi vẫn chưa tìm được. Trình phân tích cú pháp dateutil hoạt động thậm chí còn tồi tệ hơn ...

+3

Bạn có nghĩa là bạn nghĩ rằng phân tích cú pháp và chuyển đổi 25.000 ngày, bao gồm cả việc xây dựng một danh sách mới có cùng kích thước sẽ nhanh hơn một phần ba giây trong một ngôn ngữ thông dịch? Bạn có thể muốn chuyển sang ngôn ngữ được biên dịch. –

+1

@TimPietzcker Bạn có thể đọc và phân tích cú pháp tệp có chứa hơn 25000 ngày và 10 cột khác trong vòng chưa đầy một phần ba giây với các chú gấu trúc/gấu trúc. – bmu

+0

Đó là những gì tôi đã trải nghiệm, quá .... – HyperCube

Trả lời

8

Indexing/cắt có vẻ là nhanh hơn so với regex được sử dụng bởi @NPE:

In [47]: def with_indexing(dstr):        
    ....:  return datetime.datetime(*map(int, [dstr[:4], dstr[5:7], dstr[8:10], 
    ....:        dstr[11:13], dstr[14:16], dstr[17:]])) 

In [48]: p = re.compile('[-T:]') 

In [49]: def with_regex(dt_str): 
    ....:  return datetime.datetime(*map(int, p.split(dt_str))) 

In [50]: %timeit with_regex(dstr) 
100000 loops, best of 3: 3.84 us per loop 

In [51]: %timeit with_indexing(dstr) 
100000 loops, best of 3: 2.98 us per loop 

Tôi nghĩ nếu bạn sử dụng một trình phân tích cú pháp tệp như numpy.genfromtxt, đối số converters và phương pháp phân tích cú pháp chuỗi nhanh, bạn có thể đọc và phân tích toàn bộ tệp trong chưa đầy một nửa giây.

tôi đã sử dụng các chức năng sau đây để tạo ra một tập tin ví dụ với khoảng 25000 hàng, chuỗi ngày ISO như chỉ mục và 10 cột dữ liệu:

import numpy as np 
import pandas as pd 

def create_data(): 
    # create dates 
    dates = pd.date_range('2010-01-01T00:30', '2013-01-04T23:30', freq='H') 
    # convert to iso 
    iso_dates = dates.map(lambda x: x.strftime('%Y-%m-%dT%H:%M:%S')) 
    # create data 
    data = pd.DataFrame(np.random.random((iso_dates.size, 10)) * 100, 
         index=iso_dates) 
    # write to file 
    data.to_csv('dates.csv', header=False) 

Thần I sử dụng đoạn mã sau để phân tích các tập tin:

In [54]: %timeit a = np.genfromtxt('dates.csv', delimiter=',', 
            converters={0:with_regex}) 
1 loops, best of 3: 430 ms per loop 

In [55]: %timeit a = np.genfromtxt('dates.csv', delimiter=',', 
            converters={0:with_indexing}) 
1 loops, best of 3: 391 ms per loop 

pandas (dựa trên numPy) có một phân tích cú pháp tập tin C-based mà thậm chí còn nhanh hơn:

In [56]: %timeit df = pd.read_csv('dates.csv', header=None, index_col=0, 
            parse_dates=True, date_parser=with_indexing) 
10 loops, best of 3: 167 ms per loop 
+0

Cảm ơn bạn đã trả lời chi tiết. Điều đó giúp ích rất nhiều! – HyperCube

15

Đây là cách để làm điều đó nhanh hơn gấp 3 lần.

Phiên bản gốc:

In [23]: %timeit datetime.datetime.strptime("2013-01-01T01:23:45", "%Y-%m-%dT%H:%M:%S") 
10000 loops, best of 3: 21.8 us per loop 

Các phiên bản nhanh hơn:

In [24]: p = re.compile('[-T:]') 

In [26]: %timeit datetime.datetime(*map(int, p.split("2013-01-01T01:23:45"))) 
100000 loops, best of 3: 7.28 us per loop 

này rõ ràng là hư không gần như linh hoạt như strptime().

chỉnh sửa: Sử dụng một regex duy nhất để trích xuất các thành phần ngày là nhẹ nhanh hơn:

In [48]: pp = re.compile(r'(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})') 

In [49]: %timeit datetime.datetime(*map(int, pp.match("2013-01-01T01:23:45").groups())) 
100000 loops, best of 3: 6.92 us per loop 
+0

Cảm ơn bạn đã phản hồi nhanh! 3 lần nhanh hơn là một cải tiến lớn !! :) – HyperCube

Các vấn đề liên quan