如何使用python处理传入的实时数据

如何使用python处理传入的实时数据,python,pandas,Python,Pandas,哪一种是处理熊猫实时传入数据的最受推荐/最适合的方式 每隔几秒钟,我就会收到以下格式的数据点: {'time' :'2013-01-01 00:00:00', 'stock' : 'BLAH', 'high' : 4.0, 'low' : 3.0, 'open' : 2.0, 'close' : 1.0} 我想将其附加到现有的数据帧中,然后对其运行一些分析 问题是,仅使用DataFrame.append追加行可能会导致所有复制的性能问题 我尝试过的事情: 一些人建议预先分配一个大数据框,并在

哪一种是处理熊猫实时传入数据的最受推荐/最适合的方式

每隔几秒钟,我就会收到以下格式的数据点:

{'time' :'2013-01-01 00:00:00', 'stock' : 'BLAH',
 'high' : 4.0, 'low' : 3.0, 'open' : 2.0, 'close' : 1.0}
我想将其附加到现有的数据帧中,然后对其运行一些分析

问题是,仅使用DataFrame.append追加行可能会导致所有复制的性能问题

我尝试过的事情: 一些人建议预先分配一个大数据框,并在数据进来时更新它:

In [1]: index = pd.DatetimeIndex(start='2013-01-01 00:00:00', freq='S', periods=5)

In [2]: columns = ['high', 'low', 'open', 'close']

In [3]: df = pd.DataFrame(index=t, columns=columns)

In [4]: df
Out[4]: 
                    high  low open close
2013-01-01 00:00:00  NaN  NaN  NaN   NaN
2013-01-01 00:00:01  NaN  NaN  NaN   NaN
2013-01-01 00:00:02  NaN  NaN  NaN   NaN
2013-01-01 00:00:03  NaN  NaN  NaN   NaN
2013-01-01 00:00:04  NaN  NaN  NaN   NaN

In [5]: data = {'time' :'2013-01-01 00:00:02', 'stock' : 'BLAH', 'high' : 4.0, 'low' : 3.0, 'open' : 2.0, 'close' : 1.0}

In [6]: data_ = pd.Series(data)

In [7]: df.loc[data['time']] = data_

In [8]: df
Out[8]: 
                    high  low open close
2013-01-01 00:00:00  NaN  NaN  NaN   NaN
2013-01-01 00:00:01  NaN  NaN  NaN   NaN
2013-01-01 00:00:02    4    3    2     1
2013-01-01 00:00:03  NaN  NaN  NaN   NaN
2013-01-01 00:00:04  NaN  NaN  NaN   NaN
另一种选择是建立一个目录列表。只需将传入的数据附加到一个列表中,并将其分割成更小的数据帧即可完成这项工作

In [9]: ls = []

In [10]: for n in range(5):
   .....:     # Naive stuff ahead =)
   .....:     time = '2013-01-01 00:00:0' + str(n)
   .....:     d = {'time' : time, 'stock' : 'BLAH', 'high' : np.random.rand()*10, 'low' : np.random.rand()*10, 'open' : np.random.rand()*10, 'close' : np.random.rand()*10}
   .....:     ls.append(d)

In [11]: df = pd.DataFrame(ls[1:3]).set_index('time')

In [12]: df
Out[12]: 
                        close      high       low      open stock
time                                                             
2013-01-01 00:00:01  3.270078  1.008289  7.486118  2.180683  BLAH
2013-01-01 00:00:02  3.883586  2.215645  0.051799  2.310823  BLAH

或者诸如此类的事情,可能需要对输入进行多一点处理。

实际上,您正试图解决两个问题:捕获实时数据和分析数据。第一个问题可以用解决,它就是为此而设计的。然后,另一个问题可以通过读取相同的日志文件来解决。

