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

如何在Pandas中按站点过滤并映射多列数据?

按站点规则映射DataFrame列数据并避免SettingWithCopyWarning

问题背景

有如下简化后的DataFrame:

Site     LocationName    Resource#    
   01        Test Name            5
   01          Testing            6
   02       California           10
   02            Texas           11
   ...

每个站点对应独立的LocationName和Resource#映射规则:

  • 站点01的映射规则:
    • LocationName: {'Test Name': 'Another Test', 'Testing': 'RandomLocation'}
    • Resource#: {5: 5000}
  • 站点02的映射规则:
    • LocationName: {'California': 'CA-123'}
    • Resource#: {10: '10A', 11: '11B'}

需要按站点规则映射列数据,无映射项设为None/空值,期望输出:

Site#     LocationName    Resource#    
   01     Another Test         5000
   01   RandomLocation
   02           CA-123          10A
   02                           11B

原思路是过滤站点后对Series执行map,但触发SettingWithCopyWarning:

df01 = df[df.Site == '01']
df01 = df['LocationName'].map({'Test Name': 'Another Test', 'Testing': 'RandomLocation'})

解决方案

1. 嵌套字典+apply(推荐)

先把所有站点的映射规则整理成嵌套字典,针对每行数据根据站点匹配对应映射:

import pandas as pd

# 定义全局映射规则
site_mappings = {
    '01': {
        'LocationName': {'Test Name': 'Another Test', 'Testing': 'RandomLocation'},
        'Resource#': {5: 5000}
    },
    '02': {
        'LocationName': {'California': 'CA-123'},
        'Resource#': {10: '10A', 11: '11B'}
    }
}

# 映射LocationName列
df['LocationName'] = df.apply(
    lambda row: site_mappings[row['Site']]['LocationName'].get(row['LocationName'], None),
    axis=1
)
# 映射Resource#列
df['Resource#'] = df.apply(
    lambda row: site_mappings[row['Site']]['Resource#'].get(row['Resource#'], None),
    axis=1
)

这种方式直接在原DataFrame上修改,不会触发副本警告,规则集中管理,新增站点只需扩展字典即可。

2. groupby分组映射

通过groupby按站点分组后,给每组应用对应映射逻辑,最后合并结果:

def process_site(group):
    site = group.name
    group['LocationName'] = group['LocationName'].map(site_mappings[site]['LocationName']).fillna(None)
    group['Resource#'] = group['Resource#'].map(site_mappings[site]['Resource#']).fillna(None)
    return group

df = df.groupby('Site').apply(process_site).reset_index(drop=True)

如果不同站点的映射逻辑差异极大,可以把process_site拆分成对应站点的单独函数,灵活性更高。

3. 优化原过滤思路

如果坚持用过滤站点的方式,可通过两种方法避免警告:

显式创建副本

df01 = df[df.Site == '01'].copy()
df01['LocationName'] = df01['LocationName'].map(site_mappings['01']['LocationName']).fillna(None)
df01['Resource#'] = df01['Resource#'].map(site_mappings['01']['Resource#']).fillna(None)

df02 = df[df.Site == '02'].copy()
df02['LocationName'] = df02['LocationName'].map(site_mappings['02']['LocationName']).fillna(None)
df02['Resource#'] = df02['Resource#'].map(site_mappings['02']['Resource#']).fillna(None)

df = pd.concat([df01, df02])

用.loc直接修改原DataFrame

# 处理站点01
mask_01 = df.Site == '01'
df.loc[mask_01, 'LocationName'] = df.loc[mask_01, 'LocationName'].map(site_mappings['01']['LocationName']).fillna(None)
df.loc[mask_01, 'Resource#'] = df.loc[mask_01, 'Resource#'].map(site_mappings['01']['Resource#']).fillna(None)

# 处理站点02
mask_02 = df.Site == '02'
df.loc[mask_02, 'LocationName'] = df.loc[mask_02, 'LocationName'].map(site_mappings['02']['LocationName']).fillna(None)
df.loc[mask_02, 'Resource#'] = df.loc[mask_02, 'Resource#'].map(site_mappings['02']['Resource#']).fillna(None)

这种写法直接操作原DataFrame的指定行,从根源避免SettingWithCopyWarning。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 04:08:09