You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

优化DataFrame迭代:高效识别与处理设备充电周期子集

优化充电周期提取的DataFrame处理性能

Hey, let's break down how to optimize your battery cycle extraction code further—you've already made solid improvements by ditching iterrows() and using get_value(), so let's build on that.

First, let's recap the context clearly:
We have a Pandas DataFrame tracking device battery status, with columns timestamp, battery_state, and battery_level. Our goal is to split this into distinct charging cycles, where a cycle ends when the current row's battery level drops below the previous one (signaling a new cycle starts after a discharge).

Raw Data Example

timestamp          battery_state  battery_level
0   2017-10-08 13:42:02  Charging        0.94
1   2017-10-08 13:45:43  Charging        0.95
2   2017-10-08 13:49:08  Charging        0.96
3   2017-10-08 13:54:07  Charging        0.97
4   2017-10-08 13:57:26  Charging        0.98
5   2017-10-08 14:01:35  Charging        0.99
6   2017-10-08 14:03:03  Full            1.00
7   2017-10-08 14:17:19  Charging        0.98
8   2017-10-08 14:26:05  Charging        0.97
9   2017-10-08 14:46:10  Charging        0.98
10  2017-10-08 14:47:47  Full            1.00
11  2017-10-08 16:36:24  Charging        0.91
12  2017-10-08 16:40:32  Charging        0.92
13  2017-10-08 16:47:58  Charging        0.93
14  2017-10-08 16:51:51  Charging        0.94
15  2017-10-08 16:55:26  Charging        0.95

Your Current Optimized Code

Here's the implementation you've already tuned for better performance:

previous_index = 0  # stores the initial index of each period
for index in islice(device_charge_samples.index, 1, None):  # skip first row since no previous sample
    # Detect period boundary: current battery level < previous level
    if device_charge_samples.get_value(index, 'battery_level') < device_charge_samples.get_value(index - 1, 'battery_level'):
        subset = device_charge_samples[previous_index:index].reset_index(drop=True)
        # Process subset function here
        previous_index = index
# Handle last period case
subset = device_charge_samples[previous_index:].reset_index(drop=True)
# Process subset function here

Recommendations for Further Optimization

The biggest gains come from moving away from Python-level loops entirely and using Pandas' vectorized operations. Here's how:

1. Vectorized Boundary Detection & Cycle ID Assignment

Instead of looping to find cycle splits, use diff() and cumsum() to mark cycles in one go—this leverages underlying NumPy operations, which are way faster than Python loops:

# Calculate where battery level drops (signaling new cycle start)
cycle_starts = device_charge_samples['battery_level'].diff() < 0
# Fill the first row's NaN with False (it's the start of the first cycle)
cycle_starts.iloc[0] = False

# Assign unique ID to each cycle using cumulative sum
device_charge_samples['cycle_id'] = cycle_starts.cumsum()

2. Split Cycles with groupby()

Once you have the cycle_id column, use groupby() to split the DataFrame into cycles efficiently. This eliminates manual slicing and looping:

# Iterate over each cycle group
for cycle_id, subset in device_charge_samples.groupby('cycle_id'):
    # Reset index if needed (groupby retains original indices by default)
    subset = subset.reset_index(drop=True)
    # Process your subset here
    print(f"Processing cycle {cycle_id} with {len(subset)} rows")

3. Why apply() Isn't the Best Fit

While apply() can technically work, it's still a Python-level loop under the hood for row-wise operations. It won't give you a performance boost over your current optimized loop—stick with the vectorized groupby() approach instead.

4. Bonus: Minimal Memory Optimization

If you want to avoid adding a new column, you can group directly using the cycle start array:

cycle_ids = cycle_starts.cumsum()
for cycle_id, subset in device_charge_samples.groupby(cycle_ids):
    # Process subset here
    pass

Performance Breakdown

  • Your current loop: Fast for small datasets, but slows down significantly with 100k+ rows.
  • Vectorized groupby() approach: ~10-100x faster for large datasets, since it uses C-level operations instead of Python iteration.

内容的提问来源于stack exchange,提问作者Ruben Alves

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:54:56