You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过前缀匹配两个DataFrame为df1新增marker列?

解决Pandas中前缀匹配新增列的问题(替代嵌套循环)

Hey there! Let's ditch those messy nested loops and solve this problem the pandas way—efficiently and cleanly.

First, let's recap what you need: add a marker column to df1 by matching the prefix of BSI values with initial values from df2, then pull the corresponding marker for cartopy styling.

Step 1: Setup Your Sample Data

First, let's define the sample DataFrames properly in code:

import pandas as pd

# Sample df1
df1 = pd.DataFrame({
    'BSI': ['AA-010', 'AA-030', 'AA-180', 'AA-200', 'AA-220'],
    'Shelter_Number': ['1085', '3690', '279', '2018', '3301'],
    'Location': [
        'SUSSEX (N SIDE) & RIDEAU FALLS',
        'SUSSEX (E SIDE) & ALEXANDER NS',
        'CRICHTON (E SIDE) & BEECHWOOD FS',
        'BEECHWOOD (S SIDE) & CHARLEVOIX NS',
        'BEECHWOOD (S SIDE) & MAISONNEUVE NS'
    ],
    'Latitude': [45.439571, 45.442795, 45.439556, 45.441154, 45.442188],
    'Longitude': [-75.695694, -75.692322, -75.676849, -75.673622, -75.671356]
})

# Sample df2
df2 = pd.DataFrame({
    'initial': ['AA', 'AB', 'AC', 'AD', 'AE'],
    'marker': ['bo', 'bv', 'b^', 'b<', 'b>']
})

Step 2: Efficient Solutions (No Nested Loops!)

Nested loops are slow, error-prone, and not how pandas is designed to work. Here are two better approaches:

Approach 1: Dictionary Mapping + apply

First, convert df2 into a lookup dictionary for fast access, then use apply to check each BSI value:

# Create a lookup dict: initial -> marker
marker_lookup = df2.set_index('initial')['marker'].to_dict()

# Function to find matching marker
def get_marker(bsi_value):
    for prefix in marker_lookup.keys():
        if bsi_value.startswith(prefix):
            return marker_lookup[prefix]
    return None  # Return None if no match found

# Add the marker column to df1
df1['marker'] = df1['BSI'].apply(get_marker)

Approach 2: Vectorized Extraction + Merge (Even Faster!)

If your initial values follow a consistent pattern (like 2 uppercase letters at the start of BSI), use string extraction and merge—this is the fastest method for large datasets:

# Extract the prefix from BSI (adjust regex if your prefixes vary in length)
df1['initial'] = df1['BSI'].str.extract(r'^([A-Z]{2})')

# Merge with df2 to get the marker, then clean up
df1 = df1.merge(df2, on='initial', how='left').drop('initial', axis=1)

Step 3: Result

Either method will give you the desired output:

BSI Shelter_Number                                      Location   Latitude  Longitude marker
0  AA-010           1085              SUSSEX (N SIDE) & RIDEAU FALLS  45.439571  -75.695694     bo
1  AA-030           3690            SUSSEX (E SIDE) & ALEXANDER NS  45.442795  -75.692322     bo
2  AA-180            279           CRICHTON (E SIDE) & BEECHWOOD FS  45.439556  -75.676849     bo
3  AA-200           2018        BEECHWOOD (S SIDE) & CHARLEVOIX NS  45.441154  -75.673622     bo
4  AA-220           3301       BEECHWOOD (S SIDE) & MAISONNEUVE NS  45.442188  -75.671356     bo

Why Your Nested Loop Failed

Most likely, you ran into scope issues or were trying to modify df1 rows directly during iteration (which doesn't work because iterrows() returns copies, not references). Nested loops also perform terribly with large datasets—these pandas-native methods are way more efficient.

内容的提问来源于stack exchange,提问作者jiwanheo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:36:51