2013-01-21 38 views
7

Tôi có file khổng lồ trông như thế này:Tốc độ cải thiện về gấu trúc lớn read_csv với chỉ số datetime

05/31/2012,15: 30: 00.029,1306.25,1, E, 0,, ​​1306,25

05/31/2012,15: 30: 00.029,1306.25,8, E, 0,, ​​1306,25

tôi có thể dễ dàng đọc chúng bằng cách sử dụng sau đây:

pd.read_csv(gzip.open("myfile.gz"), header=None,names= 
    ["date","time","price","size","type","zero","empty","last"], parse_dates=[[0,1]]) 

có cách nào để có hiệu quả phân tích ngày như thế này vào gấu trúc timestamps? Nếu không, có bất kỳ hướng dẫn nào để viết một hàm cython có thể chuyển đến date_parser = không?

Tôi đã thử viết chức năng phân tích cú pháp của riêng mình và vẫn mất quá nhiều thời gian cho dự án tôi đang làm việc.

+0

Vì vậy, hàm read_csv đáp ứng nhu cầu phân tích cú pháp của bạn nhưng quá chậm? – BKay

+0

Vâng, về cơ bản. Nếu không có giải pháp dễ dàng, tôi muốn xem liệu ai đó có thể đưa ra hướng dẫn để xử lý điều này trong cython hay không. –

+0

Điều này làm tôi bối rối rằng 'pd.Timestamp' không hoạt động (ví dụ:' pd.Timestamp ('05 /31/2012,15:30:00.029 ') '). Thực tế nó không phải là rất có thể là một lỗi. –

Trả lời

6

Một cải tiến của trước solution of Michael WS:

  • chuyển đổi sang pandas.Timestamp là tốt hơn để thực hiện bên ngoài mã Cython
  • atoi và chế biến có nguồn gốc-c dây là một chút-bit nhanh hơn funcs python
  • số lượng datetime -lib gọi được giảm xuống một từ 2 (+1 thỉnh thoảng cho ngày)
  • micro cũng được chế biến

NB! Thứ tự ngày trong mã này là ngày/tháng/năm.

Tất cả trong tất cả các mã có vẻ nhanh hơn khoảng 10 lần so với ban đầu. Tuy nhiên nếu điều này được gọi sau khi read_csv thì trên ổ cứng SSD sự khác biệt là tổng thời gian chỉ là một vài phần trăm do chi phí đọc. Tôi đoán rằng trên ổ cứng thông thường, sự khác biệt sẽ nhỏ hơn.

cimport numpy as np 
import datetime 
import numpy as np 
import pandas as pd 
from libc.stdlib cimport atoi, malloc, free 
from libc.string cimport strcpy 

### Modified code from Michael WS: 
### https://stackoverflow.com/a/15812787/2447082 

def convert_date_fast(np.ndarray date_vec, np.ndarray time_vec): 
    cdef int i, d_year, d_month, d_day, t_hour, t_min, t_sec, t_ms 
    cdef int N = len(date_vec) 
    cdef np.ndarray out_ar = np.empty(N, dtype=np.object) 
    cdef bytes prev_date = <bytes> 'xx/xx/xxxx' 
    cdef char *date_str = <char *> malloc(20) 
    cdef char *time_str = <char *> malloc(20) 

    for i in range(N): 
     if date_vec[i] != prev_date: 
      prev_date = date_vec[i] 
      strcpy(date_str, prev_date) ### xx/xx/xxxx 
      date_str[2] = 0 
      date_str[5] = 0 
      d_year = atoi(date_str+6) 
      d_month = atoi(date_str+3) 
      d_day = atoi(date_str) 

     strcpy(time_str, time_vec[i]) ### xx:xx:xx:xxxxxx 
     time_str[2] = 0 
     time_str[5] = 0 
     time_str[8] = 0 
     t_hour = atoi(time_str) 
     t_min = atoi(time_str+3) 
     t_sec = atoi(time_str+6) 
     t_ms = atoi(time_str+9) 

     out_ar[i] = datetime.datetime(d_year, d_month, d_day, t_hour, t_min, t_sec, t_ms) 
    free(date_str) 
    free(time_str) 
    return pd.to_datetime(out_ar) 
