使用fuzzywuzzy python比较和分组字符串的嵌套循环

如何解决使用fuzzywuzzy python比较和分组字符串的嵌套循环

我正在努力制作一个更快的代码,以便在相同的“person_id”和相同的“TNVED”中对相似的产品名称(列“prep”)进行分组。所以我的数据框示例如下所示: sample_of_dataframe

所以我在 IIN_BIN 上做了字典,这本字典的键是 TNVED。键的值也是字典,键为group_ids,通过与fuzzywuzzy的相似度分组。

from fuzzywuzzy import fuzz
import warnings

warnings.filterwarnings("ignore")

length = len(np.unique(df['IIN_BIN'].to_list()))   
t1 = time.time()
amount = 0
dict_main = {}
df['prep']=df['prep'].fillna("")

for BIN in np.unique(df['IIN_BIN'].to_list()):
    temp_list_BIN = df[df['IIN_BIN'] == BIN]['TNVED']
    dict_pre_main = {}
    
    for tnved in np.unique(temp_list_BIN):
        dict_temp = {}
        j = 0
        df_1_slice = df[df['IIN_BIN'] == BIN]
        df_1_slice = df_1_slice[df['TNVED'] == tnved]
        df_1_slice.reset_index(inplace = True)
        df_1_slice.drop(['index'],axis = 1,inplace = True)

        while len(df_1_slice) != 0:
            temp_list = []
            temp_del_list = []
            temp_fuzz_list = []
            temp_df = pd.DataFrame(columns = df_1_slice.columns)
            
            for i in range(0,len(df_1_slice)):
                fuz_rate = fuzz.token_sort_ratio(
                    df_1_slice['prep'][0],df_1_slice['prep'][i])

                if fuz_rate >=90:
                    temp_del_list.append(i)
                    temp_list.append([0,i,fuz_rate])
                    temp_fuzz_list.append(fuz_rate)
                    temp_df = temp_df.append(df_1_slice.loc[i])
                    dict_temp[j] = temp_df

            df_1_slice.drop(temp_del_list,axis = 0,inplace = True)
            df_1_slice.reset_index(inplace = True)
            df_1_slice.drop('index',inplace = True)
            j+=1

        dict_pre_main[tnved] = dict_temp

    dict_main[BIN] = dict_pre_main
    time_gone = time.time() - t1

    if amount%60 == 0:
        print('Percentage of BINs proceeded: ',amount/length,'%. Time gone from start: ',time_gone,' s.')

    amount+=1

可能有更快的方法来做到这一点,因为那时我不得不将所有这些字典解压缩到一个数据帧中,这花了我大约 1-2 天的时间来处理 200 万行数据帧?

t1 = time.time()
temp_list = list(df.columns)
temp_list.append('group_sorted')
concat_full = pd.DataFrame(columns = temp_list)
length = len(dict_main.keys())    
amount = 0

for key_iin in dict_main.keys():
    for key_tnved in dict_main[key_iin].keys():
        for key_group_number in dict_main[key_iin][key_tnved].keys():
            dict_main[key_iin][key_tnved][key_group_number]['group_sorted'] = key_group_number
            concat_full = concat_full.append(
                dict_main[key_iin][key_tnved][key_group_number])
        
    time_gone = time.time() - t1

    if amount%60 == 0:
        print('Percentage of BINs proceeded: ',' s.')

    amount+=1

concat_full.to_csv('item_desc_fuzzied.csv',index = False)

可能有更快的方法吗?

解决方法

您正在使用 Fuzzywuzzy 并且由于您的抑制警告,我假设您使用的是纯 Python 实现。你应该使用 fuzzywuzzy[speedup] 或者为了更好的性能 RapidFuzz(我是作者)。在 RapidFuzz 中,将模糊字符串匹配转换为:

from fuzzywuzzy import fuzz

for i in range(0,len(df_1_slice)):
    fuz_rate = fuzz.token_sort_ratio(
        df_1_slice['prep'][0],df_1_slice['prep'][i])

    if fuz_rate >=90:
        temp_del_list.append(i)
        temp_list.append([0,i,fuz_rate])
        temp_fuzz_list.append(fuz_rate)
        temp_df = temp_df.append(df_1_slice.loc[i])
        dict_temp[j] = temp_df

类似的东西

from rapidfuzz import process,fuzz

matches = process.extract(
        df_1_slice['prep'][0],df_1_slice['prep'],scorer=fuzz.token_sort_ratio,limit=None,score_cutoff=90)

for choice,score,index in matches:
        temp_del_list.append(index)
        temp_list.append([0,index,score])
        temp_fuzz_list.append(choice)
        temp_df = temp_df.append(df_1_slice.loc[index])
        dict_temp[j] = temp_df

使用process.extract有以下优点:

  • df_1_slice['prep'][0] 只预处理一次
  • 更少的函数调用,因为它可以在 C/C++ 中迭代 DataSeries(Python 中的函数调用很慢)
  • 可以以更多方式预处理查询,例如只对查询中的单词进行一次排序

请注意,此实现尝试使循环后的最终结果保持相似,并且可能只是解决方案的一部分。您对 Pandas 的使用可能会得到改进,但我自己对 Pandas 不是很熟悉。我注意到的一件事是某些变量似乎从未被使用过。这方面的一个例子是 temp_fuzz_list。如果它们真的没有使用,删除它们是有意义的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?