如何修复Pandas中apply函数的IndexError?基于sum_result多条件映射的函数优化
Let's break down the issues in your code and fix them step by step.
Why the IndexError Happens
The error pops up because when there are no rows where sum_result=2, df.loc[df['sum_result']==2,'frame'] returns an empty Series. Trying to access .iloc[0] or .iloc[-1] on an empty Series triggers that "out-of-bounds" error.
Your current code also has a few other problems:
- You're looping through the entire DataFrame inside the
applyfunction, which is inefficient (sinceapplyalready iterates row by row) - You're using bitwise operators (
&,|) instead of logical operators (and,or) for boolean checks - The frame difference logic is flawed—you need to compare the current row's frame to all sum_result=2 frames, not just the first/last, and check if any difference is ≤10
Fixed Solution
First, precompute the frame values where sum_result=2 once (outside the apply function) to avoid redundant calculations. Then explicitly handle the case where this list is empty.
Here's the corrected code:
# Precompute the list of frame values where sum_result equals 2 icv_frames = df.loc[df['sum_result'] == 2, 'frame'].tolist() def result_func(row): sum_val = row['sum_result'] frame_val = row['frame'] if sum_val == 2: return 'ICV' elif sum_val == 1: # Only check frame differences if there are ICV frames if icv_frames: # Verify if any frame difference is within the 10 threshold if any(abs(frame_val - icv_frame) <= 10 for icv_frame in icv_frames): return 'ReviewNG' # Default to 'Other' if no ICV frames or difference is too large return 'Other' elif sum_val == 0: return 'Other' else: return "" # Apply the function to each row (axis=1 passes entire rows to the function) df['Result'] = df.apply(result_func, axis=1)
Key Improvements
- Precompute ICV Frames: We calculate
icv_framesonce instead of every row, which boosts efficiency. - Empty ICV Frame Handling: We check if
icv_framesis non-empty before accessing its values, eliminating the IndexError. - Correct Logical Checks: Use
any()to confirm if any frame difference meets the ≤10 condition, and use proper logical operators instead of bitwise ones. - Full Row Access: Using
apply(..., axis=1)lets us access bothsum_resultandframefor each row—your original code only passedsum_result, which broke the frame comparison logic.
Test the Fixed Code
Running this with your sample dataset will produce your expected output:
| frame | user1 | user2 | sum_result | Result |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | Other |
| 1 | 1 | 0 | 0 | Other |
| 2 | 2 | 0 | 1 | ReviewNG |
| 3 | 3 | 1 | 2 | ICV |
| 4 | 4 | 1 | 1 | ReviewNG |
| 5 | 5 | 0 | 0 | Other |
If there are no rows with sum_result=2, the function will skip the ReviewNG check for sum_result=1 rows and return 'Other' instead, without throwing any errors.
内容的提问来源于stack exchange,提问作者TeoK

