Pandas 数据框将逻辑应用于列计算

Pandas dataframe applying logic to columns calculations

您好,我有一个具有以下结构的巨大数据框:

    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,我想使用最后观察到的值来计算变化百分比。如果我只有一只股票很容易,我只会填充这些值,但由于我有很多代码,我无法安全地执行此操作,因为我可以将代码 'a' 中的值填充到代码 'b'这不是我想要的

我想这可以通过创建一个带有 if 语句的函数来处理数据异常来解决,或者也许在 pandas 中有一个很好的方法来处理这个问题……也许是多索引?事实是我不知道如何完成这项任务,有人可以帮忙吗?

谢谢

步骤 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,这次只是 d2 索引中的 'ticker',然后取 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