分组数据指定区间Trapz积分:从起始到电流最小值的积分
问题描述
我有一个结构如下的DataFrame:
Device TimeSec Current 1 0.1 0.02 1 0.25 0.05 1 0.32 0.07 1 0.45 0.01 1 0.67 0.05 1 1.01 0.08 1 1.12 0.11 1 1.32 0.15 2 0.11 0.04 2 0.22 0.06 2 0.28 0.07 2 0.35 0.02 2 0.41 0.05 2 0.51 0.08 2 0.61 0.12 ....
我的需求是:
- 每个设备的数据组中存在一个电流最小值;
- 按
Device对DataFrame进行分组,并执行trapz积分; - 积分区间为每个设备数据的
TimeSec起始点到Current最小值对应的位置。
我之前已经实现了对整个设备组的积分,代码如下:
DeviceGroup = df.groupby('Device') Result = DeviceGroup.apply(lambda x: integrate.trapz(x.Current, x=x.TimeSec))
现在需要修改为从起始到Current最小值的区间积分,请问该如何实现?
解决方案
其实只需要在apply的lambda函数里做两步调整:先找到每组中Current最小值对应的行位置,再截取从开头到这个位置(包含该位置)的子数据进行积分就可以了。
具体实现代码
from scipy import integrate # 分组后对每组数据执行自定义积分逻辑 result = df.groupby('Device').apply(lambda x: # 找到Current最小值对应的索引位置,截取数据后执行积分 integrate.trapz( x.Current.iloc[:x.Current.idxmin() + 1], x=x.TimeSec.iloc[:x.Current.idxmin() + 1] ) )
代码解释
x.Current.idxmin():这个方法会返回当前设备组中Current列最小值所在的组内相对索引(从0开始计数)。iloc[:x.Current.idxmin() + 1]:因为Python的切片是左闭右开规则,所以要加1才能包含最小值所在的那一行,这样就确保积分区间是从组内第一个数据点到电流最小值对应的点。- 积分计算:把截取后的
Current和TimeSec序列传入integrate.trapz,就能得到指定区间的积分结果。
特殊情况处理
如果同一个设备的Current列存在多个相同的最小值,idxmin()只会返回第一个出现的最小值位置。如果需要积分到最后一个最小值的位置,可以改成下面的逻辑:
from scipy import integrate result = df.groupby('Device').apply(lambda x: # 找到所有等于最小值的行,取最后一行的索引 min_rows = x[x.Current == x.Current.min()] last_min_loc = x.index.get_loc(min_rows.index[-1]) # 基于位置截取数据并积分 integrate.trapz( x.Current.iloc[:last_min_loc + 1], x=x.TimeSec.iloc[:last_min_loc + 1] ) )
这样就能确保积分区间覆盖到最后一个出现电流最小值的位置啦。
内容的提问来源于stack exchange,提问作者FunkyMore
相关产品推荐
相关产品推荐

