如何基于DataFrame互斥规则及日期条件创建错误标记?(Python Pandas)
Solution for Mutual Exclusion Validation with Date Conditions
Got it, let's break down how to solve this problem efficiently—especially for large datasets (millions of rows) while handling both mutual exclusion rules and date validity checks.
Step 1: Preprocess Date Columns
First, we need to convert string date columns to datetime type, since we can't properly compare string dates.
import pandas as pd # Load sample data df_1 = pd.DataFrame({'Col A': [1,2,3,4,5,6,6,6], 'Anti Col A': [4,5,2,2,1,7,1,3], 'Start Date': ['2021-06-01','2021-06-01','2021-06-01','2021-06-01','2021-06-01','2021-07-01','2021-06-01','2021-06-01'], 'End Date': ['2021-06-02','2021-06-05','2021-06-02','2021-06-05','2021-06-05','2021-07-05','2021-06-05','2021-06-05']}) df_2 = pd.DataFrame({'ID': ['A','A','A','B','B','C','C','C','C'], 'Col B': [1,2,3,1,4,5,6,1,7], 'Start Date': ['2021-06-01','2021-06-02','2021-06-03','2021-06-04','2021-06-05','2021-05-06','2021-06-07','2021-06-08','2021-06-05'], 'End Date': ['2021-06-01','2021-06-02','2021-06-03','2021-06-04','2021-06-05','2021-06-06','2021-06-07','2021-06-08','2021-06-09'], 'Flag_Old': [0,1,0,0,1,0,0,1,1], 'Flag_New': [0,1,0,0,0,0,0,0,1]}) # Convert date columns to datetime df_1[['Start Date', 'End Date']] = df_1[['Start Date', 'End Date']].apply(pd.to_datetime) df_2[['Start Date', 'End Date']] = df_2[['Start Date', 'End Date']].apply(pd.to_datetime)
Step 2: Define Validation Logic
We'll create a function to check each ID group in df_2. The key points are:
- Treat mutual exclusion rules as bidirectional (if A can't coexist with B, B can't coexist with A)
- Only apply rules where the row's date overlaps with the rule's valid date range
- Check if the group contains both values in a valid mutual exclusion pair
def check_mutual_exclusion(group, rule_df): # Get all unique values in the group's Col B for quick lookups col_b_values = set(group['Col B'].unique()) # Convert rules to bidirectional (A <-> B instead of just A -> B) bidirectional_rules = pd.concat([ rule_df[['Col A', 'Anti Col A', 'Start Date', 'End Date']].rename(columns={'Col A': 'Value', 'Anti Col A': 'Mutual_Excl'}), rule_df[['Anti Col A', 'Col A', 'Start Date', 'End Date']].rename(columns={'Anti Col A': 'Value', 'Col A': 'Mutual_Excl'}) ]) # Filter rules that apply to values in the current group relevant_rules = bidirectional_rules[bidirectional_rules['Value'].isin(col_b_values)] # Check each row for violations violation_flags = [] for _, row in group.iterrows(): current_val = row['Col B'] row_start = row['Start Date'] row_end = row['End Date'] # Filter rules for the current value that overlap with the row's date range valid_rules_for_row = relevant_rules[ (relevant_rules['Value'] == current_val) & (relevant_rules['Start Date'] <= row_end) & (relevant_rules['End Date'] >= row_start) ] # Check if any of the mutual exclusion values exist in the group has_violation = any(excl_val in col_b_values for excl_val in valid_rules_for_row['Mutual_Excl']) violation_flags.append(1 if has_violation else 0) group['Error_Flag'] = violation_flags return group
Step 3: Apply Validation to the Dataset
Use groupby to apply the validation function to each ID group in df_2:
# Apply the validation function df_2_with_errors = df_2.groupby('ID').apply(check_mutual_exclusion, rule_df=df_1).reset_index(drop=True) # View the result print(df_2_with_errors[['ID', 'Col B', 'Start Date', 'End Date', 'Flag_New', 'Error_Flag']])
Key Notes on Efficiency
- Using sets for
col_b_valuesensures O(1) lookups, which is critical for large groups - Converting rules to bidirectional avoids missing edge cases where the row's value is the
Anti Col Ain the original rule - For even larger datasets, you can optimize further by replacing the row loop with vectorized operations (using numpy broadcasting for date comparisons)
Example Output
The Error_Flag column will match your expected Flag_New values, correctly ignoring rules outside the date range and only marking rows that are part of a valid, violated mutual exclusion pair.
内容的提问来源于stack exchange,提问作者Dr.Chuck
相关产品推荐
相关产品推荐

