2013-01-04 43 views
8

我有包含代表ISO格式日期的字符串列表的數據文件。目前,我讀他們使用:使用Python strptime將日期列表轉換爲datetime非常緩慢

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

這看起來很簡單,但在巨大的名單〜25000個日期操作時是可笑緩慢 - >約0.34轉換列表秒。 由於我有成千上萬的這樣的名單,我正在尋找更快的方式。但是,我還沒有找到。 dateutil語法分析器執行得更糟...

+3

你的意思是你認爲解析和轉換25.000日期,包括建立一個相同大小的新列表應該比解釋型語言中的三分之一秒更快?您可能想切換到編譯語言。 –

+1

@TimPietzcker您可以在numpy/pandas的不到三分之一秒內讀取和解析包含超過25000個日期和10個列的文件。 – bmu

+0

這就是我所經歷的...... – HyperCube

回答

8

索引/切片似乎比由@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 

我認爲如果你使用像numpy.genfromtxt這樣的文件解析器,converters參數和一個快速的字符串解析方法,你可以在不到半秒的時間內讀取和解析整個文件。

我用下面的函數來創建具有約25000行,ISO日期字符串作爲索引和10個的數據列的一例的文件:

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) 

比我用下面的代碼來解析文件:

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(基於numpy的)已基於C的文件解析器這甚至更快:

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

謝謝你詳細解答。這有助於很多! – HyperCube

15

這是一種快速執行約3倍的方法。

原始版本:

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 

更快的版本:

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 

這顯然遠不及靈活strptime()

編輯:使用單一的正則表達式提取的時間分量是稍快:

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

感謝您的快速響應!快3倍是一大進步! :) – HyperCube