【问题标题】:Fuzzy Searching a Column in Pandas在 Pandas 中模糊搜索列
【发布时间】:2021-01-16 09:50:12
【问题描述】:

有没有办法使用FuzzyWuzzy 或类似库在数据框列中搜索值? 我试图在一个列中找到一个与另一列中的值相对应的值,同时考虑到模糊匹配。所以

例如,如果我在一列中有 州名,而在另一列中有 州代码,我将如何找到佛罗里达州的州代码,即 FL 同时提供餐饮服务像“Flor”这样的缩写?

也就是说,我想找到与“Flor”对应的州名的匹配项,并获得相应的州代码“FL”。

非常感谢任何帮助。

【问题讨论】:

    标签: python pandas string-matching fuzzy-search fuzzy-comparison


    【解决方案1】:

    如果缩写都是前缀,您可以使用.startswith() 字符串方法来处理状态的短版本或长版本。

    >>> test_value = "Flor"
    >>> test_value.upper().startswith("FL")
    True
    >>> "Florida".lower().startswith(test_value.lower())
    True
    

    但是,如果您有更复杂的缩写,difflib.get_close_matches 可能会满足您的需求!

    >>> import pandas as pd
    >>> import difflib
    >>> df = pd.DataFrame({"states": ("Florida", "Texas"), "st": ("FL", "TX")})
    >>> df
        states  st
    0  Florida  FL
    1    Texas  TX
    >>> difflib.get_close_matches("Flor", df["states"].to_list())
    ['Florida']
    >>> difflib.get_close_matches("x", df["states"].to_list(), cutoff=0.2)
    ['Texas']
    >>> df["st"][df.index[df["states"]=="Texas"]].iloc[0]
    'TX'
    

    您可能想尝试/排除IndexError 从 difflib 读取返回列表的第一个成员,并可能调整截止以减少与关闭状态的错误匹配(也许提供所有状态作为 可能性 给某些用户或需要更多字母来表示关闭状态)。

    您还可能会看到将两者结合起来的最佳结果;在尝试模糊匹配之前先测试前缀。

    把它们放在一起

    def state_from_partial(test_text, df, col_fullnames, col_shortnames):
        if len(test_text) < 2:
            raise ValueError("must have at least 2 characters")
    
        # if there's exactly two characters, try to directly match short name
        if len(test_text) == 2 and test_text.upper() in df[col_shortnames]:
            return test_text.upper()
    
        states = df[col_fullnames].to_list()
        match = None
        # this will definitely fail at least for states starting with M or New
        #for state in states:
        #    if state.lower().startswith(test_text.lower())
        #        match = state
        #        break  # leave loop and prepare to find the prefix
    
        if not match:
            try:  # see if there's a fuzzy match
                match = difflib.get_close_matches(test_text, states)[0]  # cutoff=0.6
            except IndexError:
                pass  # consider matching against a list of problematic states with different cutoff
    
        if match:
            return df[col_shortnames][df.index[df[col_fullnames]==match]].iloc[0]
    
        raise ValueError("couldn't find a state matching partial: {}".format(test_text))
    

    注意以“New”或“M”(可能还有其他)开头的状态,它们都非常接近并且可能需要特殊处理。测试将在这里创造奇迹。

    【讨论】:

      猜你喜欢
      • 2021-03-08
      • 2013-02-18
      • 1970-01-01
      • 1970-01-01
      • 2020-03-15
      • 2014-08-20
      • 2011-10-28
      • 2016-06-12
      • 2017-06-09
      相关资源
      最近更新 更多