【问题标题】:pandas - how to get last n groups of a groupby object and combine them as a dataframepandas - 如何获取 groupby 对象的最后 n 组并将它们组合为数据框
【发布时间】:2019-03-24 12:27:43
【问题描述】:

如何获取df.groupby() 之后的最后 'n' 个组并将它们组合为一个数据框。

data = pd.read_sql_query(sql=sqlstr, con=sql_conn, index_col='SampleTime')
grouped = data.groupby(data.index.date,sort=False)

在完成grouped.ngroups 之后,我得到的组总数为 277。我想合并最后 12 个组并生成一个数据框。

【问题讨论】:

    标签: python pandas pandas-groupby


    【解决方案1】:

    在列表理解中使用pd.concatgroupby.get_group

    pd.concat([grouped.get_group(x) for x in list(grouped.groups.keys())[-12:]])
    

    【讨论】:

    • 我刚刚在我正在处理的数据框上尝试了这个,这似乎是 OP 要求的? ed: concat 不起作用,但 .tail(12) 返回了最后 12 个组
    • 新版本应该与 OP 想要的保持一致 :) (尽管它与 rahlf23 的版本相比并没有提供太多)
    • @MathewSavage 真的很有趣,文档说它返回每个组的最后一行,而不是最后一组。也许我也应该测试一下
    【解决方案2】:

    假设你知道grouped的顺序

    grouped = zip(*df.groupby(data.index.date,sort=False))
    pd.concat(list(grouped)[1][-12:])
    

    【讨论】:

      【解决方案3】:

      您可以将列表解析传递给pd.concat()

      import pandas as pd
      
      df = pd.DataFrame([
      ['A',1,2],
      ['A',7,6],
      ['B',1,3],
      ['B',9,9],
      ['C',1,8],
      ['A',4,3],
      ['C',7,6],
      ['D',4,2]],
      columns=['Var','Val1','Val2'])
      
      last_n = 2
      grouped = df.groupby('Var')
      
      pd.concat([grouped.get_group(group) for i, group in enumerate(grouped.groups) if i>=len(grouped)-last_n])
      

      产量:

        Var  Val1  Val2
      4   C     1     8
      6   C     7     6
      7   D     4     2
      

      【讨论】:

        【解决方案4】:

        Pandas GroupBy 对象是可迭代的。要提取可迭代对象的最后 n 个元素,通常无需从可迭代对象创建列表并切片最后 n 个元素。这会占用大量内存。

        相反,您可以使用itertools.islice(由@mtraceur 建议)或collections.deque。两者都在 O(n) 时间内工作。

        itertools.islice

        与生成器不同,Pandas GroupBy 对象是可重复使用的可迭代对象。因此,您可以通过len(g) 计算GroupBy 对象g 的组数,然后通过islice 切片g。或者,也许更习惯用法,您可以使用GroupBy.ngroups。然后使用pd.concat 连接一个可迭代的数据帧:

        from operator import itemgetter
        
        g = data.groupby(data.index.date, sort=False)
        res = pd.concat(islice(map(itemgetter(1), g), max(0, g.ngroups-12), None))
        

        collections.deque

        或者,您可以使用collections.deque 并指定maxlen,然后像以前一样连接。

        from collections import deque
        
        grouped = data.groupby(data.index.date, sort=False)
        res = pd.concat(deque(map(itemgetter(1), grouped), maxlen=12))
        

        collections 文档中所述:

        一旦有界长度deque 已满,当添加新项目时, 从另一端丢弃相应数量的项目.... 它们对于跟踪交易和其他数据池也很有用 仅对最近的活动感兴趣。

        【讨论】:

        • 在您的示例中,在哪里可以看到您恢复了最后 5 个?
        • 使用双端队列很好,但您仍在迭代所有组。所以优点是在这种情况下可以节省内存,对吗?无论如何都很好
        • @RafaelC,是的,优点主要是内存使用量较低。您无法避免遍历所有组。
        • 我很好奇,您是否也考虑/评估过使用itertools.islice(map(...), len(grouped) - 12, len(grouped) 而不是collections.deque(map(...), maxlen=12)?我的直觉是在这种情况下更喜欢islice,但也许我错过了什么?
        • @mtraceur,我已经添加了islice 解决方案(但使用ngroups),希望没问题。
        猜你喜欢
        • 2019-01-14
        • 2023-01-03
        • 2018-03-31
        • 2015-02-01
        • 2021-01-22
        • 1970-01-01
        • 1970-01-01
        • 2019-06-09
        • 1970-01-01
        相关资源
        最近更新 更多