Python 3.x 如何基于另一行更新数据帧?

Python 3.x 如何基于另一行更新数据帧?,python-3.x,pandas,Python 3.x,Pandas,我有一个测量学生成绩的数据框student,如下所示: ID TestDate PerformanceStatus (PS) 1 15/03/2016 0 1 01/04/2016 2 1 05/05/2016 1 1 07/06/2016 1 2 15/03/2016 0 2 01/04/2016 2 2 05/05/2016 1 2 07/06/2016 3 2 23/08/2016 1 我想更新我的表,使其具有一个新列Prev

我有一个测量学生成绩的数据框
student
,如下所示:

ID  TestDate    PerformanceStatus (PS)
1   15/03/2016  0
1   01/04/2016  2
1   05/05/2016  1
1   07/06/2016  1
2   15/03/2016  0
2   01/04/2016  2
2   05/05/2016  1
2   07/06/2016  3
2   23/08/2016  1
我想更新我的表,使其具有一个新列PreviousPerformanceStatus。 此先前的performanceStatus是根据监控的performanceStatus计算的,如下所示: 注意:如果在测试日期之前没有记录performanceStatus,我想将
PreviousPerformanceStatus=performanceStatus设置为

ID  TestDate    PS  PreviousPerformanceStatus
1   15/03/2016  0   0
1   01/04/2016  2   0
1   05/05/2016  1   2
1   07/06/2016  1   1
2   15/03/2016  0   0
2   01/04/2016  2   0
2   05/05/2016  1   2
2   07/06/2016  3   1
2   23/08/2016  1   3
我可以用SQL语句来实现这一点,但是如何用pandas更新我的数据帧呢。 谢谢

例如:
(对于ID=1的情况)先前的PerformanceStatus是基于“更早”测试日期的PerformanceStatus计算的,因此当TestDate=01/04/2016时,我想使用TestDate=15/03/2016的数据。但是,如果我找不到任何以前的数据,我将使用PerformanceStatus中的值默认先前的PerformanceStatus,并在
'ID'
上执行
groupby
,然后使用和:

如果事先知道数据帧将正确排序,则可以跳过日期转换和排序

结果输出:

   ID   TestDate  PS  PrevPS
0   1 2016-03-15   0       0
1   1 2016-04-01   2       0
2   1 2016-05-05   1       2
3   1 2016-06-07   1       1
4   2 2016-03-15   0       0
5   2 2016-04-01   2       0
6   2 2016-05-05   1       2
7   2 2016-06-07   3       1
8   2 2016-08-23   1       3

'ID'
上执行
分组,并使用和:

如果事先知道数据帧将正确排序,则可以跳过日期转换和排序

结果输出:

   ID   TestDate  PS  PrevPS
0   1 2016-03-15   0       0
1   1 2016-04-01   2       0
2   1 2016-05-05   1       2
3   1 2016-06-07   1       1
4   2 2016-03-15   0       0
5   2 2016-04-01   2       0
6   2 2016-05-05   1       2
7   2 2016-06-07   3       1
8   2 2016-08-23   1       3

为什么要使用
bfill
?下一行也会这样做,例如
df['PrevPS']=df['PS'].shift();df['PrevPS']=df['PrevPS'].fillna(0).astype(int)
@discort:为了说明“如果在测试日期之前没有记录performanceStatus,我想使PreviousPerformanceStatus=performanceStatus”的要求。单独使用
shift
将在第一个位置引入
NaN
。你不能仅仅用零填充,因为我认为不能保证第一个状态为零;示例数据中正好是这样。@discort:如果我正确阅读了问题,您需要执行
groupby
,因为移位是在
'ID'
级别进行的,而不是在数据帧上全局进行的。例如,对于您发布的代码,ID 2的“Previous”列的第一个条目将为1,而不是示例输出中显示的0。您能解释这一行吗
df['PrevPS']=df.groupby('ID')['PS'].apply(lambda-grp:grp.shift().bfill()).astype(int)
为什么要使用
bfill
?接下来的几行也会这样做,例如
df['PrevPS']=df['PS'].shift();df['PrevPS']=df['PrevPS'].fillna(0).astype(int)
@discort:为了说明“如果在测试日期之前没有记录performanceStatus,我想使PreviousPerformanceStatus=performanceStatus”的要求。单独使用
shift
将在第一个位置引入
NaN
。你不能仅仅用零填充,因为我认为不能保证第一个状态为零;示例数据中正好是这样。@discort:如果我正确阅读了问题,您需要执行
groupby
,因为移位是在
'ID'
级别进行的,而不是在数据帧上全局进行的。例如,对于您发布的代码,ID 2的“Previous”列的第一个条目将为1,而不是示例输出中显示的0。您能解释这一行吗
df['PrevPS']=df.groupby('ID')['PS'].apply(lambda-grp:grp.shift().bfill()).astype(int)