2016-03-07 109 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