如何基于df1索引提取df2中对应行的前后行?
解决方案:提取df2中与df1索引相邻的行
首先我得明确你的需求:你想要从df2里筛选出那些索引恰好是df1各索引的前后相邻邻居的行——也就是对df1的每一个索引值,找到df2中比它小的最大索引(前序邻居)和比它大的最小索引(后序邻居),最后把这些行汇总起来(自动去重)。
第一步:构造示例数据
先把你给出的两个DataFrame用pandas正确构造出来,方便后续操作:
import pandas as pd # 构造df1 df1 = pd.DataFrame( data=[[1, 'alpha'], [3, 'alpha'], [5, 'alpha'], [9, 'alpha']], index=[3, 18, 125, 230], columns=['Id', 'B'] ) # 构造df2 df2 = pd.DataFrame( data=[ [21, 'Beta'], [33, 'Beta'], [120, 'Beta'], [36, 'Beta'], [32, 'Beta'], [71, 'Beta'], [210, 'Beta'], [53, 'Beta'], [22, 'Beta'], [1227, 'Beta'], [11, 'Beta'], [7, 'Beta'], [18, 'Beta'] ], index=[1, 2, 5, 7, 10, 14, 15, 21, 123, 127, 128, 227, 235], columns=['Id', 'B'] )
第二步:核心实现代码
我们用bisect模块做二分查找,快速定位每个df1索引在df2索引中的前后邻居,效率很高(尤其是当数据量大的时候):
import bisect # 获取df2排序后的索引列表(二分查找需要有序序列) df2_sorted_indices = sorted(df2.index) # 用集合存储目标索引,自动去重 target_indices = set() # 遍历df1的每一个索引 for idx in df1.index: # 找到当前索引在df2有序索引中的插入位置 insert_pos = bisect.bisect_left(df2_sorted_indices, idx) # 提取前序邻居:如果插入位置不是第一个,取前一个索引 if insert_pos > 0: target_indices.add(df2_sorted_indices[insert_pos - 1]) # 提取后序邻居:如果插入位置不是最后一个,取当前位置的索引 if insert_pos < len(df2_sorted_indices): target_indices.add(df2_sorted_indices[insert_pos]) # 从df2中提取目标行,保持原df2的行顺序 result_df = df2.loc[df2.index.isin(target_indices)] # 打印结果 print(result_df)
代码解释
- 排序df2索引:把df2的索引转成有序列表,这样才能用二分查找快速定位邻居,避免遍历整个df2索引(数据量大时速度差距明显)。
- 二分查找定位:
bisect_left会返回当前df1索引应该插入到df2有序索引中的位置,这个位置左边的元素都小于当前索引,右边的都大于等于当前索引。 - 收集邻居索引:根据插入位置,分别取出前一个(比当前df1索引小的最大值)和后一个(比当前df1索引大的最小值)索引,用集合存储自动去重。
- 提取目标行:用
loc和isin筛选出df2中符合条件的行,保持原df2的行顺序;如果想要按索引排序后的顺序,可以用df2.reindex(sorted(target_indices))。
运行结果
最终得到的result_df会包含df2中索引为2、5、15、21、123、127、227、235的行,完全符合你提到的期望输出范围。
内容的提问来源于stack exchange,提问作者Snowfire777
相关产品推荐
相关产品推荐

