使用Python的多个分组和groupby聚合
我有一个看起来与下面数据非常相似的数据集使用Python的多个分组和groupby聚合,python,pandas,numpy,Python,Pandas,Numpy,我有一个看起来与下面数据非常相似的数据集 我想使用sku列中的值创建两个组 第1组-新& 第2组-旧 在group1-new中,我想按机架分组,取每个分组机架的平均值,并对group1-old中的所有内容求和 数据: 期望的结果 used free total date 2 1.5 3.5 11/1/2020 2 1.5 3.5 11/1/2020 5
used free total date
2 1.5 3.5 11/1/2020
2 1.5 3.5 11/1/2020
5 14 19 11/1/2020
我们得到上述结果是因为:
第1组-新建有两组:d和e
使用d的平均值为2,无d的平均值为1.5,总计d的平均值为3.5
使用e的平均值为2,无e的平均值为1.5,总计e的平均值为3.5
group2-old只是简单地取总数
其中使用的是5个,免费的是14个,总共是19个
这是分组后数据的外观:
id group used free total date
d new 2 1 3 11/1/2020
d new 2 2 4 11/1/2020
e new 2 1 3 11/1/2020
e new 2 2 4 11/1/2020
a old 1 4 5 11/1/2020
b old 1 4 5 11/1/2020
c old 1 4 5 11/1/2020
f old 1 1 2 11/1/2020
g old 1 1 2 11/1/2020
这就是我正在做的:
new = df[df.sku.str.contains('|'.df(['new']), na = False)]
old = df[df.sku.str.contains('|'.df(['old']), na = False)]
set = jdf.groupby('rack').agg({'used': 'mean', 'free': 'mean',
'total': 'mean'}).sum().to_frame().T
我只是不知道如何把这些放在一起创建新的数据帧。
非常感谢您的建议。您可以通过条件筛选多个
sku
的匹配值,并通过~
的反向掩码筛选旧的所有不匹配值:
mask = df.sku.isin(['new','foo','foo1','foo3'])
new = df[mask]
old = df[~mask]
然后聚合平均值
,对于所有其他值,仅对数值列使用总和
:
df = (new.groupby('rack').mean()
.append(old.select_dtypes(np.number).sum().to_frame('old').T)
.rename_axis('col')
.reset_index())
print (df)
col backup free total
0 d 2.0 1.5 3.5
1 e 2.0 1.5 3.5
2 old 5.0 14.0 19.0
如果可能,按机架
和日期
分组解决方案有点变化-对于旧值,首先使用日期
值:
mask = df.sku.isin(['new','foo','foo1','foo3'])
new = df[mask]
old = df[~mask]
df = (new.groupby(['rack', 'date']).mean()
.append(old.select_dtypes(np.number).sum().to_frame(('old', old['date'].iat[0])).T)
.reset_index())
print (df)
rack date backup free total
0 d 11/1/2020 2.0 1.5 3.5
1 e 11/1/2020 2.0 1.5 3.5
2 old 11/1/2020 5.0 14.0 19.0
对于多个
sku
的匹配,您可以根据条件进行过滤;对于反转遮罩的~
的匹配,您可以根据条件过滤旧的所有不匹配值:
mask = df.sku.isin(['new','foo','foo1','foo3'])
new = df[mask]
old = df[~mask]
然后聚合平均值
,对于所有其他值,仅对数值列使用总和
:
df = (new.groupby('rack').mean()
.append(old.select_dtypes(np.number).sum().to_frame('old').T)
.rename_axis('col')
.reset_index())
print (df)
col backup free total
0 d 2.0 1.5 3.5
1 e 2.0 1.5 3.5
2 old 5.0 14.0 19.0
如果可能,按机架
和日期
分组解决方案有点变化-对于旧值,首先使用日期
值:
mask = df.sku.isin(['new','foo','foo1','foo3'])
new = df[mask]
old = df[~mask]
df = (new.groupby(['rack', 'date']).mean()
.append(old.select_dtypes(np.number).sum().to_frame(('old', old['date'].iat[0])).T)
.reset_index())
print (df)
rack date backup free total
0 d 11/1/2020 2.0 1.5 3.5
1 e 11/1/2020 2.0 1.5 3.5
2 old 11/1/2020 5.0 14.0 19.0
您可以首先通过
'sku'
按分组。然后,您可以使用get_group
,groupby
再次获取目标组并计算汇总。例如,'new'
的平均值:
g = df.groupby('sku')
g.get_group('new').groupby('rack').mean()
输出:
used free total
rack
d 2.0 1.5 3.5
e 2.0 1.5 3.5
used free total date
sku rack
new d 2.0 1.5 3.5 11/1/2020
e 2.0 1.5 3.5 11/1/2020
old 5.0 14.0 19.0 11/1/2020
您可以首先通过'sku'
按分组。然后,您可以使用get_group
,groupby
再次获取目标组并计算汇总。例如,'new'
的平均值:
g = df.groupby('sku')
g.get_group('new').groupby('rack').mean()
输出:
used free total
rack
d 2.0 1.5 3.5
e 2.0 1.5 3.5
used free total date
sku rack
new d 2.0 1.5 3.5 11/1/2020
e 2.0 1.5 3.5 11/1/2020
old 5.0 14.0 19.0 11/1/2020
除最后一组(即总和)外,所有组均采用机架平均值的方法:
#定义消费的最后一组
last_grp=‘old’
#计算除最后一组外所有组的机架平均值
out=df.query('sku!=@last_grp').groupby(['sku','rack']).mean()
#将最后一组的总和添加到df
out.loc[(last\u grp',,:]=df.query('sku==@last\u grp')。选择数据类型(np.number).sum()
#将日期添加回df(如果有多个日期,将用逗号连接)
out['date']=','.join(df.date.unique())
输出:
used free total
rack
d 2.0 1.5 3.5
e 2.0 1.5 3.5
used free total date
sku rack
new d 2.0 1.5 3.5 11/1/2020
e 2.0 1.5 3.5 11/1/2020
old 5.0 14.0 19.0 11/1/2020
注意:如果您不想汇总所有组,您需要将df.query('sku!=@last\u grp')
替换为df[df.sku.isin(target\u grps)]
,其中target\u grps
代表您的目标组(例如“new”、“foo”、“foo2”)。将机架平均值用于除最后一组以外的所有组(金额如下):
#定义消费的最后一组
last_grp=‘old’
#计算除最后一组外所有组的机架平均值
out=df.query('sku!=@last_grp').groupby(['sku','rack']).mean()
#将最后一组的总和添加到df
out.loc[(last\u grp',,:]=df.query('sku==@last\u grp')。选择数据类型(np.number).sum()
#将日期添加回df(如果有多个日期,将用逗号连接)
out['date']=','.join(df.date.unique())
输出:
used free total
rack
d 2.0 1.5 3.5
e 2.0 1.5 3.5
used free total date
sku rack
new d 2.0 1.5 3.5 11/1/2020
e 2.0 1.5 3.5 11/1/2020
old 5.0 14.0 19.0 11/1/2020
注意:如果您不想汇总所有组,您需要将df.query('sku!=@last\u grp')
替换为df[df.sku.isin(target\u grps)]
其中target\u grps
代表您的目标组(例如“新”、“foo”、“foo2”).Hi我更新了帖子。group1 new应该按机架分组,然后对所有3列(已用、免费、总计)进行平均。处理日期的方式如何?我想知道是否可以包括日期?嗯,是否可以使用。groupby(['rack',date']))
?您好,我更新了帖子。group1 new应该按机架分组,然后对所有3列(已用、免费、总计)进行平均处理日期是如何处理的
?我想知道是否可以包括日期?嗯,是否可能使用。groupby(['rack',date'])
?@Lynnette-当然,添加。重命名轴('col')。重置索引()
@Lynnette-it测试子字符串,所以需要df.sku.str.contains('.|'.join(['new','foo','foo1','foo3'])
@Lynnette-如果不是像new1
、new2
、foo569
这样的子字符串,则通过isin
工作进行测试well@Lynnette-然后df.sku.str.contains('|'.join(['new','foo','foo1','foo4']),na=False)
@Lynnette-当然,添加。重命名轴('col')。重置索引()
@Lynnette-it测试子字符串,所以需要df.sku.str.contains('.|'.join(['new','foo','foo1','foo3'])
@Lynnette-如果不是像new1
、new2
、foo569
这样的子字符串,则通过isin
工作进行测试well@Lynnette-thendf.sku.str.contains('|'.join(['new','foo','foo1','foo4']),na=False)
Hi@Caina,如果我有多个字符串要过滤怎么办?比如“new”、“foo1”、“foo2”?可能你需要在组中循环(最后一个除外,你想取和),并将它们连接起来。嗨@Lynnette,你似乎已经有了一个非常好的答案。我写这篇评论只是为了注意到我已经用一种可扩展的方法更新了答案。最好!谢谢你的帮助。嗨@Caina,如果我有多个字符串要过滤呢?比如“new”、“foo1”、“f”