首页 > 解决方案 > 我可以在不必为每条记录运行这些循环的情况下对这些记录进行聚类吗?

问题描述

所以我想对这张表中的记录进行聚类,以找出哪些记录是“相似的”(即有足够的共同点)。该表的示例如下:

        author beginpage endpage volume publication year  id_old  id_new
0          NaN       495     497    NaN             1975       1       1
1          NaN       306     317     14             1997       2       2
2        lowry       265     275    193             1951       3       3
3    smith p k        76      85    150             1985       4       4
4          NaN       248     254    NaN             1976       5       5
5     hamill p        85     100    391             1981       6       6
6          NaN      1513    1523      7             1979       7       7
7     b oregan       737     740    353             1991       8       8
8          NaN       503     517     98             1975       9       9
9      de wijs       503     517     98             1975       10      10

在这个小表中,最后一行的 'new_id' 应该等于 9,以表明这两条记录相似。

为了实现这一点,我编写了下面的代码,它适用于少量记录。但是,我想将我的代码用于包含 15000 条记录的表。当然,如果您进行数学计算,使用此代码将花费太长时间。谁能帮助我使这段代码更有效率?提前致谢!

我的代码,其中“dfhead”是包含记录的表:

for r in range(0,len(dfhead)):
    for o_r in range(r+1,len(dfhead)):
        if ((dfhead.loc[r,c] == dfhead.loc[o_r,c]).sum() >= 3) :
            if (dfhead.loc[o_r,['id_new']] > dfhead.loc[r,['id_new']]).sum() ==1: 
                dfhead.loc[o_r,['id_new']] = dfhead.loc[r,['id_new']]

标签: pythonpandasclustered-index

解决方案


如果您只是想检测“beginpage”、“endpage”、“volume”、“publication”、“year”之间的整体相等性,则应该尝试处理重复项。我不确定这一点,因为您的代码对我来说仍然是一个谜。

这样的事情可能会起作用(尽管您的列“id”首先需要在数据框中命名为“id_old”):

cols = ["beginpage", "endpage","volume", "publication", "year"]

#isolate duplicated rows
duplicated = df[df.duplicated(cols, keep=False)]

#find the minimum key to keep
temp = duplicated.groupby(cols, as_index=False)['index'].min()
temp.rename({'id_old':'id_new'}, inplace=True, axis=1)

#import the "minimum key" to duplicated by merging the dataframes
duplicated = duplicated.merge(temp, on=cols, how="left")

#gather the "un-duplicated" rows
unduplicated = df[~df.duplicated(cols, keep=False)]

#concatenate both datasets and reset the index
new_df = unduplicated.append(duplicated)
new_df.reset_index(drop=True, inplace=True)

#where "id_new" is empty, then the data comes from "unduplicated"
#and you could fill the datas from id_old
ix = new_df[new_df.id_new.isnull()].index
new_df.loc[ix, 'id_new'] = new_df.loc[ix, 'id_old']

推荐阅读