如何在Pandas DataFrame中基于相邻行的撤销操作标记有效交易行(适配多连续撤销及大数据量性能需求)
Got it, let's tackle this problem properly. The core issue with your initial code is that it only handles single undo operations and relies on slow row-wise apply which won't scale for 300k rows. Instead, we need a vectorized approach that tracks which transacted records get revoked by consecutive undos, based on matching transaction_count and reverse chronological order (since undo targets the most recent matching transaction first).
Here's a scalable solution using Pandas' built-in vectorized operations:
import pandas as pd # Your original dataset df = pd.DataFrame( {'action': ['transacted','transacted','transacted','transacted','undo','transacted','transacted','transacted','transacted','transacted','undo','undo','undo','transacted'], 'transaction_count': [10,20,35,60,60,60,80,90,100,10,10,100,90,90]} ) # Step 1: Preserve original index to maintain order after filtering df['original_idx'] = df.index # Step 2: Split data into transactions and undos transactions = df[df['action'] == 'transacted'].copy() undos = df[df['action'] == 'undo'].copy() # Step 3: Assign reverse ranks within each transaction_count group # This ranks the most recent transaction as 1, next as 2, etc. transactions['reverse_rank'] = transactions.groupby('transaction_count')['original_idx'].rank(ascending=False, method='first') # Step 4: Count how many times each transaction_count was undone undo_counts = undos['transaction_count'].value_counts() # Step 5: Map undo counts to transactions and filter out revoked records transactions['undo_count'] = transactions['transaction_count'].map(undo_counts).fillna(0) transactions = transactions[transactions['reverse_rank'] > transactions['undo_count']] # Step 6: Clean up and restore original order final_result = transactions.sort_values('original_idx').drop(columns=['original_idx', 'reverse_rank', 'undo_count']) print(final_result)
How This Works:
- Original Index Preservation: We keep track of the original row order so we can sort back to the correct sequence after processing.
- Reverse Ranking: For each group of transactions with the same
transaction_count, we rank them from newest to oldest. This lets us easily identify how many of the most recent transactions get revoked. - Undo Count Mapping: We count how many times each
transaction_countwas undone, then map that number to the transaction groups. - Filtering: We keep only transactions where their reverse rank is greater than the number of undos for that count—meaning they weren't among the most recent ones revoked.
Output:
Running this code gives exactly the result you're looking for:
| action | transaction_count |
|---|---|
| transacted | 10 |
| transacted | 20 |
| transacted | 35 |
| transacted | 60 |
| transacted | 80 |
| transacted | 90 |
Performance Notes:
All operations here use Pandas' optimized vectorized functions (no row-wise apply loops), so it will handle 300k rows efficiently. Grouping and ranking operations are O(n log n) which is manageable for large datasets.
内容的提问来源于stack exchange,提问作者Caner Bas

