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

Python Pandas:DataFrame多字符串映射仅单个生效的问题排查

问题原因分析

你遇到的核心问题是**fln()、lpg()、hwl()这三个函数会互相覆盖对方的修改结果**,而且完全没有做条件判断——不管当前行的序列号符合哪个规则,只要调用了这些函数,就会强制用对应位置的切片去执行映射,不匹配的行直接变成NaN,最后执行的那个函数会覆盖之前所有对New Meter Model和New Meter Manufacturer的修改。

举个直观的例子:

  • 如果先调用fln(),它会用序列号最后8位匹配规则,给符合条件的行赋值;
  • 接着调用lpg(),它会用序列号最后2位匹配,这时候哪怕之前fln()已经赋值过的行,只要最后两位不是2061,就会被改成NaN;
  • 最后调用hwl()的话,同理,只有最后两位是1914的行会被赋值,其他行(包括之前被fln或lpg处理过的)都会被覆盖成NaN。

这就是为什么你看到有时候只有某一个映射生效——本质上取决于你最后执行的是哪个函数,或者刚好哪部分数据匹配了最后那个函数的规则。

另外注意:原代码里lpg()和hwl()用str[-2:]去匹配"2061"和"1914"明显有问题,最后2位只能是两位字符,不可能匹配4位的字符串,这大概率是你写代码时的笔误,后面的修复方案会默认调整为合理的切片长度(比如取最后4位),你可以根据实际序列号规则再修改。

修复方案

你需要把这三个函数的逻辑合并,根据序列号的特征做条件判断,只对符合规则的行应用对应的映射,避免互相覆盖。这里提供两种可行的方式:

方式1:使用loc+掩码做精准赋值(推荐,效率更高)

这种方式适合规则明确的场景,处理大数据集时性能更好:

import numpy as np

def map_meter_info():
    # 处理FLN规则:序列号最后8位匹配指定值
    fln_mask = gas_data["New Serial Number"].str[-8:].isin(["2000", "2100", "1800", "1900"])
    gas_data.loc[fln_mask, "New Meter Model"] = gas_data.loc[fln_mask, "New Serial Number"].str[-8:].map({
        "2000": "G4SZV-2", "2100": "G4SZV-2", "1800": "G4SZV-1", "1900": "G4SZV-1"
    })
    gas_data.loc[fln_mask, "New Meter Manufacturer"] = "FLN"

    # 处理LPG规则:序列号最后4位为2061
    lpg_mask = gas_data["New Serial Number"].str[-4:] == "2061"
    gas_data.loc[lpg_mask, "New Meter Model"] = "G470"
    gas_data.loc[lpg_mask, "New Meter Manufacturer"] = "LPG"

    # 处理HWL规则:序列号最后4位为1914
    hwl_mask = gas_data["New Serial Number"].str[-4:] == "1914"
    gas_data.loc[hwl_mask, "New Meter Model"] = "BK-G4E"
    gas_data.loc[hwl_mask, "New Meter Manufacturer"] = "HWL"
    
    logging.info('Updated meter manufacturer codes and meter models based on serial number rules')

方式2:使用apply逐行判断(适合复杂规则)

如果你的序列号规则有更多特殊情况,逐行处理会更灵活:

def get_meter_details(row):
    serial = row["New Serial Number"]
    # 先检查FLN规则
    last8 = serial[-8:] if len(serial) >= 8 else ""
    if last8 in ["2000", "2100", "1800", "1900"]:
        model_map = {"2000": "G4SZV-2", "2100": "G4SZV-2", "1800": "G4SZV-1", "1900": "G4SZV-1"}
        return pd.Series([model_map[last8], "FLN"])
    # 再检查LPG规则
    last4 = serial[-4:] if len(serial) >= 4 else ""
    if last4 == "2061":
        return pd.Series(["G470", "LPG"])
    # 最后检查HWL规则
    if last4 == "1914":
        return pd.Series(["BK-G4E", "HWL"])
    # 都不匹配则保留原有值(或设置默认值)
    return pd.Series([row["New Meter Model"], row["New Meter Manufacturer"]])

def map_meter_info():
    gas_data[["New Meter Model", "New Meter Manufacturer"]] = gas_data.apply(get_meter_details, axis=1)
    logging.info('Updated meter manufacturer codes and meter models based on serial number rules')
额外注意事项
  1. 主逻辑里只需要调用合并后的map_meter_info()函数,不要再单独调用原来的fln()、lpg()、hwl()了;
  2. 原代码中add_location()已经对New Meter Model做过一次映射,记得确认执行顺序:如果add_location()的映射是优先级更低的默认值,应该先执行add_location(),再执行map_meter_info(),这样序列号匹配的行会覆盖默认值;
  3. 处理前可以先检查New Serial Number列的格式,比如有没有空值、长度不足的情况,避免切片报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 23:29:10