在Python中用字典键(具有多个值)替换文本更高效

2024-05-19 20:27:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我一直试图用基于多个值的字典中的键替换Pandas dataframe列中的部分文本;虽然我已经达到了预期的结果,但在大型数据集中,过程或循环非常缓慢。如果有人能给我建议一种更“Pythonic”的方法或更有效的方法来实现这个结果,我将不胜感激。请看下面的例子:

df =  pd.DataFrame({'Dish':  ['A', 'B','C'],
        'Price': [15,8,20],
         'Ingredient': ['apple banana apricot lamb ', 'wheat pork venison', 'orange lamb guinea']
        })
^{tb1}$

字典如下:

CountryList = {'FRUIT': [['apple'], ['orange'],  ['banana']],
 'CEREAL': [['oat'], ['wheat'],  ['corn']],
 'MEAT': [['chicken'],  ['lamb'],  ['pork'],  ['turkey'], ['duck']]}

我试图用基于字典值的键替换“成分”列中的文本。例如,第一行的“苹果”将替换为字典键:“水果”。。所需表格如下所示:

^{tb2}$

我在这里看到了一些相关的查询,其中每个键都有一个值;但在这种情况下,字典中的任何给定键都有多个值。到目前为止,我已经能够达到预期的结果,但在处理大型数据集时速度非常慢。 到目前为止,我用于实现此结果的代码如下所示:

countries = list(CountryList.keys())

for country in countries:
    for i in range(len(CountryList[country])):
        lender = CountryList[country][i]
        country = str(country)
        lender = str(lender).replace("['",'',).replace("']",'')
        df['Ingredient'] = df['Ingredient'].str.replace(lender,country)

也许这与多重处理有关?不用说,我的Python知识还有很多需要改进的地方

任何加快这一进程的建议都将不胜感激

提前感谢,

编辑:只需添加,一些键在字典中的值超过60000;字典中大约有200个键,这使得代码在时间上非常低效


Tags: 数据方法文本appledf字典country建议
3条回答

如果您想使用正则表达式,只需为每个键连接CountryListby pipe |中的所有值,然后为每个键调用^{},这将比您尝试的方式快得多

joined={key: '|'.join(item[0] for item in value) for key,value in CountryList.items()}

for key in joined:
    df['Ingredient'] = df['Ingredient'].str.replace(joined[key], key, regex=True)

输出

  Dish  Price                 Ingredient
0    A     15  FRUIT FRUIT apricot MEAT 
1    B      8        CEREAL MEAT venison
2    C     20          FRUIT MEAT guinea

另一种方法是反转字典中的键和值,然后对每个key使用dict.get,默认值为key,拆分Ingredient列中的单词:

reversedContries={item[0]:key for key,value in CountryList.items() for item in value}

df['Ingredient'].apply(lambda x: ' '.join(reversedContries.get(y,y) for y in x.split()))

更改CountryList的格式:

import itertools

CountryList2 = {}
for k, v in CountryList.items():
    for i in (itertools.chain.from_iterable(v)):
        CountryList2[i] = k
>>> CountryList2
{'apple': 'FRUIT',
 'orange': 'FRUIT',
 'banana': 'FRUIT',
 'oat': 'CEREAL',
 'wheat': 'CEREAL',
 'corn': 'CEREAL',
 'chicken': 'MEAT',
 'lamb': 'MEAT',
 'pork': 'MEAT',
 'turkey': 'MEAT',
 'duck': 'MEAT'}

现在您可以使用replace

df['Ingredient'] = df['Ingredient'].replace(CountryList2, regex=True)
>>> df
  Dish  Price                 Ingredient
0    A     15   FRUIT FRUIT apricot MEAT
1    B      8        CEREAL MEAT venison
2    C     20          FRUIT MEAT guinea

通过创建一个字典,其中键是子列表的值,您可以构建product to type的反向索引

product_to_type = {}
for typ, product_lists in CountryList.items():
    for product_list in product_lists:
        for product in product_list:
            product_to_type[product] = typ

一个小小的python魔术可以让您将此步骤压缩到一个生成器中,该生成器创建dict

product_to_type = {product:typ for typ, product_lists in CountryList.items()
   for product_list in product_lists for product in product_list}

然后,您可以创建一个函数来拆分成分并将其映射到类型,并将其应用到数据帧

import pandas as pd

CountryList = {'FRUIT': [['apple'], ['orange'],  ['banana']],
 'CEREAL': [['oat'], ['wheat'],  ['corn']],
 'MEAT': [['chicken'],  ['lamb'],  ['pork'],  ['turkey'], ['duck']]}

product_to_type = {product:typ for typ, product_lists in CountryList.items()
   for product_list in product_lists for product in product_list}

def convert_product_to_type(products):
    return " ".join(product_to_type.get(product, product) 
        for product in products.split(" "))
    
df =  pd.DataFrame({'Dish':  ['A', 'B','C'],
        'Price': [15,8,20],
         'Ingredient': ['apple banana apricot lamb ', 'wheat pork venison', 'orange lamb guinea']
        })

df["Ingredient"] = df["Ingredient"].apply(convert_product_to_type)

print(df)

注意:此解决方案在单词边界上拆分成分列表,假设成分本身没有空格

相关问题 更多 >