Pandas - 具有基于行索引的条件的lambda函数

时间:2017-12-19 00:29:33

标签: python pandas if-statement lambda

我试图通过引用三列将lambda函数应用于数据帧。我想根据以下逻辑更新其中一列Cumulative Total

如果它在第一行,那么Cumulative Total应该等于Total中的值。 如果它不是第一行,则应用以下引用前一行的公式:

x.shift()['Cumulative Total'] - (x.shift()['Total'] * (x.shift()['Annualized Rate'] / 1200))

我希望Cumulative Total列看起来像这样:

Total   Annualized Rate Cumulative Total
869     11.04718067     869
868     5.529953917     861
871     8.266360505     857
873     6.872852234     851
873     8.24742268      846
874     9.610983982     840
870     5.517241379     833
871     8.266360505     829
868     2.764976959     823

让我失望的是我如何判断我是否在第一行。这听起来相当微不足道,但我对熊猫来说非常新鲜,而且我完全被难倒了。 iloc似乎无法正常工作,因为它似乎只用于抓取给定索引的一行。

目前代码如下:

df['Cumulative Total'] = df.apply(lambda x: x['Total'] if x.iloc[0] else x.shift()['Cumulative Total']-(x.shift()['Total']*(x.shift()['Annualized Rate']/1200)),axis=1)

声明if x.iloc[0]是错误的。关于我如何确定它是否是第一行的任何想法?

修改:谢谢大家的回答。亚历山大的答案是正确的,但我注意到结果偏离了预期的结果。使用的数据框越大,这些差异就越明显。

亚历山大 - 您可以通过编辑答案来解决这个问题吗?使用vanilla Python,我已经得到了下面的结果。这些差异在很大程度上是微不足道的,但如上所述,使用更大的数据集可能会更加明显。

total=(869,868,871,873,873,874,870,871,868)
rate=(11.047181,5.529954,8.266361,6.872852,8.247423,9.610984,5.517241,8.266361,2.764977)
def f(total,rate):
     cum = []
     for i in range(len(total)):
         if i == 0:
             cum.append(total[i])
         else:
             cum.append(float(cum[i-1])-(float(total[i-1])*(rate[i-1]/1200.0)))
     return cum
f(total, rate)

返回:

869
860.9999997591667
856.9999996991667
850.99999934
845.9999995100001
839.9999992775
832.9999992641667
828.9999995391668
822.9999991800001

2 个答案:

答案 0 :(得分:2)

也许这个?

df = df.assign(
    Cumulative_Total=df['Total'].iat[0] 
                     - ((df['Total'] * df['Annualized Rate'].div(1200))
                        .shift()
                        .fillna(0)
                        .cumsum())
)

>>> df
   Total  Annualized Rate  Cumulative_Total
0    869        11.047181               869
1    868         5.529954               861
2    871         8.266361               857
3    873         6.872852               851
4    873         8.247423               846
5    874         9.610984               840
6    870         5.517241               833
7    871         8.266361               829
8    868         2.764977               823

答案 1 :(得分:0)

这会有用吗?在此解决方案中,我使用x.name来获取行索引。

df['Cumulative Total'] = df.apply(lambda x: x['Total'] if x.name == 0 else x.shift()['Cumulative Total']-(x.shift()['Total']*(x.shift()['Annualized Rate']/1200)),axis=1)