2016-03-07 73 views
0

我已經建立了一個簡單的DCF模型,主要是通過熊貓。基本上所有的計算都發生在一個數據框中。隨着模型變得越來越複雜,模型中增加了更多變量,我想尋找更好的編碼風格。下面的例子可以說明我目前的編碼風格 - 簡單而直接。金融建模與熊貓數據框

# some customized formulas 
def GrowthRate(): 
def BoundedVal() 
.... 
# some operations 
df['EBIT'] = df['revenue'] - df['costs'] 
df['NI'] = df['EBIT'] - df['tax'] - df['interests'] 
df['margin'] = df['NI']/df['revenue'] 

我循環遍歷所有年份來計算值。現在我已經爲模型添加了500多個變量,計算也變得更加複雜。我正在考慮爲每個變量創建一個單獨的def,並相應地更新主df。所以上面的代碼將成爲:

def EBIT(t): 
    df['EBIT'][t] = df['revenue'][t] - df['costs'][t] 
    #....some more ops 
    return df['EBIT'][t] 

def NI(t): 
    df['NI'][t] = EBIT(t) - df['tax'][t] - df['interests'][t] 
    #....some more ops 
    return df['NI'][t] 

def margin(t): 
    if check_df_is_nan(): 
     df['margin'][t] = NI(t) - df['costs'][t] 
     #....some more ops 
     return df['margin'][t] 
    else: 
     return df['margin'][t] 

每個功能能夠1)如果調用由其它函數計算結果,並更新DF 2)的返回值。

爲了避免多餘的計算(如果margin(t)被多次調用),最好在每個def上添加一個「檢查val是否已經被計算過」的函數。

我的問題:1)是否可以將if語句添加到一組defs中?類似於上面的if子句。 2)我有超過50個自定義defs,所以主文件變得太長。我不能簡單地將所有defs移動到另一個文件並全部導入,因爲某些defs也會引用主文件中的數據框。有什麼建議麼?我可以將df設置爲全局變量,以便其他文件的defs能夠修改和更新嗎?

回答

0

對於1,只需檢查值是否爲NaN。

import pandas as pd 
def EBIT(t): 
    if pd.notnull(df['EBIT'][t]): 
     return df['EBIT'][t] 

    df['EBIT'][t] = df['revenue'][t] - df['costs'][t] 
    ... 

對於2,使用全局變量可能有效,但這是一種不好的方法。你應該儘可能避免使用它們。

你應該做的是讓每個函數以全局數據框爲參數。然後你可以傳入你想要操作的數據框。

# in some other file 
def EBIT(df, t): 
    # logic goes here 

# in the main file 
import operations as op 
# ... 
op.EBIT(df, t) 
enter code here 

P.S.你是否考慮過在整個柱子上操作而不是使用t?它應該快得多。

+0

謝謝Jezzamon。我需要使用就地更新,所以我通常先創建所有列並填寫np.nan。只是想知道這是否有任何方法來避免「if」陳述,但是將「if」邏輯應用於所有defs。 – Timescape

+0

啊,我看到這不會按原樣工作。我會編輯。 – Jezzamon

+0

再次感謝Jezzamon。對於1,我添加了額外的df參數並將所有自定義函數移至另一個文件。對於2,模型使用t-1結果來計算年t值,因此循環數年是唯一的解決方案。不用擔心時間消耗。完成所有計算只需1秒鐘,因此在現階段我更關心如何編寫正確的方向。 – Timescape