阿晨1998
可以pd.merge_asof用来查找之前和之后的选项。before_df = pd.merge_asof(df1, df2, left_on='start', right_on='end', suffixes=['', '_before'])before_df# start end start_before end_before# 0 200 300 NaN NaN# 1 600 900 350.0 550.0# 2 950 1050 650.0 800.0after_df = pd.merge_asof(df2, df1, left_on='start', right_on='end', suffixes=['_after', ''])# start_after end_after start end# 0 350 550 200 300# 1 650 800 200 300# 2 900 1100 600 900但是要使其工作或子集和超集计算并不容易。对于那些人,我会争取这种可以一次性工作的算法。def range_intersect(lh_ranges, rh_ranges): all_ranges = sorted( [(b, e, 'lh') for b, e in lh_ranges] + [(b, e, 'rh') for b, e in rh_ranges] ) res = [] max_b, max_e = None, None for b, e, which in all_ranges: if which == 'rh': if max_e is None or e > max_e: max_b, max_e = b, e elif max_e is not None and e <= max_e: res.append((b, e, max_b, max_e)) return res这会发现 的元素是lh中元素的子集rh。要查找超集,可以反向运行。为简单起见,它采用范围列表而不是DataFrames。转换很简单。lh = df1.to_dict('split')['data']rh = df2.to_dict('split')['data']lh# [[200, 300], [600, 900], [950, 1050]]rh # [[350, 550], [650, 800], [900, 1100]]在那之后,DataFrame你想要的结果只是几个合并。# Compute supersets, then run in reverse to get the subsets.superset_df = pd.DataFrame(range_intersect(lh, rh), columns=['start', 'end', 'start_superset', 'end_superset'])subset_df = pd.DataFrame(range_intersect(rh, lh), columns=['start_subset', 'end_subset', 'start', 'end'])# Merge all the results together.result = df1.merge(subset_df, how='left').merge(superset_df, how='left').merge(before_df, how='left').merge(after_df, how='left')# The reversed operations, after and subset, can have many matches in df1.result.drop_duplicates(['start', 'end'])# start end start_subset end_subset start_superset end_superset start_before end_before start_after end_after# 0 200 300 NaN NaN NaN NaN NaN NaN 350.0 550.0# 2 600 900 650.0 800.0 NaN NaN 350.0 550.0 900.0 1100.0# 3 950 1050 NaN NaN 900.0 1100.0 650.0 800.0 NaN NaN