如何查找pandas DataFrame两列对应折线的交点
Pandas 计算两条顺序折线交点的方案
Pandas 本身没有内置计算折线交点的专用API,其自带的intersection方法仅支持索引、集合的精确值匹配求交,无法识别线段交叉产生的交点。
这类需求本质是相邻点构成的线段求交问题,可以直接基于线性几何原理,结合Pandas的向量化运算实现,不需要引入额外的计算几何库。
核心逻辑
两条按x顺序排列的折线,交点只会出现在x轴相邻两个采样点构成的同一区间内:
- 对每个相邻采样点构成的区间,分别取两条折线在区间两端的y值
- 如果两个序列在区间两端的y值差符号相反(或某端差值为0),说明两条线段在这个区间内存在交点
- 对存在交点的区间,用线性插值即可算出精确的交点坐标
实现代码
import pandas as pd import numpy as np # 示例数据 lst0 = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15] lst1 = [2,4,1,4,1,5,7,8,3,2,4,7,8,2,1] lst2 = [9,1,3,7,8,2,0,1,2,5,9,3,5,2,6] df = pd.DataFrame({ "index": lst0, "list1": lst1, "list2": lst2 }) # 构造相邻线段的端点坐标列 df['x_start'] = df['index'] df['x_end'] = df['index'].shift(-1) df['y1_start'] = df['list1'] df['y1_end'] = df['list1'].shift(-1) df['y2_start'] = df['list2'] df['y2_end'] = df['list2'].shift(-1) # 剔除最后一行(无后续点,无法构成线段) seg_df = df.dropna().copy() # 计算区间两端两个序列的y值差 seg_df['diff_start'] = seg_df['y1_start'] - seg_df['y2_start'] seg_df['diff_end'] = seg_df['y1_end'] - seg_df['y2_end'] # 筛选存在交点的线段区间:两端差值异号即存在交叉 cross_seg = seg_df[np.sign(seg_df['diff_start']) != np.sign(seg_df['diff_end'])].copy() # 线性插值计算精确交点坐标 cross_seg['cross_x'] = cross_seg['x_start'] - cross_seg['diff_start'] * (cross_seg['x_end'] - cross_seg['x_start']) / (cross_seg['diff_end'] - cross_seg['diff_start']) cross_seg['cross_y'] = cross_seg['y1_start'] + (cross_seg['cross_x'] - cross_seg['x_start']) * (cross_seg['y1_end'] - cross_seg['y1_start']) / (cross_seg['x_end'] - cross_seg['x_start']) # 输出所有交点 print(cross_seg[['cross_x', 'cross_y']])
说明
- 上述代码针对x轴严格递增的折线场景编写,和给出的示例数据结构完全匹配
- 如果存在线段完全重合、x值非单调的特殊场景,可以在现有判断逻辑基础上补充对应的边界规则即可
- 运行代码得到的第一个交点坐标为
(1.7, 3.4),是联立两条线段方程得到的精确结果
内容的提问来源于stack exchange,提问作者netrunner
相关产品推荐
相关产品推荐

