pandas 中是不是有与 .groupby 相对的“ungroup by”操作?
Posted
技术标签:
【中文标题】pandas 中是不是有与 .groupby 相对的“ungroup by”操作?【英文标题】:Is there an "ungroup by" operation opposite to .groupby in pandas?pandas 中是否有与 .groupby 相对的“ungroup by”操作? 【发布时间】:2013-12-06 00:21:05 【问题描述】:假设我们采用 pandas 数据框...
name age family
0 john 1 1
1 jason 36 1
2 jane 32 1
3 jack 26 2
4 james 30 2
然后做一个groupby()
...
group_df = df.groupby('family')
group_df = group_df.aggregate('name': name_join, 'age': pd.np.mean)
然后进行一些聚合/汇总操作(在我的示例中,我的函数name_join
聚合了名称):
def name_join(list_names, concat='-'):
return concat.join(list_names)
因此,分组汇总输出为:
age name
family
1 23 john-jason-jane
2 28 jack-james
问题:
有没有一种快速、有效的方法可以从聚合表中获取以下内容?
name age family
0 john 23 1
1 jason 23 1
2 jane 23 1
3 jack 28 2
4 james 28 2
(注意:age
列值只是示例,我不在乎在此特定示例中平均后丢失的信息)
我认为我可以做到的方式看起来不太有效:
-
创建空数据框
在
group_df
的每一行中,将名称分开
返回一个数据框,其行数与起始行中的名称一样多
将输出附加到空数据帧
【问题讨论】:
pandas: How do I split text in a column into multiple columns?的可能重复 @AndyHayden:也许但这个问题的标题很烂;这个很简单。 (所以如果只有示例用例需要改进,最好改进它而不是关闭它) “存储在 pandas 数据框中的表” 是迂回的。只需学会将数据框视为表格(如果它代表的是它)。 这个问题有点笨拙:不要进行聚合/汇总操作然后反转它,只需在groupby()
之后停止,如有必要,对 age
进行一些平均,然后进行 reset_index()
【参考方案1】:
原来pd.groupby()
返回一个对象,原始数据存储在obj
中。所以取消分组只是提取原始数据。
group_df = df.groupby('family')
group_df.obj
示例
>>> dat_1 = df.groupby("category_2")
>>> dat_1
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7fce78b3dd00>
>>> dat_1.obj
order_date category_2 value
1 2011-02-01 Cross Country Race 324400.0
2 2011-03-01 Cross Country Race 142000.0
3 2011-04-01 Cross Country Race 498580.0
4 2011-05-01 Cross Country Race 220310.0
5 2011-06-01 Cross Country Race 364420.0
.. ... ... ...
535 2015-08-01 Triathalon 39200.0
536 2015-09-01 Triathalon 75600.0
537 2015-10-01 Triathalon 58600.0
538 2015-11-01 Triathalon 70050.0
539 2015-12-01 Triathalon 38600.0
[531 rows x 3 columns]
【讨论】:
这是一个很好的 hack,但恐怕它可能不是未来的证明。我想到了 Hadley Wickham 的 talk 关于可维护代码。他警告不要在标签外使用功能。函数维护者可能不知道最终用户以这种方式使用函数,因此他/她可能会修改函数行为,而不知道它可能会破坏现有的下游代码。你怎么看? @HanyNagaty 是的——当然有可能。请求将 ungroup() 方法添加到 pandas 会很聪明,它只会返回 grouped_df.obj。如果 ungroup() 方法不起作用,他们会添加单元测试以确保测试失败。 @HanyNagaty 我在这里打开了关于 Pandas 的 GitHub 问题。如果您喜欢此功能,请支持它。 github.com/pandas-dev/pandas/issues/43902 @MaddDancho 是的,我喜欢它,我在那里发表了评论。【参考方案2】:这是一个从分组对象中恢复原始数据帧的完整示例
def name_join(list_names, concat='-'):
return concat.join(list_names)
print('create dataframe\n')
df = pandas.DataFrame('name':['john', 'jason', 'jane', 'jack', 'james'], 'age':[1,36,32,26,30], 'family':[1,1,1,2,2])
df.index.name='indexer'
print(df)
print('create group_by object')
group_obj_df = df.groupby('family')
print(group_obj_df)
print('\nrecover grouped df')
group_joined_df = group_obj_df.aggregate('name': name_join, 'age': 'mean')
group_joined_df
create dataframe
name age family
indexer
0 john 1 1
1 jason 36 1
2 jane 32 1
3 jack 26 2
4 james 30 2
create group_by object
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x7fbfdd9dd048>
recover grouped df
name age
family
1 john-jason-jane 23
2 jack-james 28
print('\nRecover the original dataframe')
print(pandas.concat([group_obj_df.get_group(key) for key in group_obj_df.groups]))
Recover the original dataframe
name age family
indexer
0 john 1 1
1 jason 36 1
2 jane 32 1
3 jack 26 2
4 james 30 2
【讨论】:
【参考方案3】:有几种方法可以撤销DataFrame.groupby,一种方法是执行DataFrame.groupby.filter(lambda x:True),这会回到原来的DataFrame。
【讨论】:
AttributeError: 'function' 对象没有属性 'filter' 在问题的上下文中,它将是 group_df.filter(lambda x:True)。为我工作。有复制到新数据帧的开销。【参考方案4】:粗略的等价物是.reset_index()
,但将其视为groupby()
的“对立面”可能没有帮助。
您正在将一个字符串拆分为多个片段,并保持每个片段与“家庭”的关联。 This old answer of mine 完成这项工作。
只需将'family'设置为索引列,参考上面的链接,然后在最后reset_index()
得到你想要的结果。
【讨论】:
太棒了!我仍在研究 apply、lambda、pd.Series 和 stack 的组合的作用,但它完全按预期工作。谢谢!以上是关于pandas 中是不是有与 .groupby 相对的“ungroup by”操作?的主要内容,如果未能解决你的问题,请参考以下文章
pandas 中是不是有与 excel 中的 MATCH 函数等效的函数?
panda groupby ID,并计算相对于坐标中心的半径