如何基于可变多列条件为Pandas DataFrame批量添加标签?
Got it, let's finish your labeling function! The key piece you're missing is combining multiple boolean conditions with logical AND (&) and using Pandas' .loc indexer to safely assign labels without warnings. Here's a step-by-step breakdown:
Step 1: Initialize the Label Column
First, add a label column to your DataFrame with a default value (like 0 for rows that don't match any condition).
Step 2: Combine Conditions with Logical AND
For each condition dictionary, you need to merge all column-value checks into a single boolean mask. We'll use functools.reduce to chain the & operator across all your conditions, ensuring only rows that meet all criteria get the label.
Step 3: Assign Labels Safely with .loc
Use .loc to target rows matching the combined condition and set their label value. This avoids the common SettingWithCopyWarning that pops up with direct boolean indexing.
Complete Function Code
import pandas as pd from functools import reduce def labeling(df, crit): # Initialize label column with default 0 for non-matching rows df['label'] = 0 for dic in crit: # Extract the target label and make a copy of the condition dict to avoid modifying the original lbl = dic["label"] cond_dict = dic.copy() del cond_dict["label"] # Create a list of boolean conditions for each key-value pair conds = [df[key] == cond_dict[key] for key in cond_dict] # Combine all conditions using logical AND combined_condition = reduce(lambda x, y: x & y, conds) # Assign the label to rows that meet all conditions df.loc[combined_condition, 'label'] = lbl return df
Testing with Your Example
Let's verify this works with your sample data and conditions:
Sample Input DataFrame
data = { 'ip_src': ['192.168.84.129', '31.13.94.53', '192.168.1.101'], 'ip_dst': ['192.168.84.128', '192.168.1.101', '31.13.94.53'], 'ip_proto': [17.0, 17.0, 17.0], 'frame_time_delta': [0.000000, 0.006656, 0.012948], 'payload_size': [172.0, 176.0, 172.0], 'src_port': [52165.0, 40002.0, 52165.0], 'dst_port': [40002.0, 52165.0, 19305.0], 'flow_dir': [1, 0, 1] } df = pd.DataFrame(data)
Conditions List
l_crit = [ {"ip_src": "192.168.84.129", "ip_dst": "192.168.84.128", "label": 1}, {"ip_src": "192.168.1.100", "ip_dst": "192.168.1.105", "dst_port": 9999, "label": 1}, {"ip_src": "192.168.1.101", "ip_dst": "104.44.195.76", "label": 2}, {"ip_src": "192.168.1.101", "ip_dst": "31.13.94.53", "ip_proto": 17, "label": 3}, {"ip_src": "192.168.1.101", "dst_port": 19305, "label": 4} ]
Run the Function
labeled_df = labeling(df, l_crit) print(labeled_df)
Output (Matches Your Expected Result)
ip_src ip_dst ip_proto frame_time_delta payload_size src_port dst_port flow_dir label 0 192.168.84.129 192.168.84.128 17.0 0.000000 172.0 52165.0 40002.0 1 1 1 31.13.94.53 192.168.1.101 17.0 0.006656 176.0 40002.0 52165.0 0 0 2 192.168.1.101 31.13.94.53 17.0 0.012948 172.0 52165.0 19305.0 1 4
Key Notes
- We use
dic.copy()to preserve your original condition dictionaries (so you can reuse them later if needed). reduce(lambda x, y: x & y, conds)ensures only rows that satisfy every condition in the dictionary get the label..locguarantees we're modifying the original DataFrame safely, avoiding common Pandas warnings.
内容的提问来源于stack exchange,提问作者sooaran

