【问题标题】:Sum the values of certain rows to another nearest row based on condition根据条件将某些行的值与另一个最近的行相加
【发布时间】:2019-12-17 05:08:02
【问题描述】:

我有如下数据框

id  log loc     pos_evnts   neg_evnts   As  non_As  pos_wrds    neg_wrds    As/Ac
A   c   City    8           0           48  0       0           0           1
A   d   City    2           6           0   180     4           10          0
A   e   City    0           22          87  0       0           0           1
A   f   City    8           0           35  0       0           0           1
A   g   City    8           2           42  0       0           0           1
A   h   City    4           4           0   115     4           2           0
A   i   City    2           0           32  0       0           0           1
B   j   Hill    3           0           24  0       0           0           1
B   k   City    6           8           116 0       0           2           1
B   l   City    2           4           200 0       0           2           1
C   m   City    2           0           40  0       0           0           0
C   n   Hill    5           0           1   0       2           0           0
C   o   City    5           0           7   0       0           5           1

如您所见,As/Ac 列中有零 (0)。 我想要做的是,当我们有一个零时,将零行的值添加到下 1 行。预期的结果如下所示。

此处“零”行的值添加到其下方的壁橱 1 行,但“零”行本身并未更改。

id  log loc     pos_evnts   neg_evnts   As  non_As  pos_wrds    neg_wrds    As/Ac
A   c   City    8           0           48  0       0           0           1
A   d   City    2           6           0   180     4           10          0
A   e   City    2           28          87  180     4           10          1
A   f   City    8           0           35  0       0           0           1
A   g   City    8           2           42  0       0           0           1
A   h   City    4           4           0   115     4           2           0
A   i   City    6           4           32  115     4           2           1
B   j   Hill    3           0           24  0       0           0           1
B   k   City    6           8           116 0       0           2           1
B   l   City    2           4           200 0       0           2           1
C   m   City    2           0           40  0       0           0           0
C   n   Hill    5           0           1   0       2           0           0
C   o   City    12          0           48  0       5           5           1

此处添加到下面壁橱 1 行的“零”行的值以及“零”行本身使用新值更新,但 As/Ac 列除外。 我希望 As/Ac 保持不变,因为我稍后会删除零行。


id  log loc     pos_evnts   neg_evnts   As  non_As  pos_wrds    neg_wrds    As/Ac
A   c   City    8           0           48  0       0           0           1
A   d   City    2           28          87  180     4           10          0
A   e   City    2           28          87  180     4           10          1
A   f   City    8           0           35  0       0           0           1
A   g   City    8           2           42  0       0           0           1
A   h   City    6           4           32  115     4           2           0
A   i   City    6           4           32  115     4           2           1
B   j   Hill    3           0           24  0       0           0           1
B   k   City    6           8           116 0       0           2           1
B   l   City    2           4           200 0       0           2           1
C   m   City    12          0           48  0       5           5           0
C   n   Hill    12          0           48  0       5           5           0
C   o   City    12          0           48  0       5           5           1

我尝试了df['As/Ac'].shift(fill_value=0).shift(-1).cumsum(),它给出了组',其中零后面跟着一个,但我无法继续进行(总结它们),因为我需要保留前 3 列并且它们是不同的。

我也尝试了以下方法,但出现错误。

df['validheads'] = df['As/Ac'].shift(fill_value=0).shift(-1).cumsum()
df.iloc[:,3:].groupby(['validheads'],as_index=False).sum()

