【问题标题】:group by pandas dataframe and select latest in each group按熊猫数据框分组并在每组中选择最新的
【发布时间】:2017-05-22 09:49:14
【问题描述】:

如何对 pandas 数据框的值进行分组并从每个组中选择最新的(按日期)?

例如,给定一个按日期排序的数据框:

    id     product   date
0   220    6647     2014-09-01 
1   220    6647     2014-09-03 
2   220    6647     2014-10-16
3   826    3380     2014-11-11
4   826    3380     2014-12-09
5   826    3380     2015-05-19
6   901    4555     2014-09-01
7   901    4555     2014-10-05
8   901    4555     2014-11-01

按 id 或产品分组,并选择最早的给:

    id     product   date
2   220    6647     2014-10-16
5   826    3380     2015-05-19
8   901    4555     2014-11-01

【问题讨论】:

    标签: python pandas group-by pandas-groupby


    【解决方案1】:

    给定一个按日期排序的数据框,您可以通过多种方式获得所需内容:

    像这样:

    df.groupby(['id','product']).last()
    

    像这样:

    df.groupby(['id','product']).nth(-1)
    

    或者像这样:

    df.groupby(['id','product']).max()
    

    如果您不希望 idproduct 显示为索引,请使用 groupby(['id', 'product'], as_index=False)。 或者使用:

    df.groupby(['id','product']).tail(1)
    

    【讨论】:

    • 在我的测试中,当同一列中有 None 值时,last() 的行为与 nth() 略有不同。例如,如果组中的第一行的值为 1,而同一组中的其余行都为 None,则 last() 将返回 1 作为值,尽管最后一行为 None。另一方面,nth(-1) 将返回 None,这更像我的预期。
    【解决方案2】:

    我遇到了类似的问题,最终使用drop_duplicates 而不是groupby

    与上面建议的其他方法相比,它在大型数据集上的运行速度似乎要快得多。

    df.sort_values(by="date").drop_duplicates(subset=["id"], keep="last")
    
        id  product        date
    2  220     6647  2014-10-16
    8  901     4555  2014-11-01
    5  826     3380  2015-05-19
    

    【讨论】:

    • 我通常也使用它,但希望更快的解决方案是使用 groupby。 groupby 直观地更有意义,通常是我们解决这个问题的方式!
    【解决方案3】:

    使用.tail() 作为聚合方法并保持分组不变:

    df.sort_values('date').groupby('id').apply(lambda x: x.tail(1))
    
            id  product date
    id              
    220 2   220 6647    2014-10-16
    826 5   826 3380    2015-05-19
    901 8   901 4555    2014-11-01
    

    【讨论】:

      【解决方案4】:

      您还可以使用tail 和 groupby 来获取组的最后 n 个值:

      df.sort_values('date').groupby('id').tail(1)
      
          id  product date
      2   220 6647    2014-10-16
      8   901 4555    2014-11-01
      5   826 3380    2015-05-19
      

      【讨论】:

      • 我喜欢这个,因为它不仅仅适用于日期。
      • 这个选项比接受的答案要快得多,但可读性较差。假设groupby 保持秩序,这不是一个问题吗?
      • groupby 保留顺序,请参阅stackoverflow.com/questions/26456125/…
      • @ade1e 代码将如何更改以执行重新采样(例如每月或每年)并保留组的最后 n 个值,而不是求和/平均?
      • 我发现这个答案比被接受的@MichaelD 更具可读性:)
      【解决方案5】:

      groupby 中使用idxmax 并将dfloc 切片

      df.loc[df.groupby('id').date.idxmax()]
      
          id  product       date
      2  220     6647 2014-10-16
      5  826     3380 2015-05-19
      8  901     4555 2014-11-01
      

      【讨论】:

      • 该解决方案对数百万条记录运行速度非常慢
      • 2021 年我收到此错误:KeyError: "Passing list-likes to .loc or [] with any missing labels.
      • 改用重新索引
      • 如果日期列有NaTs,这将不起作用吗?
      猜你喜欢
      • 2020-09-18
      • 1970-01-01
      • 2021-03-13
      • 1970-01-01
      • 2019-10-14
      • 2016-09-01
      • 2021-08-11
      • 2013-02-28
      • 1970-01-01
      相关资源
      最近更新 更多