如何在Pandas中更好地管理我对内存的使用?

时间:2014-04-15 05:02:45

标签: python pandas hdf5

我正在使用Pandas来存储,加载和操纵财务数据。典型的数据文件是6000x4000 DataFrame(6000股x 4000交易日),如果说一半股票在给定日期具有价值N / A,则将以CSV格式大小为200MB。我一直在使用具有16GB内存的工作站,这足以将这个大小的整个CSV加载到内存中,执行各种计算,然后存储结果。在一般情况下,我在高峰使用期间最终使用大约10GB的RAM。我觉得我可以做得更有效率。我想将这个数字降到2GB左右,这样我就可以使用普通笔记本电脑和4GB内存来运行我的每日更新。这合理吗?无论我的硬件是什么,我都会使用太多内存吗?

我理解上面的答案取决于我正在做的事情的细节。以下是我可能运行的函数类型的示例:

def momentum_strategy():
    # prices.csv is a matrix containing stock prices for 6000 stocks
    # and 4000 trading dates
    prices = pd.read_csv("prices.csv")
    # Daily stock returns
    returns = prices/prices.shift(1) -1 
    # Annualized return volatility
    volatility = pd.rolling_std(returns, 21, 21) * 252**0.5
    # 6-month stock returns
    trail6monthreturns = prices/prices.shift(21*6) - 1
    # Rank of 6 month stock returns
    retrank = trail6monthreturns.rank(axis=1, ascending=False)
    # Portfolio of the top 100 stocks as measured by 6 month return
    positions = retrank.apply(lambda x: np.where(x<= 100, 1, np.nan))
    # Daily returns for top 100 stocks
    uptrendreturns = positions * returns
    # Daily return for 100 stock portfolio
    portfolioreturns = uptrendreturns.mean(1)
    return positions, portfolioreturns

我有一个想法是使用HDF5存储格式而不是CSV,因为通过最近的测试和仔细阅读pandas文档和stackoverfow我看到它在输入/输出方面要快得多,并且在这些操作期间内存密集程度更低。有什么想法吗?例如,我在每个单独的CSV中存储每日开盘价,最高价,最低价,收盘价,成交量,看跌期权,市盈率,收益增长率以及另外30种不同的指标(如上例所示,通常为6000只股票x每个交易日4000个)。如果推荐使用swtich到HDF5,我应该将这些相同的DataFrame存储在30多个单独的H5文件中吗?

在上面的函数中,如果我想在函数完成后访问某些中间结果,但没有用尽内存,那么将结果存储在包含HDF5的“temp”文件夹中是否有意义文件?例如:

def momentum_strategy_hdf5():
    # prices.csv is a matrix containing stock prices for 6000 stocks
    # and 4000 trading dates
    prices = pd.read_csv("prices.csv")
    s = pd.HDFStore("temp.h5")
    # Daily stock returns
    s['returns'] = prices/prices.shift(1) -1 
    # Annualized return volatility
    s['volatility'] = pd.rolling_std(s['returns'], 21, 21) * 252**0.5
    # 6-month stock returns
    s['trail6monthreturns'] = prices/prices.shift(21*6)
    # Rank of 6 month stock returns
    s['retrank'] = s['trail6monthreturns'].rank(axis=1, ascending=False)
    # Portfolio of the top 100 stocks as measured by 6 month return
    s['positions'] = s['retrank'].apply(lambda x: np.where(x<= 100, 1, np.nan))
    # Daily returns for top 100 stocks
    s['uptrendreturns'] = s['positions'] * s['returns']
    # Daily return for 100 stock portfolio
    s['portfolioreturns'] = s['uptrendreturns'].mean(1)
    return s['positions'], s['portfolioreturns']

编辑:我刚测试了上面两个功能,第一个用了15秒,而第二个用了42秒。所以写的第二个要慢得多,但希望有更好的方法吗?

2 个答案:

答案 0 :(得分:5)

以下是此类数据的典型工作流程:

  • 1)读取csv数据,转换为DataFrame,强制数据类型,使用HDFStore写出(根据您的需要可以是“固定”或“表格”格式)。这是一个单独的过程,然后退出该过程。当数据集很大时,我以逻辑格式(例如说日期范围)读取它,然后输出'table'格式的HDF5文件。然后可以附加到此。

  • 2)查询(也可以是日期或其他一些标准)。执行计算,然后写出 NEW HDF5文件。这可以并行完成(多个过程)。请确保您在每个过程中都要写单独的文件。

  • 3)将先前的数据文件合并为单个HDF5文件。这是一个单一的过程事件。

  • 4)重复2&amp; 3根据需要。

关键是要做不连续的步骤,在两者之间写出中间数据,然后退出中间的过程。这样可以保持可管理的内存中数据大小,并使内存中的计算速度更快。此外,这允许在只读HDF5文件上对cpu密集型操作进行多次处理。

在单独的系统进程中执行此操作以允许系统回收内存非常重要。

HTH

答案 1 :(得分:0)

虽然我没有多少使用HDF5文件的经验,但我建议使用三个可以让你朝着更好的方向前进的Python库

H5py是一个专门用于编码和解码二进制格式文件的Python库。我没有声称它比Pandas HDFstore更好(我发现Pandas在处理大量数据2.2M x 24时非常棒)但它可能会有所作为。

在内存管理对话中已经多次提到

PyTables。我没有这个图书馆的经验,但我在讨论memory/HDf5 problems时已经看过了。

mmap是一个用于内存映射的库(将数据从磁盘移入内存以便在不使用二进制格式的情况下进行操作的过程)。如果您猜测我没有使用此库的经验,那么您将成为赢家。

同样,我不能从这里的经验谈论太多,但我认为这三条路线可能会让你在处理大型数据集时更好地利用Python的内存。