Pandas性能优化:基于同DataFrame其他行条件推导Actual_Price列的高效方案
Efficient Alternative to
apply for Deriving Actual_Price Column in Pandas The apply approach you're using works for small datasets, but it’s inherently slow at scale because it processes rows one by one in Python. Instead, we can leverage vectorized Pandas operations (optimized under the hood with C) to get the same result way faster. Here’s a streamlined, performance-focused solution:
Step-by-Step Implementation
First, let’s align with your requirements to ensure we match the logic exactly:
- For non-
Group_4rows:Actual_Priceis just the row’sPricevalue. - For
Group_4rows: Grab thePricefrom the first matchingGroup_1row with the sameID_2; if no match exists, usepd.NA.
Solution Code
import pandas as pd # Generate the sample DataFrame (as provided) df = pd.DataFrame() df["GroupType"] = ["Group_1","Group_2","Group_3","Group_1","Group_2","Group_3", "Group_1","Group_2","Group_3","Group_1","Group_4","Group_4","Group_4"] df["ID_1"] = ["10","10","10", "10","10","10", "10","10", "10", "12","12","12","13"] df["ID_2"] = [pd.NA,"100",pd.NA, pd.NA,"200",pd.NA, pd.NA,"300",pd.NA, "400","400","400",pd.NA] df["Price"] = [1,2,3,4,5,6,7,8,9,10,11,12,13] # 1. Build a lookup map: ID_2 -> Price for Group_1 rows (keep first occurrence only) group1_id2_price = ( df[df['GroupType'] == 'Group_1'] .drop_duplicates(subset=['ID_2'], keep='first') # Matches your original logic of taking the first match .set_index('ID_2')['Price'] ) # 2. Populate the Actual_Price column df['Actual_Price'] = df['Price'] # Default to Price for non-Group_4 rows # For Group_4 rows, map ID_2 to the corresponding Group_1 Price (pd.NA if no match) df.loc[df['GroupType'] == 'Group_4', 'Actual_Price'] = df.loc[df['GroupType'] == 'Group_4', 'ID_2'].map(group1_id2_price) print(df)
Why This Is Way Faster
- Vectorized operations:
drop_duplicates,set_index, andmapall operate on entire columns/Series at once, avoiding the overhead of Python-level row-by-row loops. - Single lookup table: We build the
Group_1ID-to-Price map once, instead of querying the entire DataFrame for everyGroup_4row (which is what yourapplyfunction does repeatedly).
Verification
Running this code produces exactly the expected output you shared:
- Rows 0-9 (non-Group_4) have
Actual_Priceequal to theirPrice. - Rows 10-11 (Group_4 with ID_2=400) pull the Price from row 9 (Group_1, ID_2=400), so
Actual_Price=10. - Row 12 (Group_4 with ID_2=pd.NA) has no matching Group_1 row, so
Actual_Price=pd.NA.
内容的提问来源于stack exchange,提问作者Puneeth R
相关产品推荐
相关产品推荐

