2017-04-19 72 views
2

元素假设我有以下的数据帧df应用功能,数据帧

   1  3 
Scenario1 0.001 0.05 
Scenario2 0.003 0.01 
Scenario3 0.001 0.042 
Scenario4 0.09 0.006 
Scenario5 0.02 0.04 

假设这些利率和期限,我想计算年金。

如果你认为我只是想套用这个公式是不熟悉它:

def computeAnnuity(r,n): 
     return (1-(1+r)**-n)/r 

我怎样才能得到其中的每个元素我已经计算前的函数值的数据帧?

我想这样做

df.applymap(computeAnnuity) 

给作为r(在DF的每个元素)的返回和n列数据框的名称(即是1和3)。但我不知道如何以有效的方式做到这一点,而无需循环或循环。

换句话说,给你的Scenario1期1一个实际的例子,其中有0.001我想(1-(1+0.001)**-1)/0.001或者,例如,对于Scenario4期3在那里我有0.006我想(1-(1+0.006)**-3)/0.006。我想为数据框中的每个元素(以一种高效且自动的方式:使用该函数)完成此操作。

回答

3

我想你需要apply

def computeAnnuity(r,n): 
    return (1-(1+r)**-n)/r 

df1 = df.apply(lambda x: computeAnnuity(x, x.name)) 
print (df1) 
        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 

print ((1-(1+0.001)**-1)/0.001) 
0.9990009990008542 
2

对于性能(因为我们正在寻找的效率在这里),我会建议使用broadcasting一个NumPy基础的方法 -

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模块

在所涉及的计算展望进一步提升,看来我们正在处理powerdivision基础操作。这些可以与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