金融建模与熊猫数据框
问题描述:
我已经建立了一个简单的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能够修改和更新吗?
答
对于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?它应该快得多。
谢谢Jezzamon。我需要使用就地更新,所以我通常先创建所有列并填写np.nan。只是想知道这是否有任何方法来避免“if”陈述,但是将“if”逻辑应用于所有defs。 – Timescape
啊,我看到这不会按原样工作。我会编辑。 – Jezzamon
再次感谢Jezzamon。对于1,我添加了额外的df参数并将所有自定义函数移至另一个文件。对于2,模型使用t-1结果来计算年t值,因此循环数年是唯一的解决方案。不用担心时间消耗。完成所有计算只需1秒钟,因此在现阶段我更关心如何编写正确的方向。 – Timescape