【发布时间】:2020-04-19 05:29:55
【问题描述】:
给定以下两个代表范围的数据框:
df1 =
start end
0 200 300
1 600 900
2 950 1050
df2 =
start end
0 350 550
1 650 800
2 900 1100
它们可以这样表示:
df1 [200 300] [600 900] [950 1050]
df2 [350 550] [650 800] [900 1100]
我的任务是确定df1 和df2 范围之间的四种不同类型的关系:
-
df2df1的子集-
df2 [650 800]df1 [600 900]的子集
-
-
df2的超集df1-
df2 [900 1100]的超集df1 [950 1050]
-
-
df2在df1之后(最近邻,不包括子集/超集)-
df2 [350 550]在df1 [200 300]之后 -
df2 [900 1100]在df1 [600 900]之后
-
-
df2在df1之前(最近邻,不包括子集/超集)-
df2 [350 550]在df1 [600 900]之前 -
df2 [650 800]在df1 [950 1050]之前
-
我正在尝试使用从this answer 学到的merge_asof(),但由于超集/子集关系添加的复杂性,它不起作用,例如:
# Create "before" condition
df_before = pd.merge_asof(
df2.rename(columns={col:f'before_{col}' for col in df2.columns}).sort_values('before_end'),
df1.assign(before_end=lambda x: x['end']).sort_values('before_end'),
on='before_end',
direction='forward'
).query('end > before_end')
print(df_before)
输出:
before_start before_end start end
0 350 550 600.0 900.0
1 650 800 600.0 900.0
目标输出:
before_start before_end start end
0 350 550 600.0 900.0
1 650 800 950.0 1050.0
问题是
pd.merge_asof(
df2.rename(columns={col:f'before_{col}' for col in df2.columns}).sort_values('before_end'),
df1.assign(before_end=lambda x: x['end']).sort_values('before_end'),
on='before_end',
direction='forward'
)
在df2 [650 800]中找到800之后最接近的df1.end,即df1 [600 900]:
before_start before_end start end
0 350 550 600.0 900.0
1 650 800 600.0 900.0
2 900 1100 NaN NaN
是否可以根据特定条件执行merge_asof() 来查找最近的值,例如“仅当该范围内的df1.start 大于800(本例中为950)时才查找最近的df1.end” ?有了这种复杂程度,也许还有其他功能更适合这项任务?
注意事项:
-
df1中的范围可以相互重叠,但绝不相同。 -
df2中的范围可以相互重叠,但绝不相同。 -
df1和df2各有超过 20 万行。 -
df1和df2的行数不同。 - 关系与
df1相关,因此df1中的每一行只需要一个匹配项,每行最多有四个关系。鉴于上面提供的数据,合并回df1后的最终输出将如下所示:
df1 =
start end subset_start subset_end superset_start superset_end before_start before_end after_start after_end
0 200 300 NaN NaN NaN NaN NaN NaN 350.0 550.0
1 600 900 650.0 800.0 NaN NaN 350.0 550.0 900.0 1100.0
2 950 1050 NaN NaN 900.0 1100.0 650.0 800.0 NaN NaN
【问题讨论】:
-
df1和df2中的每一个是否都没有重叠范围?这看起来像这种情况,每个范围内的范围不重叠,但它会影响解决方案,例如如果df1可以有许多重叠范围,例如[0, 10)、[0, 20)等。另外,您想如何处理多个匹配项?df2中的相同范围可能是df1中一行之前的最近邻居,但也可能是另一行之后的最近邻居。反之亦然。df1中的每行只需要一个匹配项吗?还是df2中的每行? -
@mcskinner 感谢您的反馈。我将更新问题以澄清。