将逻辑应用于列计算的熊猫数据帧



嗨,我有一个巨大的数据帧,具有以下结构:

ticker  calendar-date     last-update   Assets    Ebitda  .....
0   a       2001-06-30        2001-09-14    110       1000    .....
1   a       2001-09-30        2002-01-22    0         -8      .....
2   a       2001-09-30        2002-02-01    0         800     .....
3   a       2001-12-30        2002-03-06    120       0       .....
4   b       2001-06-30        2001-09-18    110       0       .....
5   b       2001-06-30        2001-09-27    110       30      .....
6   b       2001-09-30        2002-01-08    140       35      .....
7   b       2001-12-30        2002-03-08    120       40      .....
..

我想要的是每个股票代码:为每行创建资产和 EBITDA 与上一个日历日期 (t-1) 和上一个日历日期 (t-2) 相比变化百分比的新列。

但问题来了:

1)如您所见,日历日期(按股票代码)并不总是唯一的值,因为同一日历日期可能会有更多的上次更新,但我总是希望自上次日历日期以来的变化,而不是上次更新。

2)在这种情况下,有些行的值为 0,我想使用最后一个观测值来计算 %change。如果我只有一只很容易的股票,我只会填充值,但由于我有很多股票代码,我无法安全地执行此操作,因为我可以将值从股票代码"a"填充到股票代码"b",这不是我想要的

我想这可以解决,创建一个带有 if 语句的函数来处理数据异常,或者也许有一种很好的方法可以在熊猫内部处理这个问题......也许多索引??事实是我不知道如何处理这项任务,任何人都可以提供帮助?

谢谢

步骤 1
sort_values以确保以后操作的正确排序

icols = ['ticker', 'calendar-date', 'last-update']
df.sort_values(icols, inplace=True)

步骤 2
groupby'ticker'replace零和正向填充

vcols = ['Assets', 'Ebitda']
temp = df.groupby('ticker')[vcols].apply(lambda x: x.replace(0, np.nan).ffill())
d1 = df.assign(**temp.to_dict('list'))
d1
ticker calendar-date last-update  Assets  Ebitda
0      a    2001-06-30  2001-09-14   110.0  1000.0
1      a    2001-09-30  2002-01-22   110.0    -8.0
2      a    2001-09-30  2002-02-01   110.0   800.0
3      a    2001-12-30  2002-03-06   120.0   800.0
4      b    2001-06-30  2001-09-18   110.0     NaN
5      b    2001-06-30  2001-09-27   110.0    30.0
6      b    2001-09-30  2002-01-08   140.0    35.0
7      b    2001-12-30  2002-03-08   120.0    40.0

注意:'b'的第一个'Ebitda'NaN,因为没有要转发填充的内容。

第 3 步
groupby['ticker', 'calendar-date']并抓住最后一列。 因为我们在上面排序,所以最后一行将是最近更新的行。

d2 = d1.groupby(icols[:2])[vcols].last()

第 4
步再次groupby,这次只需'ticker'哪个在d2的索引中,并采取pct_change

d3 = d2.groupby(level='ticker').pct_change()

步骤 5
join返回df

df.join(d3, on=icols[:2], rsuffix='_pct')
ticker calendar-date last-update  Assets  Ebitda  Assets_pct  Ebitda_pct
0      a    2001-06-30  2001-09-14     110    1000         NaN         NaN
1      a    2001-09-30  2002-01-22       0      -8    0.000000   -0.200000
2      a    2001-09-30  2002-02-01       0     800    0.000000   -0.200000
3      a    2001-12-30  2002-03-06     120       0    0.090909    0.000000
4      b    2001-06-30  2001-09-18     110       0         NaN         NaN
5      b    2001-06-30  2001-09-27     110      30         NaN         NaN
6      b    2001-09-30  2002-01-08     140      35    0.272727    0.166667
7      b    2001-12-30  2002-03-08     120      40   -0.142857    0.142857