2014-04-15 31 views
2

我正在使用熊貓來存儲,加載和操作財務數據。一個典型的數據文件是一個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的通過最近的測試中與大熊貓文件的審閱和stackoverlfow我看到在這種操作過程中,輸入/輸出速度更快,內存消耗更少。對此有何想法?例如,我將每日開盤價,最高價,最低價,收盤價,成交量,未平倉量,市盈率,盈利增長以及另外30種不同的度量值存儲在每個單獨的CSV中(如上例所示,通常6000個股票x 4000個交易日期)。如果推薦使用HDF5,應該將這些相同的DataFrame存儲在30個以上的獨立H5文件中?

在上面的函數中,如果我想要在函數完成後訪問一些中間結果,但不使用內存,那麼將結果存儲在包含HDF5文件?例如:

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秒。所以第二個寫得比較慢,但希望有更好的方法?

+0

如果你的數據幀大多是空的,你看着使用[稀疏的結構(http://pandas.pydata.org/pandas-docs/stable/sparse.html)? – BrenBarn

+0

謝謝,我只是做了一些測試。你確定to_sparse()對DataFrames產生內存差異嗎?我只是嘗試在Series和DataFrame上使用它。我可以在Series上使用to_sparse()而不是DataFrames來節省內存。雖然,當我用DataFrames的二進制文件寫入磁盤時,我確實看到了空間減少。 – bobo5645

回答

4

下面是一個典型的工作流程爲這種類型的數據:

  • 1)CSV數據讀取,轉換成數據幀,脅迫的數據類型,寫出使用HDFStore(根據您的需求可能是'固定'或'表'格式)。這是否是一個單獨的過程,然後退出過程。當數據集很大時,我以邏輯格式(例如說一個日期範圍)讀取它,然後輸出一個'表'格式的HDF5文件。然後可以附加到這個。

  • 2)查詢(也可能是日期或其他標準)。執行計算,然後寫出NEW HDF5文件。這可以並行完成(多個進程)。請確保您在每個過程中都獨立寫入文件。

  • 3)將先前的數據文件合併成單個HDF5文件。這是一個單一的過程事件。

  • 4)根據需要重複2 & 3。

關鍵是做分立的步驟,寫出中間數據之間,退出進程之間的過程。這保持了可管理的內存數據大小,並使內存計算速度更快。此外,這允許在只讀HDF5文件上對cpu密集型操作進行多重處理。

在單獨的系統進程中執行此操作以允許系統回收內存很重要。

HTH

+0

非常感謝傑夫!要說清楚,當你說使用單獨的進程時,你的意思是使用像這樣的多處理進程:http://stackoverflow.com/a/2046630/3389318 – bobo5645

+0

此外,我讀到使用HDF5處理少於20k行的數據,可以比鹹菜慢。由於我的數據只有4k行,我應該用鹹菜嗎? – bobo5645

+0

你在問題中指出你的數據更大,所以YMMV。我更喜歡HDF5的所有數據。 – Jeff

0

雖然我不使用HDF5文件有很多經驗,我會建議可能讓你在一個更好的方向

H5py中去,是一個Python庫專門用於編碼和解碼文件,內置三個Python庫和從二進制格式。我並不是說它比Pandas HDFstore更好(我發現Pandas在處理大量數據量2.2M x 24時非常棒),但它可能會訣竅。

PyTables在內存管理對話中已經提到了幾次。我對這個圖書館沒有經驗,但是我在與memory/HDf5 problems討論的過程中看到過它。

mmap是一個用於存儲器映射(將數據從磁盤移動到內存中進行操作而不使用二進制格式化的過程)的庫。如果你猜測我沒有使用這個圖書館的經驗,那麼你會成爲贏家。

再一次,我不能在這裏談論很多經驗,但我認爲這三條路線可能會讓您更好地利用Python的內存來處理大型數據集。