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

基于通配符在Pandas DataFrame中匹配字典值的最优方案问询

嘿,我来帮你搞定这个通配符匹配的需求!你已经实现了全词匹配,但要做带优先级的通配符/子串匹配并取首个结果,这里有几个高效的方案,比你现在用的iterrows要靠谱多~

通配符匹配字典值并取首个结果的最优实现方案

核心思路

你需要的是按优先级匹配:按照字典的顺序,找到第一个符合通配符/子串条件的键,返回对应的分类值。关键是要保证匹配的顺序,同时提升处理效率(毕竟iterrows在大数据量下很慢)。

方案1:简单子串匹配(最易维护)

如果你的需求只是“描述中包含字典键的内容”,直接用字符串包含判断就可以,代码简洁又高效:

import pandas as pd

df = pd.read_csv("transactions.csv")
# 注意:Python 3.7+的字典会保留插入顺序,所以这里的顺序就是匹配优先级!先写的会先被匹配
category_mapping = {
    'SUBWAY': '9',
    'TRANSFER TO': '5',
    'Best Buy': '8'
}

def get_first_match(description):
    # 按顺序遍历字典,找到第一个匹配的就返回
    for keyword, category in category_mapping.items():
        if keyword in description:
            return category
    # 没有匹配到的话返回空值(也可以改成你需要的默认值)
    return pd.NA

# 用apply批量处理,比iterrows效率高N倍
df['Category'] = df['Description'].apply(get_first_match)

方案2:支持标准通配符(*、?)

如果你的匹配规则需要用*(匹配任意字符)、?(匹配单个字符)这类通配符,就用fnmatch模块,用法和上面差不多:

import pandas as pd
import fnmatch

df = pd.read_csv("transactions.csv")
# 这里可以写带通配符的规则,比如"*SUBWAY*"匹配任何包含SUBWAY的描述
category_mapping = {
    '*SUBWAY*': '9',
    '*TRANSFER TO*': '5',
    '*Best Buy*': '8'
}

def get_wildcard_match(description):
    for pattern, category in category_mapping.items():
        if fnmatch.fnmatch(description, pattern):
            return category
    return pd.NA

df['Category'] = df['Description'].apply(get_wildcard_match)

方案3:大数据量优化(正则预编译)

如果你的交易数据量特别大,用正则预编译可以进一步提升匹配速度,尤其是当关键词很多的时候:

import pandas as pd
import re

df = pd.read_csv("transactions.csv")
category_mapping = {
    'SUBWAY': '9',
    'TRANSFER TO': '5',
    'Best Buy': '8'
}

# 预编译所有关键词的正则表达式,避免重复编译浪费时间
compiled_patterns = [(re.compile(re.escape(keyword)), category) for keyword, category in category_mapping.items()]

def get_regex_match(description):
    for pattern, category in compiled_patterns:
        # search方法会检查描述中是否包含该关键词
        if pattern.search(description):
            return category
    return pd.NA

df['Category'] = df['Description'].apply(get_regex_match)

额外优化:忽略大小写匹配

如果你的交易描述大小写不固定(比如有时是"subway"有时是"SUBWAY"),可以在匹配时统一转成小写:

def get_case_insensitive_match(description):
    desc_lower = description.lower()
    for keyword, category in category_mapping.items():
        if keyword.lower() in desc_lower:
            return category
    return pd.NA

为什么这比你现在的方法好?

你原来用iterrows遍历每一行的方式,在数据量小的时候没问题,但数据量大时会非常慢。用apply结合遍历字典的方式,不仅代码更简洁,效率也能提升一个量级,同时还能轻松实现优先级匹配(首个匹配即返回)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:39:14