1 回答
TA贡献2037条经验 获得超6个赞
可以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.0
after_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
添加回答
举报