如何遍历指定时间区间组合,获取两种方法的最小角度差值?
问题描述
我用Python实现了两种基于Pandas DataFrame数据的向量计算方法,现在需要在指定时间约束内遍历所有可能的两个时间区间组合,找到能让两种方法结果角度差最小的区间组合。
数据背景
数据格式示例:
epoch r1 r2 r3 2020-07-07T08:17 -6.366163 11.8 -1.2 2020-07-07T08:18 -5.163 10.38 -2.5 2020-07-07T08:19 -4.3 9.4 5.2 ........... 2020-07-07T14:00 1.25 22.2 1.5
现有代码流程:
- 时间处理:将
epoch转为datetime格式,提取时间字符串用于区间筛选 - 两种向量计算方法:
- 方法1:基于合并区间数据的协方差矩阵特征值分解,取最小特征值对应的特征向量
- 方法2:基于两个区间均值向量的叉积计算归一化向量
- 角度差计算:通过向量点积计算两个方法结果的角度差(转为度数)
核心需求
在时间约束下(比如第一个区间限制在09:00-11:00,第二个区间限制在11:00-12:00),遍历所有合法的df_1(第一个区间)和df_2(第二个区间)组合,执行完整计算流程,找到角度差最小的区间组合并输出。要求避免遗漏最优区间,角度差<1度为最优,>10度为较差。
解决方案
步骤1:优化时间处理逻辑
直接使用datetime对象处理时间,避免字符串比较的歧义,同时提取所有唯一时间点作为区间分割候选:
import pandas as pd import numpy as np import datetime # 读取数据(注意:原数据中r1列的"1 0.25"需先转为1.25格式) df = pd.read_csv("example.csv") df['epoch'] = pd.to_datetime(df['epoch'], format='%Y-%m-%dT%H:%M') # 提取所有唯一时间点,用于生成区间组合 time_points = sorted(df['epoch'].unique())
步骤2:封装核心计算函数
将现有计算逻辑拆分为独立函数,提高复用性和可读性:
def compute_method1(df1, df2): """基于协方差矩阵特征值分解计算归一化向量""" df_add = pd.concat([df1, df2], ignore_index=True) data = np.array([df_add['r1'], df_add['r2'], df_add['r3']]) covMatrix = np.cov(data, bias=True) eigval_mva, eigvec_mva = np.linalg.eig(covMatrix) eigval_mva = eigval_mva.real mincol = np.argmin(eigval_mva) eigenvect = eigvec_mva[:, mincol].real return eigenvect / np.linalg.norm(eigenvect) def compute_method2(df1, df2): """基于均值向量叉积计算归一化向量""" r1_mean = df1[['r1', 'r2', 'r3']].mean().values r2_mean = df2[['r1', 'r2', 'r3']].mean().values diff = r1_mean - r2_mean cross_r = np.cross(r1_mean, r2_mean) v = np.cross(diff, cross_r) norm_v = v / np.linalg.norm(v) if np.linalg.norm(v) != 0 else np.zeros(3) return norm_v def calculate_angle(v1, v2): """计算两个归一化向量的角度差(度数)""" if np.all(v1 == 0) or np.all(v2 == 0): return np.inf # 无效向量返回无穷大 dot_product = np.dot(v1, v2) # 避免浮点精度溢出导致arccos报错 dot_product = np.clip(dot_product, -1.0, 1.0) rad = np.arccos(dot_product) return np.rad2deg(rad)
步骤3:遍历所有合法区间组合
根据时间约束生成所有候选区间,计算并记录最优结果:
# 设定时间约束 df1_start_bound = datetime.datetime(2020, 7, 7, 9, 0) df1_end_bound = datetime.datetime(2020, 7, 7, 11, 0) df2_start_bound = datetime.datetime(2020, 7, 7, 11, 0) df2_end_bound = datetime.datetime(2020, 7, 7, 12, 0) # 筛选符合约束的时间点 df1_candidates = [t for t in time_points if df1_start_bound <= t <= df1_end_bound] df2_candidates = [t for t in time_points if df2_start_bound <= t <= df2_end_bound] # 初始化最优结果 min_angle = np.inf best_intervals = None # 遍历所有df1区间组合(start <= end) for i in range(len(df1_candidates)): df1_start = df1_candidates[i] for j in range(i+1, len(df1_candidates)): df1_end = df1_candidates[j] df1 = df[(df['epoch'] >= df1_start) & (df['epoch'] <= df1_end)] if len(df1) < 2: # 数据量不足跳过 continue # 遍历所有df2区间组合(start <= end) for k in range(len(df2_candidates)): df2_start = df2_candidates[k] for l in range(k+1, len(df2_candidates)): df2_end = df2_candidates[l] df2 = df[(df['epoch'] >= df2_start) & (df['epoch'] <= df2_end)] if len(df2) < 2: continue # 执行计算 v1 = compute_method1(df1, df2) v2 = compute_method2(df1, df2) angle_deg = calculate_angle(v1, v2) # 更新最优结果 if angle_deg < min_angle: min_angle = angle_deg best_intervals = { "df1_start": df1_start.strftime("%Y-%m-%d %H:%M"), "df1_end": df1_end.strftime("%Y-%m-%d %H:%M"), "df2_start": df2_start.strftime("%Y-%m-%d %H:%M"), "df2_end": df2_end.strftime("%Y-%m-%d %H:%M"), "angle_diff": round(angle_deg, 2) } # 输出最优结果 print("最优区间组合:") if best_intervals: print(f"第一个区间:{best_intervals['df1_start']} 至 {best_intervals['df1_end']}") print(f"第二个区间:{best_intervals['df2_start']} 至 {best_intervals['df2_end']}") print(f"角度差:{best_intervals['angle_diff']}°") else: print("未找到有效区间组合")
关键优化说明
- 时间处理:用datetime对象直接比较,避免字符串格式歧义
- 数值稳定性:添加
np.clip避免浮点精度问题导致arccos报错,处理零向量特殊情况 - 数据过滤:跳过数据量小于2的区间,避免协方差矩阵计算失效
- 遍历逻辑:严格按照时间约束生成候选区间,确保不遗漏所有合法组合
内容的提问来源于stack exchange,提问作者The first man
相关产品推荐
相关产品推荐