【问题讨论】:

    标签: python python-3.x pandas pandas-groupby


    【解决方案1】:

    您可以反向 cumsum(反转 As/Ac 列后的 cumsum)和该列上的组然后使用 .agg 聚合值

    df.groupby(df.loc[::-1, 'As/Ac'].cumsum()[::-1]).agg({'id': 'last',
                                                          'log': 'last',
                                                          'loc': 'last',
                                                          'pos_evnts':'sum',
                                                          'neg_evnts':'sum',
                                                          'As':'sum',
                                                          'non_As':'sum',
                                                          'pos_wrds':'sum',
                                                          'neg_wrds':'sum',
                                                          'As/Ac': 'last'}).sort_index(ascending=False).reset_index(drop=True)
    
    

    输出将是

        id  log loc     pos_evnts   neg_evnts   As  non_As  pos_wrds    neg_wrds    As/Ac
    0   A   c   City    8           0           48  0       0           0           1
    1   A   e   City    2           28          87  180     4           10          1
    2   A   f   City    8           0           35  0       0           0           1
    3   A   g   City    8           2           42  0       0           0           1
    4   A   i   City    6           4           32  115     4           2           1
    5   B   j   Hill    3           0           24  0       0           0           1
    6   B   k   City    6           8           116 0       0           2           1
    7   B   l   City    2           4           200 0       0           2           1
    8   C   o   City    12          0           48  0       2           5           1
    

    【讨论】:

    • 您实际上可以更轻松地实现这一点:df.groupby(df.loc[::-1, 'As/Ac'].cumsum()[::-1]).cumsum() 恭喜在反向 cumsum 上,我将使用将其添加到我的知识库:-) 你的回答将匹配 moys 与 df.groupby(df.loc[::-1, 'As/Ac'].cumsum()[::- 1]).cumsum()
    • OP 还想要前三列
    • 我想他会更喜欢这个:df.groupby(df.loc[::-1, 'As/Ac'].cumsum()[::-1]).cumsum( ) ;-) 当你添加它时,我将删除我的答案。
    • 请将此添加到您的答案中,以便其他人以后可以参考
    • 谢谢施吉特。这就是我一直在寻找的
    【解决方案2】:

    moys,在 jezrael 的帮助下,我完成了我的解决方案,我错过了我在下面添加的两行

    df['Truth'] = df['As/Ac'] == 0 | ( (df['As/Ac'].shift() == 0) & (df['As/Ac'] == 1) ) 
    df['T'] = df['Truth'].ne(df['Truth'].shift()).cumsum() 
    # from jezrael
    cols = df.select_dtypes(np.number).columns.difference(['T']) 
    df.loc[df['Truth'], cols] = df.loc[df['Truth'], cols] .groupby(df['T']).cumsum()
    
       id log   loc  pos_evnts  neg_evnts   As  non_As  pos_wrds  neg_wrds  As/Ac  Truth  T
    0   A   c  City          8          0   48       0         0         0      1  False  1
    1   A   d  City          2          6    0     180         4        10      0   True  2
    2   A   e  City          2         28   87     180         4        10      1   True  2
    3   A   f  City          8          0   35       0         0         0      1  False  3
    4   A   g  City          8          2   42       0         0         0      1  False  3
    5   A   h  City          4          4    0     115         4         2      0   True  4
    6   A   i  City          6          4   32     115         4         2      1   True  4
    7   B   j  Hill          3          0   24       0         0         0      1  False  5
    8   B   k  City          6          8  116       0         0         2      1  False  5
    9   B   l  City          2          4  200       0         0         2      1  False  5
    10  C   m  City          2          0   40       0         0         0      0   True  6
    11  C   n  Hill          7          0   41       0         2         0      0   True  6
    12  C   o  City         12          0   48       0         2         5      1   True  6
    

    在他的许可下修改 Shijith 的答案,您将获得:

    In [4658]: df.groupby(df.loc[::-1, 'As/Ac'].cumsum()[::-1]).cumsum()                                                                                                                           
    Out[4658]: 
        pos_evnts  neg_evnts   As  non_As  pos_wrds  neg_wrds  As/Ac
    0           8          0   48       0         0         0      1
    1           2          6    0     180         4        10      0
    2           2         28   87     180         4        10      1
    3           8          0   35       0         0         0      1
    4           8          2   42       0         0         0      1
    5           4          4    0     115         4         2      0
    6           6          4   32     115         4         2      1
    7           3          0   24       0         0         0      1
    8           6          8  116       0         0         2      1
    9           2          4  200       0         0         2      1
    10          2          0   40       0         0         0      0
    11          7          0   41       0         2         0      0
    12         12          0   48       0         2         5      1
    
    

    【讨论】:

    • 感谢您的回答。我投了赞成票。但是,我接受 Shijith 的回答,因为我想要前 3 列(它们是文本)和他的代码,As/Ac 列中的零(0)行也被删除(我想稍后单独做)跨度>
    • 他值得称赞。非常感谢你提出这么有趣的问题,我为解决这些问题而活,我希望有更多这样的问题:-)
    猜你喜欢
    • 2022-12-10
    • 2021-07-16
    • 1970-01-01
    • 1970-01-01
    • 2015-07-01
    • 2014-02-05
    • 1970-01-01
    • 2022-06-28
    • 1970-01-01
    相关资源
    最近更新 更多