我将使用HDF5/pytables,如下所示:

  • 将数据保持为python列表“尽可能长”
  • 将结果附加到该列表中
  • 当它变得“大”时:
    • 使用pandas io(和可追加的表)推送到HDF5存储区
    • 清除列表
  • 重复一遍
  • 事实上,我定义的函数为每个“键”使用一个列表,这样您就可以在同一个过程中将多个数据帧存储到HDF5存储中


    我们定义了一个函数,您可以在每行
    d
    中调用该函数:

    CACHE = {}
    STORE = 'store.h5'   # Note: another option is to keep the actual file open
    
    def process_row(d, key, max_len=5000, _cache=CACHE):
        """
        Append row d to the store 'key'.
    
        When the number of items in the key's cache reaches max_len,
        append the list of rows to the HDF5 store and clear the list.
    
        """
        # keep the rows for each key separate.
        lst = _cache.setdefault(key, [])
        if len(lst) >= max_len:
            store_and_clear(lst, key)
        lst.append(d)
    
    def store_and_clear(lst, key):
        """
        Convert key's cache list to a DataFrame and append that to HDF5.
        """
        df = pd.DataFrame(lst)
        with pd.HDFStore(STORE) as store:
            store.append(key, df)
        lst.clear()
    
    注意:我们使用with语句在每次写入后自动关闭存储。它保持开放的速度可能会更快,但如果是这样的话。还请注意,使用列表可能比使用列表更具可读性,但此处列表的性能会稍好一些

    要使用此选项,请将其称为:

    process_row({'time' :'2013-01-01 00:00:00', 'stock' : 'BLAH', 'high' : 4.0, 'low' : 3.0, 'open' : 2.0, 'close' : 1.0},
                key="df")
    
    注:“df”是pytables存储中使用的存储

    作业完成后,确保存储并清除剩余的缓存:

    for k, lst in CACHE.items():  # you can instead use .iteritems() in python 2
        store_and_clear(lst, k)
    
    现在,您可以通过以下方式获得完整的数据帧:

    with pd.HDFStore(STORE) as store:
        df = store["df"]                    # other keys will be store[key]
    
    一些评论:
    • 5000可以调整,尝试使用较小/较大的数字以满足您的需要
    • ,数据帧追加为O(
      len(df)
    • 在你进行统计或数据搜索之前,你不需要熊猫,使用最快的
    • 此代码适用于多个输入的键(数据点)
    • 这是非常少的代码,我们将停留在香草python列表中,然后是熊猫数据帧

    此外,要获取最新的读取,可以定义一个get方法,该方法在读取之前存储并清除。通过这种方式,您将获得最新的数据:

    def get_latest(key, _cache=CACHE):
        store_and_clear(_cache[key], key)
        with pd.HDFStore(STORE) as store:
            return store[key]
    
    现在,当您通过以下方式访问:

    df = get_latest("df")
    
    您将获得可用的最新“df”


    另一个选项稍微复杂一些:在表中定义自定义表,请参阅


    注意:您需要知道字段名才能创建数据。

    这在很大程度上取决于您将对数据执行的操作,例如,您是否需要整个系列的框架。另一个选项是附加到
    HDFStore
    ;然后选择您需要的(您已经同步了读/写操作),预分配的数据帧应该可以工作。快速检查df的内存使用情况。。。1000000个数据点=大约50年的第二次数据(假设工作日和10小时交易日)。因此,大约5年的时间和1000只股票将使用大约1G内存。这取决于是否可以接受的应用程序和资源限制。将对此发表评论“问题是,仅使用DataFrame.append附加行可能会导致所有复制操作的性能问题”。您是否尝试将所需字段转换为“元组”,然后将其附加到DataFrame。如果您在这方面需要帮助,请告诉我。正如其他人所提到的,除非您需要立即采取实时行动(如果您使用python并且仅接收OHLC数据,并且仅每隔几秒钟接收一次,则我怀疑情况是否如此),将过程分为两个阶段:1.数据检索/存储和2.数据处理将使生活变得更加轻松。我有一个脚本,每秒接收数百个OHLC条;首先将它们保存到DICT列表中,然后定期将其附加到HDFStore中,这对我来说很有效-我相信它可以进一步优化,但已经有所改进CPU使用率比将每行添加到df或存储中要高出许多倍。Matthew RocklinI刚刚启动了一个新项目。我真的不明白为什么日志记录可以帮助捕获时间序列数据?你的意思是将时间序列存储为字符串,然后解析字符串吗?那么我们为什么需要日志记录?我们不应该将它们转换为适当的d吗ata结构?日志记录专门设计用于帮助捕获时间序列数据。它将为您处理所有缓冲和文件管理。Pandas设计用于高效读取大型数据文件。同时,它们可以解决您的数据管理问题。此外,您有一份数据副本,因此可以仔细检查您的work稍后。这里有一篇相关帖子:如果你关心数据,那么是的,使用日志记录来构建一个非常健壮的系统,确保所有内容都被保存。然后单独使用一个分析应用程序,每隔一段时间读取一次分块日志,并将分块添加到数据框中。如果你不关心数据,并且总是可以启动ov呃,然后将传入的数据聚合成块,一次追加100或1000行。如果您确实需要尽快追加行,则至少追加1000个空行以分配内存,然后手动插入数据,就好像您只有numpy数组一样。有人能解释一下Python日志解决方案的相对优缺点吗关于另一个答案中给出的HDF5/PyTables解决方案,后者似乎更适用于在线分析,因为它具有奇特的索引功能。谢谢。由于实时数据通常很大,并且大小不断增加,因此,相同的