【问题标题】:Python Pandas: how to take only the earliest date in each groupPython Pandas:如何只取每组中最早的日期
【发布时间】:2018-04-08 06:16:46
【问题描述】:

这是我为这个问题创建的示例数据集:

data1 = pd.DataFrame([['1','303','3/7/2016'],
                     ['4','404','6/23/2011'],
                     ['7','101','3/7/2016'],
                     ['1','303','5/6/2017']],
                    columns=["code", "ticket #", "CB date"])
data1['CB date'] = pd.to_datetime(data1['CB date'])
data2 = pd.DataFrame([['1','303','2/5/2016'],
                     ['4','404','6/23/2011'],
                     ['7','101','3/17/2016'],
                     ['1','303','4/6/2017']],
                    columns=["code", "ticket #", "audit date"])
data2['audit date'] = pd.to_datetime(data2['audit date'])
print(data1)
print(data2)
  code ticket #    CB date
0    1      303 2016-03-07
1    4      404 2011-06-23
2    7      101 2016-03-07
3    1      303 2017-05-06
  code ticket # audit date
0    1      303 2016-02-05
1    4      404 2011-06-23
2    7      101 2016-03-17
3    1      303 2017-04-06

我想合并两个 df,并确保 CB 日期始终在审核日期或之后:

data_all = data1.merge(data2, how='inner', on=['code', 'ticket #'])
data_all = data_all[data_all['audit date'] <= data_all['CB date']]
print(data_all)
  code ticket #    CB date audit date
0    1      303 2016-03-07 2016-02-05
2    1      303 2017-05-06 2016-02-05
3    1      303 2017-05-06 2017-04-06
4    4      404 2011-06-23 2011-06-23

但是,我只想在每个审核日期之后保留 CB 日期最早的行。所以在上面的输出中,第 2 行不应该存在,因为第 1 行和第 2 行都有相同的审计日期 2016/2/5,但我只想保留第 1 行,因为 CB 日期更接近 2016/2/ 5 比第 2 行 CB 日期。

期望的输出:

code ticket #    CB date audit date
0    1      303 2016-03-07 2016-02-05
3    1      303 2017-05-06 2017-04-06
4    4      404 2011-06-23 2011-06-23

我知道在 SQL 中,我必须先按代码 & 票号 & 审核日期,然后按升序排列 CB 日期,然后在每组中取项目排名 = 1;但是如何在 Python/Pandas 中做到这一点?

我在这里阅读了其他帖子,但我仍然没有得到它,所以非常感谢这里的一些建议。

我读过的几篇文章包括:

  1. Pandas Groupy take only the first N Groups
  2. Pandas: select the first couple of rows in each group

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    我会通过可选的sort_values 调用和drop_duplicates 调用来做到这一点。

    data_all.sort_values(data_all.columns.tolist())\
              .drop_duplicates(subset=['CB date'], keep='first')
    
      code ticket #    CB date audit date
    0    1      303 2016-03-07 2016-02-05
    2    1      303 2017-05-06 2016-02-05
    4    4      404 2011-06-23 2011-06-23
    

    我说sort_values 调用在这里是可选的,因为您的数据似乎已经排序。如果不是,请确保这是您的解决方案的一部分。

    【讨论】:

    • 非常感谢您一直以来的帮助!非常感谢您的知识。但是,我想在每个“审核日期”组中对“CB 日期”进行排序,我没有看到您的代码使用任何“审核日期”输入?如果我只是对其进行排序,那么它将根据“CB日期”的整个列表进行排序,而不管它们对应于哪个“审计日期”,对吧?
    • @alwaysaskingquestions .sort_values(data_all.columns.tolist()) 按层次排序。首先对所有代码进行排序,然后在每个代码组中对所有工单进行排序,然后在每个工单组中对所有 CB 日期进行排序,然后在每个 CB 日期组中对所有审计进行排序。注意我传递给函数的参数 - 所有列名的列表。
    • 我的实际数据的列比我的示例显示的多得多,我不想根据所有列进行排序,但只对重要的少数列进行排序。所以在那种情况下,我会在.sort_values(data_all.columns.tolist())中将“data_all”替换为“data_all ['colA','colB','colC']”,对吗?感谢您对我的耐心!
    • @alwaysaskingquestions 是的,可以。也许只传递['CB date', 'audit date'] 就足够了——我对最初的解决方案有点过于偏执了。
    猜你喜欢
    • 2015-12-10
    • 2018-04-01
    • 1970-01-01
    • 2022-11-28
    • 1970-01-01
    • 2016-12-18
    • 2018-06-08
    • 2016-06-09
    • 2021-11-14
    相关资源
    最近更新 更多