如何高效提取落在pandas dataframe指定列区间内的列表值
解法1:Numpy向量化实现(代码改动最小,适配当前数据量)
原双层Python循环需要执行约8.4亿次逻辑判断,运行效率极低,向量化方案将循环下沉到C层执行,耗时可降到毫秒级:
import numpy as np # 提取df的1、2列作为区间数组 intervals = df[[1, 2]].to_numpy() lst_arr = np.array(lst) # 向量化判断每个元素是否落在任意区间内 mask = ((lst_arr[:, None] >= intervals[:, 0]) & (lst_arr[:, None] <= intervals[:, 1])).any(axis=1) # 输出结果列表 new_list = lst_arr[mask].tolist()
解法2:区间合并+二分查找(性能最优,适合更大数据量)
如果区间重叠率高、或者后续数据量继续增长,可以用该方案进一步降低时间复杂度到O(klogk + nlogk),其中k是区间数,n是列表长度:
import bisect # 1. 提取区间并按左端点排序 intervals = df[[1, 2]].to_numpy().tolist() intervals.sort(key=lambda x: x[0]) # 2. 合并重叠/相邻区间 merged = [] for start, end in intervals: if not merged: merged.append([start, end]) else: last_start, last_end = merged[-1] if start <= last_end: merged[-1][1] = max(last_end, end) else: merged.append([start, end]) starts = [x[0] for x in merged] ends = [x[1] for x in merged] # 3. 二分查找判断元素是否符合要求 new_list = [] for num in lst: idx = bisect.bisect_right(starts, num) - 1 if idx >= 0 and num <= ends[idx]: new_list.append(num)
两种方案用你给出的测试用例运行,都可以得到预期输出[182, 938]。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

