如何在Pandas中实现数值符号变化后重置累积和(cumsum)?
Vectorized Solution for Resetting Cumulative Sum on Sign Change
Great question! Avoiding iterrows() is always a smart move for better performance, especially with larger DataFrames. Here's a fully vectorized approach that achieves your desired custom cumulative sum without any loops:
Full Code Implementation
import numpy as np import pandas as pd # Generate sample data (matches your example for verification) df = pd.DataFrame({'data': [-2, -1, 1, -3, -1, 2, 0, 3, -1, -2]}) # Core vectorized logic # 1. Compute signs, forward-fill zeros with the last non-zero sign signs = np.sign(df['data']) signs = signs.replace(0, np.nan).ffill().fillna(0) # Handle edge case of leading zeros # 2. Identify where the sign changes from the previous row change_points = signs != signs.shift(1) # 3. Assign unique group IDs to consecutive rows with the same sign groups = change_points.cumsum() # 4. Calculate cumulative sum within each group df['custom_cumsum'] = df.groupby(groups)['data'].cumsum() print(df)
Output (Matches Your Example)
data custom_cumsum 0 -2 -2 1 -1 -3 2 1 1 3 -3 -3 4 -1 -4 5 2 2 6 0 2 7 3 5 8 -1 -1 9 -2 -3
How It Works
Let's break down each step:
- Handle Signs & Zeros:
np.sign()gives us the sign of each value (-1, 0, 1). We replace zeros withNaNand useffill()to carry forward the last non-zero sign—this ensures zeros don't trigger a reset, which aligns with your example where the 0 continues the positive cumulative sum. - Detect Sign Changes: By comparing each sign to the previous row's sign (
shift(1)), we flag every position where the sign switches (these are our reset points). - Create Group IDs: Using
cumsum()on the change points assigns a unique ID to each continuous block of rows with the same sign. Every sign change increments the group ID. - Grouped Cumulative Sum:
groupby(groups)lets us compute the cumulative sum separately for each sign group, automatically resetting the sum whenever the group ID changes.
This method leverages pandas' optimized, C-backed operations, making it significantly faster than iterrows() for large datasets.
内容的提问来源于stack exchange,提问作者Chillar Anand
相关产品推荐
相关产品推荐

