如何使用熊猫创建索引循环FIFO缓冲区

时间:2019-02-17 12:02:48

标签: python pandas

我正在尝试创建一个索引循环FIFO(先进先出)缓冲区,以保存烛台图的最后90分钟,以按分钟(即window_size = 150)聚合的熊猫数据框中显示一组15种资产在客户端应用程序上实时显示(蜡烛棒图)。每(1m)个时间步长,每个资产将分别保持关闭,打开,高,低和成交量特征。单个烛台将通过网络套接字进行更新,从而根据价格(烛台)的变化更新最新的时间间隔。用pandas表示这种数据结构的最有效机制是什么,客户端应用程序需要输出[5,15,90]形状,如代表[close,open,high,low,volume] 15个资产的as_frame所示。和90个间隔。

因此数据将这样表示:

assets  time   close    open    high    low    volume
asset1  time1  0.001    0.002   0.003   0.001  0.001
        time2  0.001    0.001   0.003   0.001  0.001
        ...
        time90 ...

...

asset15 time1  0.001    0.002   0.003   0.001  0.001
        time2  0.001    0.001   0.003   0.001  0.001
        ...
        time90 ...

我已经用python pandas实现了一个幼稚的解决方案:

class Buffer():
    def __init__(self):
        self.cols = [
                'asset',
                'timestamp',
                'close',
                'high',
                'low'
        ];

        self.lvls = [
            'asset',
            'timestamp'
        ]

        self.frame = pd.DataFrame(
            columns=self.cols
        );

        self.frame.set_index(self.lvls)

    def add(
        self,
        entry
    ):
        ... what would be the most effective
        mechanism to add to the multi indexed
        dataframe given the entry/record 
        {
           "asset":"ASSET",
           "timestamp": 158090000, 
           "close":1.3, 
           "high":1.4, 
           "low":1.2, 
           "open":1.3, 
           "volume":134.5 
        } 
        such that the dataframe timestamp 
        index does not exceed the given 
        window size?

    def as_frame(
        self,
        assets,
        features,
        window_size
    ):
        outframe = self.frame.set_index(self.lvls)
        outframe = outframe.groupby(self.lvls).last()
        outlist = outframe.to_xarray().to_array()
        return outlist

我如何最有效地在熊猫中解决上述问题?给定另一个数据结构,如果不存在更优化/性能更好的解决方案?

2 个答案:

答案 0 :(得分:2)

添加数据应与将appenddict一起使用,过滤目标DataFrame中的列一样简单。

self.frame.append({k:v for k, v in entry.items() if k in self.cols})

根据您的问题,我认为您想保留一个DataFrame,以在传入数据上保持连续的150秒窗口。

要过滤生成的帧,我将从最近添加的时间窗口中计算“开始”时间戳,并使用它来过滤行,如下所示:

start_ts = entry['timestamp'] - 150
self.frame = self.frame[ self.frame['ts'] >= start_ts ]

根据DataFrame的大小,您可能获得更好的性能:

self.frame.drop(self.frame[ self.frame['ts'] < start_ts ].index, inplace=True)

答案 1 :(得分:-1)

在检查时间索引的长度之后,您可能可以执行移位:

if len(self.frame.index.levels(1))>=150:
   self.frame = self.frame.shift(1)