【问题标题】:Determining if there is a gap in dates using pandas使用 pandas 确定日期是否有间隔
【发布时间】:2017-05-17 21:44:12
【问题描述】:

我必须确定日期集之间是否存在间隔(由开始日期和结束日期决定)。我有两个示例数据框:

import pandas as pd

a = pd.DataFrame({'start_date' : ['01-01-2014', '01-01-2015', '05-01-2016'],
             'end_date' : ['01-01-2015', '01-01-2016', '05-01-2017']})

order = ['start_date', 'end_date']

a = a[order]

a.start_date = pd.to_datetime(a.start_date, dayfirst= True)
a.end_date = pd.to_datetime(a.end_date, dayfirst= True)


b = pd.DataFrame({'start_date' : ['01-01-2014', '01-01-2015', '05-01-2016', 
'05-01-2017', '01-01-2015'],
             'end_date' : ['01-01-2015', '01-01-2016', '05-01-2017',
                          '05-01-2018', '05-01-2018']})

order = ['start_date', 'end_date']

b = b[order]

b.start_date = pd.to_datetime(b.start_date, dayfirst= True)
b.end_date = pd.to_datetime(b.end_date, dayfirst= True)

a
b

对于数据框a,解决方案很简单。按start_date 排序,将end_date 下移一位并减去日期,如果差为正数,则日期之间存在差距。

但是,为数据帧 b 实现这一点不太明显,因为存在一个包含更大范围的范围。我不确定这样做的通用方式不会错误地找到差距。这将在分组数据(大约 40000 个组)上完成。

【问题讨论】:

    标签: python date pandas


    【解决方案1】:

    这就是想法……

    • 为开始日期分配一个+1,为结束日期分配一个-1
    • 将我按所有日期排序的累积总和作为一个平面数组。
    • 当累积总和为零时……我们遇到了差距。
    • 日期值是第一优先级,其次是 start_date。这样,当一行的 end_date 等于下一行的开始日期时,我们不会在添加正数之前添加负数。
    • 我使用numpy 来分类东西并扭转和转动
    • return 间隔开始的布尔掩码。

    def find_gaps(b):
        d1 = b.values.ravel()
        d2 = np.tile([1, -1], len(d1) // 2)
        s = np.lexsort([-d2, d1])
        u = np.empty_like(s)
        r = np.arange(d1.size)
        u[s] = r
        return d2[s].cumsum()[u][1::2] == 0
    

    演示

    find_gaps(b)
    
    array([False, False, False, False,  True], dtype=bool)
    

    find_gaps(a)
    
    array([False,  True,  True], dtype=bool)
    

    【讨论】:

      【解决方案2】:

      IIUC 你可以这样做:

      In [198]: (b.sort_values('start_date')
           ...:   .stack()
           ...:   .shift().diff().dt.days
           ...:   .reset_index(name='days')
           ...:   .dropna()
           ...:   .query("level_1 == 'end_date' and days != 0"))
           ...:
      Out[198]:
         level_0   level_1   days
      5        4  end_date -365.0
      7        2  end_date -731.0
      

      以下代码应向我们显示发现差距的索引:

      In [199]: (b.sort_values('start_date')
           ...:   .stack()
           ...:   .shift().diff().dt.days
           ...:   .reset_index(name='days')
           ...:   .dropna()
           ...:   .query("level_1 == 'end_date' and days != 0")
           ...:   .loc[:, 'level_0'])
           ...:
      Out[199]:
      5    4
      7    2
      Name: level_0, dtype: int64
      

      【讨论】:

      • 我以为你已经删除了这个。好吧,不管:-)
      • @piRSquared,坦率地说我不记得了... ;-)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-11
      • 2018-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-07-29
      相关资源
      最近更新 更多