代码之家  ›  专栏  ›  技术社区  ›  Jack

熊猫在<>运算符上合并

  •  3
  • Jack  · 技术社区  · 5 年前

    我有一个 df 从A->B/C起飞,从B/C->Z起飞。

    schedule

    我想在A->Z之间找到可能的一站式路线。这需要在B/C处停车。

    简单的合并就可以了。

    routes = pd.merge(df , df , left_on = 'Destination' , right_on = 'Origin')
    

    Routes

    但是,我的日程表df有来自a->b/c/d/../y的数千个航班和来自b/c/d/../y->z的数千个航班。将此表与自身合并会导致 routes 有几十亿行长的表。我可以过滤到一个小的df,过滤到24小时的路由。

    routes = routes[routes['Time_y'] - routes['Time_x'] < 24]
    

    首先计算所有可能的路线,然后过滤到那些有一个布局<24小时计算是不可行的。有什么方法可以表演 pd.merge 同时要有24小时的休息时间?伪代码是:

    routes = pd.merge(df , df , left_on = 'Destination' , right_on = 'Origin' , right['Time'] - left['Time'] < 24)
    

    以下是示例数据:

    df = pd.DataFrame({'Origin': {1: 'A', 6: 'A', 11: 'A', 16: 'A', 21: 'B', 26: 'B', 31: 'C', 36: 'C'}, 'Destination': {1: 'B', 6: 'B', 11: 'C', 16: 'C', 21: 'Z', 26: 'Z', 31: 'Z', 36: 'Z'}, 'Dept_Time': {1: pd.Timestamp('2019-03-30 17:31:00'), 6: pd.Timestamp('2019-05-16 17:32:00'), 11: pd.Timestamp('2019-04-01 08:30:00'), 16: pd.Timestamp('2019-06-09 08:20:00'), 21: pd.Timestamp('2019-07-26 08:31:00'), 26: pd.Timestamp('2019-03-31 06:16:00'), 31: pd.Timestamp('2019-07-03 23:52:00'), 36: pd.Timestamp('2019-03-27 17:31:00')}, 'Arrv_Time': {1: pd.Timestamp('2019-03-30 23:23:00'), 6: pd.Timestamp('2019-05-16 23:22:00'), 11: pd.Timestamp('2019-04-01 14:22:00'), 16: pd.Timestamp('2019-06-09 14:18:00'), 21: pd.Timestamp('2019-07-26 14:23:00'), 26: pd.Timestamp('2019-06-18 05:00:00'), 31: pd.Timestamp('2019-07-04 05:36:00'), 36: pd.Timestamp('2019-03-27 23:23:00')}})
    
    0 回复  |  直到 5 年前
        1
  •  0
  •   Parfait    5 年前

    考虑计算未来(提前1天)日期,并将其添加到与源/目标合并:

    from datetime import timedelta
    ...
    
    df['Future_Time'] = df['Flight_Time'] + timedelta(days=1)
    
    merged_df = pd.merge(df, df, 
                         left_on = ['Destination', 'Future_Time'],
                         right_on = ['Origin', 'Flight_Time'],
                         suffixes=['_o','_d'])
    

    假设您的飞行时间包含影响合并联接的时间组件,请将日期规格化为计算的未来日期之前的最后一个午夜,然后合并:

    df['Normalized_Time'] = df['Flight_Time'].dt.normalize()
    df['Future_Time'] = df['Normalized_Time'] + timedelta(days=1)
    
    merged_df = pd.merge(df, df, 
                         left_on = ['Destination', 'Future_Time'],
                         right_on = ['Origin', 'Normalized_Time'],
                         suffixes=['_o','_d'])
    

    以上可能导致24-48小时配对问题。但从那里你可以根据24小时的时间跨度在更小的一组上过滤:

    merged_df[merge_df['Flight_Time_d'] <= merge_df['Flight_Time_o'] + timedelta(days=1)]
    

    或者一起:

    merged_df = (pd.merge(df, df, 
                          left_on = ['Destination', 'Future_Time'],
                          right_on = ['Origin', 'Normalized_Time'],
                          suffixes=['_o','_d'])
                   .query("Flight_Time_d <= Flight_Time_o + timedelta(days=1)")
                )