如果满足条件,Pandas iterrows 在迭代期间不能跳过行
Posted
技术标签:
【中文标题】如果满足条件,Pandas iterrows 在迭代期间不能跳过行【英文标题】:Pandas iterrows can't skip row during iteration if condition met 【发布时间】:2019-06-10 23:36:57 【问题描述】:我正在使用 iterrows 循环遍历数据帧并将第 n 行与第 n+1 行进行比较。 算法如下:
if columns 0,1,2 of row_n != columns 0,1,2 of row_n+1
output row = row_n
then check row_n+1 vs row_n+2...
if columns 0,1,2 of row_n == columns 0,1,2 of row_n+1
output row columns 0,1,2,3 = row_n columns 0,1,2,3
output row column 4 = (row_n column 4 + row_n+1 column 4)
then "skip one row" and check row_n+2 vs row_n+3...
我当前的代码适用于第一次比较,但随后停止。我的猜测是,当我试图“跳过一行”时,问题正在发生。我试图使用 index = index+1 但输出看起来不像预期的那样。我该如何解决这个问题?
row_iterator = TSG_table_sorted.iterrows()
_, row_n1 = row_iterator.__next__()
for index, row_n0 in row_iterator:
Terminal_ID_n0 = row_n0['Terminal_ID'];
TSG_n0 = row_n0['TSG'];
Date_n0 = row_n0['Date'];
Vol_n0 = row_n0['Vol'];
Terminal_no_n0 = row_n0['Terminal_no'];
Terminal_ID_n1 = row_n1['Terminal_ID'];
TSG_n1 = row_n1['TSG'];
Date_n1 = row_n1['Date'];
Vol_n1 = row_n1['Vol'];
if (Terminal_ID_n0==Terminal_ID_n1 and TSG_n0==TSG_n1 and Date_n0==Date_n1):
new_vol=Vol_n0+Vol_n1;
output_table.loc[i]=[Terminal_ID_n0,TSG_n0,Date_n0,Terminal_no_n0,new_vol]
i=i+1;
else:
output_table.loc[i]=[Terminal_ID_n0,TSG_n0,Date_n0,Terminal_no_n0,Vol_n0]
i=i+1;
index=index+1;
input
Terminal_ID TSG Date Terminal_no Vol
508 t_tel_003 CashCheck 10/1/2018 003 61
9605 t_tel_003 CashCheck 10/1/2018 003 3
2309 t_tel_003 CommercialDeposit 10/1/2018 003 12
4439 t_tel_003 CommercialDeposit 10/1/2018 003 10
9513 t_tel_003 CommercialDeposit 10/1/2018 003 122
12282 t_tel_003 CommercialDeposit 10/1/2018 003 1
current output
Terminal_ID TSG Date Terminal_no Vol
0 t_tel_003 CashCheck 10/1/2018 003 64
1 t_tel_003 CommercialDeposit 10/1/2018 003 12
2 t_tel_003 CommercialDeposit 10/1/2018 003 10
3 t_tel_003 CommercialDeposit 10/1/2018 003 122
4 t_tel_003 CommercialDeposit 10/1/2018 003 1
expected output
Terminal_ID TSG Date Terminal_no Vol
0 t_tel_003 CashCheck 10/1/2018 003 64
1 t_tel_003 CommercialDeposit 10/1/2018 003 22
3 t_tel_003 CommercialDeposit 10/1/2018 003 123
【问题讨论】:
我认为你的方法有缺陷。row_iterator
正在被遍历,index
和 row_n0
始终根据当前 row_iterator
对象的值设置。您还将row_n1
设置在循环之外并且从不更新它。这使得比较是静态的而不是动态的。我以前没有使用过 pandas,但您应该重组代码以更新循环内的 row_n1
。另外,i
是什么?我没有看到它被设置,只是被使用。
【参考方案1】:
假设您的数据框看起来像(我在底部添加了 2 行额外的行,因为您的示例没有任何东西可以重现代码的 else 部分):
Terminal_ID TSG Date Terminal_no Vol
0 t_tel_003 CashCheck 2018-01-10 3 61
1 t_tel_003 CashCheck 2018-01-10 3 3
2 t_tel_003 CommercialDeposit 2018-01-10 3 12
3 t_tel_003 CommercialDeposit 2018-01-10 3 10
4 t_tel_003 CommercialDeposit 2018-01-10 3 122
5 t_tel_003 CommercialDeposit 2018-01-10 3 1
6 t_tel_004 CommercialDeposit 2018-01-10 3 1
7 t_tel_003 CommercialDeposit 2018-01-10 4 1
如您所见,最后 2 行完全不同,考虑到所有 4 列都没有匹配项(因此输出应该有这 2 行):
使用以下内容:
df_dup = df.groupby([df.index//2,'Terminal_ID','TSG','Date','Terminal_no'])[df.columns].apply(lambda x : x[x[x.columns[:-1]].duplicated(keep=False)]['Vol'].sum()).reset_index().rename(columns=0:'Vol').drop('level_0',axis=1).replace(0,np.nan).dropna()
df_uniq =df[~df[df.columns[:-1]].duplicated(keep=False)]
pd.concat([df_dup,df_uniq],ignore_index=True)
输出
Terminal_ID TSG Date Terminal_no Vol
0 t_tel_003 CashCheck 2018-01-10 3 64.0
1 t_tel_003 CommercialDeposit 2018-01-10 3 22.0
2 t_tel_003 CommercialDeposit 2018-01-10 3 123.0
3 t_tel_004 CommercialDeposit 2018-01-10 3 1.0
4 t_tel_003 CommercialDeposit 2018-01-10 4 1.0
说明 df_dup
在 groupby 下使用 df.index//2
每 2 行分组,然后对每个组应用函数来检查每个组(这里是 2 行,不包括最后一列Vol
) 相同,然后在 Vol
列上求和。
df_uniq
:过滤完全唯一的值。
最后连接两者以获得您想要的输出。
希望这会有所帮助。如果没有,请告诉我。
【讨论】:
以上是关于如果满足条件,Pandas iterrows 在迭代期间不能跳过行的主要内容,如果未能解决你的问题,请参考以下文章
Pandas.DataFrame 的 iterrows()方法详解