【发布时间】:2014-05-29 07:03:30
【问题描述】:
我正在使用 Pandas 来存储、加载和操作财务数据。一个典型的数据文件是一个 6000x4000 的 DataFrame(6000 个股票 x 4000 个交易日期),如果说一半的股票在给定日期的价值为 N/A,则 CSV 格式的大小为 200MB。我一直在使用具有 16GB 内存的工作站,这足以将这种大小的整个 CSV 加载到内存中,执行各种计算,然后存储结果。在典型的一天中,我最终会在高峰使用期间使用大约 10GB 的 RAM。我觉得我可以更有效地做事。我想把这个数字降低到 2GB 左右,这样我就可以使用具有 4GB RAM 的普通笔记本电脑运行我的几个型号的每日更新。这合理吗?无论我的硬件如何,我是否都使用了太多内存?
我了解上述问题的答案取决于我正在做的事情的细节。这是我可能运行的函数类型的示例:
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 文档和 stackoverlfow 的阅读,我发现输入/输出速度更快,并且在此类操作期间占用的内存更少。对此有什么想法吗?例如,我将每日开盘价、最高价、最低价、收盘价、交易量、流通股数、市盈率、盈利增长和另外 30 种不同的指标存储在单独的 CSV 中(如上例中,通常为 6000 只股票 x每个 4000 个交易日期)。如果建议切换到 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秒。所以写的第二个要慢得多,但希望有更好的方法吗?
【问题讨论】:
-
如果你的数据框大部分是空的,你有没有看过使用sparse structures?
-
谢谢,我刚刚用它做了一些测试。您确定 to_sparse() 会对 DataFrame 产生内存影响吗?我刚刚尝试在 Series 和 DataFrames 上使用它。我能够在 Series 但不是 DataFrames 上使用 to_sparse() 来节省内存。虽然,当我为 DataFrame 以二进制形式写入磁盘时,我确实看到空间减少了。