如何查找日期范围重叠的行?

Abe*_*ler 6 python pandas

我有一个包含如下数据的数据框(数据的微小子集):

在此处输入图片说明

我试图找出一个办法,我可以创建一个包含具有相同值的所有行一个新的数据框中:carrierflightnumberdepartureAirportarrivalAirport,但也有日期范围重叠的。

通过重叠,我的意思是effectiveDate一行位于effectiveDatediscontinuedDate另一条记录之间,该记录与我提到的其他列具有相同的值。

所以在我上面的例子中,前两行将被视为一个例子(并且都应该包含在新的数据框中),但第三行不是。

我假设我想使用groupby,但我并不完全清楚我将应用什么聚合函数。以下是我到目前为止所拥有的:

df.groupby(['carrier','flightnumber','departureAirport','arrivalAirport'])['effectiveDate', 'discontinuedDate'].min()
Run Code Online (Sandbox Code Playgroud)

但显然我需要应用一个函数来确定重叠而不是min(). 我将如何识别重叠而不是返回该组的最小值?

更新:

carrier flightnumber  departureAirport  arrivalAirport  effectiveDate discontinuedDate
4U      9748          DUS               GVA             2017-05-09    2017-07-12
4U      9748          DUS               GVA             2017-05-14    2017-07-16
4U      9748          DUS               GVA             2017-07-18    2017-08-27
AG      1234          SFO               DFW             2017-03-09    2017-05-12
AG      1234          SFO               DFW             2017-03-14    2017-05-16
Run Code Online (Sandbox Code Playgroud)

更新 2:

至于输出变为我想有重叠的任何行,并有相同的价值观carrierflightnumberdepartureAirportarrivalAirport在一个新的数据帧返回。这些行不需要包含任何其他数据。所以对于上面的示例数据,像下面这样的数据帧将是我想要的输出:

carrier flightnumber  departureAirport  arrivalAirport  effectiveDate discontinuedDate
4U      9748          DUS               GVA             2017-05-09    2017-07-12
4U      9748          DUS               GVA             2017-05-14    2017-07-16
AG      1234          SFO               DFW             2017-03-09    2017-05-12
AG      1234          SFO               DFW             2017-03-14    2017-05-16
Run Code Online (Sandbox Code Playgroud)

请注意,仅排除了一条记录(第三条为9748) - 这是因为它的日期范围与同一航班的其他记录不重叠。

piR*_*red 5

高层次概念

  • 按所有日期排序,然后按优先级effectiveDate(是否完全重叠)进行排序。
  • 对排序之前初始化的交替值和负值进行累积求和。要点是,当累积和高于 时,就会发生重叠1。当总和降至 时,连续组结束0
  • 取消排序并确定零发生的位置......这些是重叠组的末尾。
  • 在这些断点上分割数据帧索引,并且仅在分割大小大于的情况下进行分割1
  • 连接传递的分割并用于loc获取切片数据帧。

def overlaping_groups(df):
    n = len(df)
    cols = ['effectiveDate', 'discontinuedDate']
    v = np.column_stack([df[c].values for c in cols]).ravel()
    i = np.tile([1, -1], n)
    a = np.lexsort([-i, v])
    u = np.empty_like(a)
    u[a] = np.arange(a.size)
    e = np.flatnonzero(i[a].cumsum()[u][1::2] == 0)
    d = np.diff(np.append(-1, e))
    s = np.split(df.index.values, e[:-1] + 1)

    return df.loc[np.concatenate([g for j, g in enumerate(s) if d[j] > 1])]

gcols = ['carrier', 'flightnumber', 'departureAirport', 'arrivalAirport']
df.groupby(gcols, group_keys=False).apply(overlaping_groups)

  carrier  flightnumber departureAirport arrivalAirport effectiveDate discontinuedDate
0      4U          9748              DUS            GVA    2017-05-09       2017-07-12
1      4U          9748              DUS            GVA    2017-05-14       2017-07-16
3      AG          1234              SFO            DFW    2017-03-09       2017-05-12
4      AG          1234              SFO            DFW    2017-03-14       2017-05-16
Run Code Online (Sandbox Code Playgroud)