Python 熊猫:根据下一行的值替换组中的列值
我正在使用这个数据框架,它必须按DocumentId和PersonId进行分组。在该组中,如果结束日期列为空,则用DocCode为RT的行填充该列 它工作得很好,但还有另一个转折点。在该DocumentId&PersonID组中,如果金额发生变化,则下一个金额的开始日期将是上一个金额的结束日期。因此,中间数据帧将如下所示: 然后,该组中所有金额重复且金额为空的行将折叠为一行 最终数据集如下所示: 下面是我用来填充DocCode为RT的行中所有空EndDate列的代码: 首先,填写金额列值以填充所有空格。这样做是为了在金额发生变化时查找。将StartDate值移回1,当检测到金额变化时,将使用该值填充EndDate列:Python 熊猫:根据下一行的值替换组中的列值,python,pandas,Python,Pandas,我正在使用这个数据框架,它必须按DocumentId和PersonId进行分组。在该组中,如果结束日期列为空,则用DocCode为RT的行填充该列 它工作得很好,但还有另一个转折点。在该DocumentId&PersonID组中,如果金额发生变化,则下一个金额的开始日期将是上一个金额的结束日期。因此,中间数据帧将如下所示: 然后,该组中所有金额重复且金额为空的行将折叠为一行 最终数据集如下所示: 下面是我用来填充DocCode为RT的行中所有空EndDate列的代码: 首先,填写金额列值以填充
df.Amount.ffill(inplace=True)
df['StartDateShift'] = df['StartDate'].shift(-1)
>>> df
DocumentID PersonID DocCode StartDate Amount EndDate StartDateShift
0 120303 110001 FB 5/18/21 245.0 NaN 5/25/21
1 120303 110001 TW 5/25/21 460.0 NaN 6/1/21
2 120303 110001 RT 6/1/21 460.0 6/6/21 4/1/21
3 120303 110011 GK 4/1/21 0.0 NaN 4/8/21
4 120303 110011 AK 4/8/21 128.0 NaN 4/12/21
5 120303 110011 PL 4/12/21 128.0 NaN 4/16/21
6 120303 110011 FB 4/16/21 256.0 NaN 4/28/21
7 120303 110011 RT 4/28/21 256.0 5/4/21 NaN
现在获取所有数量发生变化的行,并从中创建一个掩码。使用此掩码使用StartDateShift中的值填充EndDate中的NAN:
倒填EndDate值,然后在Amount列中删除重复项,将空值折叠成一行。现在还删除StartDateShift列,您将获得最终的数据帧:
df['EndDate'].bfill(inplace=True)
df = df.drop_duplicates('Amount', keep='first').drop('StartDateShift', axis=1)
>>> df
DocumentID PersonID DocCode StartDate Amount EndDate
0 120303 110001 FB 5/18/21 245.0 5/25/21
1 120303 110001 TW 5/25/21 460.0 6/6/21
3 120303 110011 GK 4/1/21 0.0 4/8/21
4 120303 110011 AK 4/8/21 128.0 4/16/21
6 120303 110011 FB 4/16/21 256.0 5/4/21
在上面的步骤中,我没有按DocumentId和PersonId列分组,因为逻辑在没有它的情况下对示例df起作用。但对于您的实际用例,您可以在DocumentId和PersonId列上应用groupby,并为每个组执行上述所有步骤,然后在最后执行concat:
dfs = []
for i,dfg in df.groupby(['DocumentID','PersonID']):
dfg.Amount.ffill(inplace=True)
dfg['StartDateShift'] = dfg['StartDate'].shift(-1)
dfg['EndDate'].fillna(dfg[~(dfg['Amount']==dfg['Amount'].shift(-1))]['StartDateShift'], inplace=True)
dfg['EndDate'].bfill(inplace=True)
dfg = dfg.drop_duplicates('Amount', keep='first').drop('StartDateShift', axis=1)
dfs.append(dfg)
final_df = pd.concat(dfs)
>>> final_df
DocumentID PersonID DocCode StartDate Amount EndDate
0 120303 110001 FB 5/18/21 245.0 5/25/21
1 120303 110001 TW 5/25/21 460.0 6/6/21
3 120303 110011 GK 4/1/21 0.0 4/8/21
4 120303 110011 AK 4/8/21 128.0 4/16/21
6 120303 110011 FB 4/16/21 256.0 5/4/21
在投票之前,至少要问一个澄清的问题。没有投票,但你共享了图像而不是文本,人们不能复制数据并测试他们的解决方案,除非他们自己逐行构建数据框架,这是极不可能的,而且pd.read_图像不存在yetMake sense,我可以用实际数据替换excel屏幕截图。通过突出显示值来自的列来显示中间结果很直观。@MustafaAydın这有帮助吗?谢谢@Ank非常感谢您的帮助!
mask = (df['Amount'] != df['Amount'].shift(-1))
df['EndDate'].fillna(df[mask]['StartDateShift'], inplace=True)
>>> df
DocumentID PersonID DocCode StartDate Amount EndDate StartDateShift
0 120303 110001 FB 5/18/21 245.0 5/25/21 5/25/21
1 120303 110001 TW 5/25/21 460.0 NaN 6/1/21
2 120303 110001 RT 6/1/21 460.0 6/6/21 4/1/21
3 120303 110011 GK 4/1/21 0.0 4/8/21 4/8/21
4 120303 110011 AK 4/8/21 128.0 NaN 4/12/21
5 120303 110011 PL 4/12/21 128.0 4/16/21 4/16/21
6 120303 110011 FB 4/16/21 256.0 NaN 4/28/21
7 120303 110011 RT 4/28/21 256.0 5/4/21 NaN
df['EndDate'].bfill(inplace=True)
df = df.drop_duplicates('Amount', keep='first').drop('StartDateShift', axis=1)
>>> df
DocumentID PersonID DocCode StartDate Amount EndDate
0 120303 110001 FB 5/18/21 245.0 5/25/21
1 120303 110001 TW 5/25/21 460.0 6/6/21
3 120303 110011 GK 4/1/21 0.0 4/8/21
4 120303 110011 AK 4/8/21 128.0 4/16/21
6 120303 110011 FB 4/16/21 256.0 5/4/21
dfs = []
for i,dfg in df.groupby(['DocumentID','PersonID']):
dfg.Amount.ffill(inplace=True)
dfg['StartDateShift'] = dfg['StartDate'].shift(-1)
dfg['EndDate'].fillna(dfg[~(dfg['Amount']==dfg['Amount'].shift(-1))]['StartDateShift'], inplace=True)
dfg['EndDate'].bfill(inplace=True)
dfg = dfg.drop_duplicates('Amount', keep='first').drop('StartDateShift', axis=1)
dfs.append(dfg)
final_df = pd.concat(dfs)
>>> final_df
DocumentID PersonID DocCode StartDate Amount EndDate
0 120303 110001 FB 5/18/21 245.0 5/25/21
1 120303 110001 TW 5/25/21 460.0 6/6/21
3 120303 110011 GK 4/1/21 0.0 4/8/21
4 120303 110011 AK 4/8/21 128.0 4/16/21
6 120303 110011 FB 4/16/21 256.0 5/4/21