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,并计算相对于坐标中心的半径

使用 pandas GroupBy 检查组中的所有元素是不是相等

使用pandas groupby并申请累积积分

列表中的 Pandas groupby 值

Groupby 单列并使用 Pandas 合并