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
您好,我有一个具有以下结构的巨大数据框:
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