如果满足条件,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 正在被遍历,indexrow_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()方法详解

pandas iterrows()

pandas遍历dataframe的行:迭代遍历dataframe的数据行iterrows函数itertuple函数

如果满足多个特定条件,则在 pandas 中删除行

pandas:如果满足 3 列中的条件,则更新值

Pandas:如果特定列满足特定条件,则选择行