首页 > 解决方案 > 遍历 pandas 数据框中的行并匹配列表字典中的值以创建新列

问题描述

我正在尝试使用字典来模糊匹配熊猫数据框中的列。我的字典是这样的:

{
      "customer name 1": {
         "aliases": [
            "custname1",
            "customer name 1",
            "name 1",
         ]
      },
...
}

目标是使用列表aliases来匹配我的数据框列中的字符串,然后生成一个新列,customer name 1如果它找到匹配项就会有。我的数据框有 26 列,但我唯一使用的是名为Business Name. 不幸的是,我需要读取所有列,因为我需要在最后将所有列输出到一个新的 csv 文件。

我已经生成了一个适用于一小组数据的解决方案,但我发现对于一组更大的数据,它需要的时间比我希望的要长得多。目前这是我正在运行的:

def create_aggregate_names(workbook: str, names: dict, sheet: str) -> None:
    if '.xlsx' in workbook:
        wb = pd.read_excel(workbook, sheet_name=sheet)
    else:
        chunks = pd.read_csv(workbook, sep='|', encoding='latin-1', warn_bad_lines=True, error_bad_lines=False,chunksize=1000000)
    path = Path(workbook).parents[0]
    # Parse through rows to create an aggregate business name
    for chunk in chunks:
        if "Aggregate Business Name" not in chunk.columns:
            chunk["Aggregate Business Name"] = ""
        for index, row in chunk.iterrows():
            aggregate_name = str(row["Business Name"])
            for name in names:
                if any(alias in str(row["Business Name"]).lower() for alias in names[name]["aliases"]):
                    aggregate_name = name
            chunk.at[index, 'Aggregate Business Name'] = str(aggregate_name)
        chunk.to_csv("{}/data.csv".format(path), sep='|', index=False, mode='a')

我可以使用少于 100 万行的 csv 文件完美地运行它。一旦我得到超过 100 万行,脚本似乎永远运行,没有输出。有没有办法用大数据集做到这一点?

标签: pythonpandasdataframe

解决方案


首先,您可以通过删除级别来简化字典aliases

dict_ = {
      "customer name 1": 
          [
            "custname1",
            "customer name 1",
            "name 1",
         ],
    "customer name 2": ['custom name 2']

      }

然后,我们可以使用双列表推导来加快计算速度:

df = pd.DataFrame({'customer_name' : ['custname1', 'custome name 2', "name 1"]})

df['real_name'] = [ [y for y in dict_ if x in dict_[y]][0] 
                     if len([y for y in dict_ if x in dict_[y]])>0 else ''             
                     for x in df['customer_name'] ]

输出 :

    customer_name        real_name
0       custname1  customer name 1
1  custom  name 2  customer name 2
2          name 1  customer name 1

注意:我们在列表推导中计算了[y for y in dict_ if x in dict_[y]两次列表,这很可惜。但这在 python 3.8 中使用海象运算符是可以避免的


推荐阅读