如何在数据框中进行后向/前向数据分组?
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 的倒数第二行,但我们尚未重置索引,还有其他解决方法吗? 你是对的,当然。我认为最简单的方法是将我们要返回的结果保存为新的 DataFramezz
,然后进行调整。请参阅我的答案的更新部分以上是关于如何在数据框中进行后向/前向数据分组?的主要内容,如果未能解决你的问题,请参考以下文章