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

Die*_*aso 1 python logic date-arithmetic multidimensional-array pandas

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

    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      .....
..
Run Code Online (Sandbox Code Playgroud)

我想要的是每个股票行情显示:从每一行的上一个日历日期(t-1)和最后一个日历日期(t-2)开始,使用资产和Ebitda的%变化创建新列。

但是问题来了:

1)如您所见,日历日期(按行情显示)并不总是唯一值,因为同一日历日期可以有更多的最新更新,但我总是希望自上次日历日期以来的更改,而不是最后一次更新以来的更改。

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

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

谢谢

piR*_*red 5

第1步,
sort_values以确保适当的顺序以便以后操作

icols = ['ticker', 'calendar-date', 'last-update']
df.sort_values(icols, inplace=True)
Run Code Online (Sandbox Code Playgroud)

第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
Run Code Online (Sandbox Code Playgroud)

注:第一个'Ebitda''b'NaN因为没有什么可从正向填充。

步骤3
groupby ['ticker', 'calendar-date']并抓住最后一列。由于我们在上面进行了排序,因此最后一行将是最近更新的行。

d2 = d1.groupby(icols[:2])[vcols].last()
Run Code Online (Sandbox Code Playgroud)

再次执行步骤4
groupby,这次只是'ticker'在的索引中进行d2pct_change

d3 = d2.groupby(level='ticker').pct_change()
Run Code Online (Sandbox Code Playgroud)

步骤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
Run Code Online (Sandbox Code Playgroud)