2013-11-20 4 views
7

Я использую Питон deque() реализовать простой циклический буфер:Deque в питоне панд

from collections import deque 
import numpy as np 

test_sequence = np.array(range(100)*2).reshape(100,2) 
mybuffer = deque(np.zeros(20).reshape((10, 2))) 

for i in test_sequence: 
    mybuffer.popleft() 
    mybuffer.append(i) 

    do_something_on(mybuffer) 

мне было интересно, если есть простой способ получить то же самое в панде с помощью Series (или DataFrame). Другими словами, как я могу эффективно добавить одну строку в конец и удалить одну строку в начале Series или DataFrame?

Edit: Я попытался это:

myPandasBuffer = pd.DataFrame(columns=('A','B'), data=np.zeros(20).reshape((10, 2))) 
newpoint = pd.DataFrame(columns=('A','B'), data=np.array([[1,1]])) 

for i in test_sequence: 
    newpoint[['A','B']] = i 
    myPandasBuffer = pd.concat([myPandasBuffer.ix[1:],newpoint], ignore_index = True) 

    do_something_on(myPandasBuffer) 

Но это болезненно медленнее, чем метод deque().

+1

Я сомневаюсь, что это более эффективно для этого в пандах. По моему мнению, нет встроенного поведения в очереди (но вы можете написать свою собственную оболочку вокруг кадрового фрейма pandas, используя метод concat и/или используя индексные срезы) – dorvak

+0

Неудовлетворительный ответ: используйте HDF5Store. –

+0

Эй, Энди, спасибо тебе за ответ. Что ты конкретно имеешь ввиду? Не могли бы вы привести пример? благодаря – Fra

ответ

0

Как отмечено dorvak, панды не предназначены для поведения в очереди.

Ниже я воспроизвел простую функцию вставки из deque в dataframes pandas, массивы numpy, а также в hdf5, используя модуль h5py.

Функция timeit показывает (неудивительно), что модуль коллекций намного быстрее, за ним следует numpy, а затем pandas.

from collections import deque 
import pandas as pd 
import numpy as np 
import h5py 

def insert_deque(test_sequence, buffer_deque): 
    for item in test_sequence: 
     buffer_deque.popleft() 
     buffer_deque.append(item) 
    return buffer_deque 
def insert_df(test_sequence, buffer_df): 
    for item in test_sequence: 
     buffer_df.iloc[0:-1,:] = buffer_df.iloc[1:,:].values 
     buffer_df.iloc[-1] = item 
    return buffer_df 
def insert_arraylike(test_sequence, buffer_arr): 
    for item in test_sequence: 
     buffer_arr[:-1] = buffer_arr[1:] 
     buffer_arr[-1] = item 
    return buffer_arr 

test_sequence = np.array(list(range(100))*2).reshape(100,2) 

# create buffer arrays 
nested_list = [[0]*2]*5 
buffer_deque = deque(nested_list) 
buffer_df = pd.DataFrame(nested_list, columns=('A','B')) 
buffer_arr = np.array(nested_list) 

# calculate speed of each process in ipython 
print("deque : ") 
%timeit insert_deque(test_sequence, buffer_deque) 
print("pandas : ") 
%timeit insert_df(test_sequence, buffer_df) 
print("numpy array : ") 
%timeit insert_arraylike(test_sequence, buffer_arr) 
print("hdf5 with h5py : ") 
with h5py.File("h5py_test.h5", "w") as f: 
    f["buffer_hdf5"] = np.array(nested_list) 
    %timeit insert_arraylike(test_sequence, f["buffer_hdf5"]) 

Результаты% timeit:

Deque: 34.1 мкс на петле

панды: 48 мс на петле

NumPy массив: 187 мкс на петле

hdf5 с h5py : 31,7 мс на петлю

Примечания:

Мой метод разрезания pandas был только немного быстрее, чем метод concat, указанный в вопросе.

Формат hdf5 (через h5py) не показал никаких преимуществ. Я также не вижу никаких преимуществ HDFStore, как предположил Энди.

Смежные вопросы