为了性能(因为我们在这里寻找效率),我建议使用基于NumPy 的方法,使用broadcasting -
a = df.values
N = df.columns.values.astype(int)
df_out = pd.DataFrame((1-(1+a)**-N)/a, columns=df.columns, index=df.index)
样本输入、输出-
In [41]: df
Out[41]:
1 3
Scenario1 0.001 0.050
Scenario2 0.003 0.010
Scenario3 0.001 0.042
Scenario4 0.090 0.006
Scenario5 0.020 0.040
In [42]: df_out
Out[42]:
1 3
Scenario1 0.999001 2.723248
Scenario2 0.997009 2.940985
Scenario3 0.999001 2.764591
Scenario4 0.917431 2.964357
Scenario5 0.980392 2.775091
numexpr 模块进一步提升
查看所涉及的计算,我们似乎正在处理基于power 和division 的操作。这些可以与numexpr 模块一起使用,以进一步提高性能。
因此,我们将有两种方法,就像这样 -
import numexpr as ne
def numpy_app(df):
a = df.values
N = df.columns.values.astype(int)
return pd.DataFrame((1-(1+a)**-N)/a, columns=df.columns, index=df.index)
def numpy_numexpr_app(df):
a = df.values
N = df.columns.values.astype(int)
return pd.DataFrame(ne.evaluate('(1-(1+a)**-N)/a'), \
columns=df.columns, index=df.index)
更大数据集的运行时测试 -
In [75]: names = np.random.choice(10000,5000, replace=0)
In [76]: df = pd.DataFrame(np.random.rand(5000,5000), columns=list(names))
# @jezrael's solution using df.apply
In [77]: %timeit df.apply(lambda x: computeAnnuity(x, int(x.name)))
1 loops, best of 3: 3.54 s per loop
In [78]: %timeit numpy_app(df)
1 loops, best of 3: 1.99 s per loop
In [79]: %timeit numpy_numexpr_app(df)
1 loops, best of 3: 393 ms per loop