如何在数据框中进行后向/前向数据分组?

Posted

技术标签:

【中文标题】如何在数据框中进行后向/前向数据分组?【英文标题】:How to do Backward/forward Data grouping in a dataframe? 【发布时间】:2019-08-13 13:10:08 【问题描述】:

实际数据集中有不同类型的分组级别,我们需要不同类型的分组报告。 (注意:分组报告并不简单,请仔细阅读下面的示例)

需求示例

当我们需要报告第 4 级组报告时,需要对数据字段求和,直到第 4 级之前的最后一个值。报告编号可以是“组”列中给出的任何编号。 (请参阅预期输出以获得更清晰的信息)

对于其余的文件,处理如下:

purchase_date、Info1 和 Info2:团体级别的取货日期

数据:总和

实际数据库:

Group   purchase_date   Info1   Info2   data
2       03/23/2019      A       B       57
3       03/24/2019      A       B       48
4       03/25/2019      A       B       40
1       03/26/2019      Q       B       60
2       03/27/2019      Q       B       42
3       03/28/2019      Q       B       33
4       03/29/2019      Q       B       36
1       03/30/2019      R       B       54
2       03/31/2019      R       B       57
3       04/01/2019      R       B       53
4       04/02/2019      R       B       56
1       04/03/2019      A       B       48
2       04/04/2019      A       B       40
3       04/05/2019      A       B       45
4       04/06/2019      A       B       60
1       04/07/2019      A       B       38
2       04/08/2019      A       B       58

按上述要求分组数据后的预期输出:

4th group level report:             
Group   purchase_date   Info1   Info2   data
4       03/25/2019      A       B       145
4       03/29/2019      Q       B       171
4       04/02/2019      R       B       220
4       04/06/2019      A       B       193
4       04/08/2019      A       B       96

2nd group level Report
Group   purchase_date   Info1   Info2   data
2       03/23/2019      A       B       57
2       03/27/2019      Q       B       190
2       03/31/2019      R       B       180
2       04/04/2019      A       B       197
2       04/08/2019      A       B       201

我已经尝试过按功能分组,但我无法启动它。

谁能帮我得到想要的输出?

提前致谢。

【问题讨论】:

问题的每个部分只是将我引向问题的其他部分。如果没有我将 dfs 之间的变化拼凑在一起,这根本不清楚 好的,我仔细阅读了 :-) 你尝试了什么? @roganjosh,但所有部分都在重定向预期的输出,这里我给出了“组”列中可用的不同数据值的反向分组示例。 @Wen-Ben,我试过“Pandas group by”,但它只允许我做简单的聚合 【参考方案1】:

使用以下函数f(z, l),其中参数l 是必需的级别,z 是您的DataFrame:

def f(z, l):
    x = (z['Group'] == l) | (z.index == z.index[-1])
    cs = z['data'].cumsum()
    dx = cs - cs.where(x, np.nan).ffill().shift(1).fillna(0)
    return z[x].drop('data', 1).assign(Group=l).join(dx)

print(f(df, 2))
print(f(df, 4))

输出:

    Group purchase_date Info1 Info2   data
0       2    03/23/2019     A     B   57.0
4       2    03/27/2019     Q     B  190.0
8       2    03/31/2019     R     B  180.0
12      2    04/04/2019     A     B  197.0
16      2    04/08/2019     A     B  201.0


    Group purchase_date Info1 Info2   data
2       4    03/25/2019     A     B  145.0
6       4    03/29/2019     Q     B  171.0
10      4    04/02/2019     R     B  220.0
14      4    04/06/2019     A     B  193.0
16      4    04/08/2019     A     B   96.0

它基本上计算累积总和,每次我们遇到给定级别的记录或 DataFrame 中的最后一条记录时,cumsum 都会重置它们。

更新:使purchase_date 中的最后一行始终等于上一行 + 4 天:

def f(z, l):
    x = (z['Group'] == l) | (z.index == z.index[-1])
    cs = z['data'].cumsum()
    dx = cs - cs.where(x, np.nan).ffill().shift(1).fillna(0)
    zz = z[x].drop('data', 1).assign(Group=l).join(dx)
    zz['purchase_date'] = pd.to_datetime(zz['purchase_date'])
    zz.at[zz.index[-1], 'purchase_date'] = zz.at[zz.index[-2], 'purchase_date'] + pd.Timedelta('4d')
    return zz

【讨论】:

感谢您的回答。是否可以保持最后一行“purchase_date”中的差距? “purchase_date”列中有 4 天的间隔,我在最后一行也需要。 它总是紧挨着最后一个值 + 4 天,还是您需要以某种方式动态得出这个? 我认为这行不通,因为您使用的是 index[-2] 因此它将引用 df 的倒数第二行,但我们尚未重置索引,还有其他解决方法吗? 你是对的,当然。我认为最简单的方法是将我们要返回的结果保存为新的 DataFrame zz,然后进行调整。请参阅我的答案的更新部分

以上是关于如何在数据框中进行后向/前向数据分组?的主要内容,如果未能解决你的问题,请参考以下文章

如何根据数据框中的值有条件地对数据进行分组?

在 pandas 数据帧中使用前向和后向填充填充缺失值(ffill 和 bfill)

卷积神经网络前向传播和BP后向传播计算步骤

如何使前向词,后向词,将下划线视为单词的一部分?

在熊猫数据框中对重复的列 ID 进行分组

前向链接与后向链接