6

tôi nhận được tăng tốc đáng kinh ngạc (50X) với mã cython sau:

cuộc gọi từ python: timestamps = convert_date_cython (df [ "ngày"] giá trị, df [ "time"] giá trị..)

cimport numpy as np 
import pandas as pd 
import datetime 
import numpy as np 
def convert_date_cython(np.ndarray date_vec, np.ndarray time_vec): 
    cdef int i 
    cdef int N = len(date_vec) 
    cdef out_ar = np.empty(N, dtype=np.object) 
    date = None 
    for i in range(N): 
     if date is None or date_vec[i] != date_vec[i - 1]: 
      dt_ar = map(int, date_vec[i].split("/")) 
      date = datetime.date(dt_ar[2], dt_ar[0], dt_ar[1]) 
     time_ar = map(int, time_vec[i].split(".")[0].split(":")) 
     time = datetime.time(time_ar[0], time_ar[1], time_ar[2]) 
     out_ar[i] = pd.Timestamp(datetime.datetime.combine(date, time)) 
    return out_ar 
2

Cardinality của chuỗi ngày giờ không lớn. Ví dụ: số chuỗi thời gian theo định dạng %H-%M-%S24 * 60 * 60 = 86400. Nếu số hàng của tập dữ liệu của bạn lớn hơn nhiều so với dữ liệu này hoặc dữ liệu của bạn chứa nhiều dấu thời gian trùng lặp, việc thêm bộ nhớ cache vào quá trình phân tích cú pháp có thể tăng tốc đáng kể.

Đối với những người không có Cython sẵn, đây là một giải pháp thay thế trong python tinh khiết:

import numpy as np 
import pandas as pd 
from datetime import datetime 


def parse_datetime(dt_array, cache=None): 
    if cache is None: 
     cache = {} 
    date_time = np.empty(dt_array.shape[0], dtype=object) 
    for i, (d_str, t_str) in enumerate(dt_array): 
     try: 
      year, month, day = cache[d_str] 
     except KeyError: 
      year, month, day = [int(item) for item in d_str[:10].split('-')] 
      cache[d_str] = year, month, day 
     try: 
      hour, minute, sec = cache[t_str] 
     except KeyError: 
      hour, minute, sec = [int(item) for item in t_str.split(':')] 
      cache[t_str] = hour, minute, sec 
     date_time[i] = datetime(year, month, day, hour, minute, sec) 
    return pd.to_datetime(date_time) 


def read_csv(filename, cache=None): 
    df = pd.read_csv(filename) 
    df['date_time'] = parse_datetime(df.loc[:, ['date', 'time']].values, cache=cache) 
    return df.set_index('date_time') 

Với bộ dữ liệu cụ thể sau, tăng tốc là 150x +:

$ ls -lh test.csv 
-rw-r--r-- 1 blurrcat blurrcat 1.2M Apr 8 12:06 test.csv 
$ head -n 4 data/test.csv 
user_id,provider,date,time,steps 
5480312b6684e015fc2b12bc,fitbit,2014-11-02 00:00:00,17:47:00,25 
5480312b6684e015fc2b12bc,fitbit,2014-11-02 00:00:00,17:09:00,4 
5480312b6684e015fc2b12bc,fitbit,2014-11-02 00:00:00,19:10:00,67 

Trong ipython:

In [1]: %timeit pd.read_csv('test.csv', parse_dates=[['date', 'time']]) 
1 loops, best of 3: 10.3 s per loop 
In [2]: %timeit read_csv('test.csv', cache={}) 
1 loops, best of 3: 62.6 ms per loop 

Để giới hạn mức sử dụng bộ nhớ, chỉ cần thay thế bộ nhớ cache dict bằng someth ing như một LRU.

+0

Trong ví dụ của tôi, dấu giây được đóng dấu. Nó rất lớn 15: 30: 00.029 –

+0

@MichaelWS để bạn có thể sử dụng thêm 1k mục trong bộ nhớ cache, bạn sẽ có được điểm – blurrcat

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