优化大Pandas DataFrame积分曲线生成:替代for循环+np.trapz的高效方案
优化Pandas大型DataFrame的累积积分计算
问题分析
原代码通过for循环逐行调用np.trapz计算累积积分,每次都要重新计算从起始行到当前行的积分,时间复杂度为O(n²),对于21万行的DataFrame来说,重复计算导致效率极低。
优化方案
利用梯形积分的数学原理,先计算每两个相邻数据点之间的区间面积,再对这些面积做累积求和,时间复杂度降为O(n),大幅提升计算速度。
梯形积分的区间面积公式:对于相邻点$(x_i, y_i)$和$(x_{i+1}, y_{i+1})$,区间面积为$\frac{(y_i + y_{i+1}) \times (x_{i+1} - x_i)}{2}$,累积积分就是从第一个点到当前点所有区间面积的总和。
优化后的代码
import pandas as pd import numpy as np import plotly.graph_objects as go from plotly.subplots import make_subplots DF = pd.read_csv(r"C:\Users\hsr4ban\Desktop\Temp\Temp.csv") DF_01 = DF[["timestamps", "Data01", "Data02"]].copy() # 避免SettingWithCopyWarning # 计算相邻时间戳的差值 dx = DF_01['timestamps'].diff() # 计算相邻Data02的平均值 y_avg = (DF_01['Data02'].shift() + DF_01['Data02']) / 2 # 计算每个区间的面积 interval_area = dx * y_avg # 累积求和得到积分曲线,第一个值设为0(无前置区间时积分值为0) DF_01['Integral'] = interval_area.cumsum().fillna(0) # Plotly绘图逻辑保持不变 Fig = make_subplots(rows=2, cols=1, shared_xaxes=True) Fig.add_trace(go.Scatter(x=DF_01["timestamps"], y=DF_01["Data02"], name="Data", mode="lines"), row=1, col=1) Fig.add_trace(go.Scatter(x=DF_01["timestamps"], y=DF_01["Integral"], name="Integral", mode="lines"), row=2, col=1) Fig.show()
关键说明
- 用
diff()计算时间戳间隔、shift()获取前一行数据,结合计算单区间面积,彻底避免了重复计算。 cumsum()直接完成累积求和,效率远高于逐行循环。- 添加
.copy()是为了规避Pandas的SettingWithCopyWarning,确保操作的是独立的DataFrame副本。
内容的提问来源于stack exchange,提问作者RanjanN
相关产品推荐
相关产品推荐

