比较数据框中的不同行并删除不需要的行:df.apply 和索引

Comparing different rows inside a data frame and removing unnecessary rows: df.apply and index

我正在比较数据框中不同行的值。如果数据框中的一行与任何其他行匹配至少 75%,我将保留原始行并删除其他行。

原始数据框如下所示:

ID Text
11213 I am going to the cinema
23213 Black is my favourite colour
35455 I am going to the cinema with you
421323 My friends think I am a good guy

所需的输出将是:

ID Text
11213 I am going to the cinema
23213 Black is my favourite colour
421323 My friends think I am a good guy

为此,我使用 df.apply 遍历数据框两次以找出匹配的行。我的计划是获取匹配的行的索引并将其删除。但是,在使用 df.apply 遍历数据框后,索引不匹配,这会产生错误。

到目前为止我已经能够想出这个:

def compare(text):
    match = df.apply(lambda row: (fuzz.partial_ratio(row['text'], text) >= 75), axis=1)
    return [i for i, x in enumerate(matching) if x]


df = pd.read_csv("test.csv", dtype=str, lineterminator='\n')

result = df.apply(lambda row: compare(row['text']).reset_index(), axis=1)
result.to_csv(f'output.csv', index=False) 

这使我能够获得匹配行的索引(尽管由于某种原因索引与原始数据框相差 +2),但我不确定如何继续并删除满足条件的行同时仅保留原始行。

我的目标是保留原始索引并找到更好的方法来删除行['text'] 相似度为 75% 的行。

我建议使用比较 df:

df_compare = pd.DataFrame(
            df['Text'].apply(lambda row: max([fuzz.partial_ratio(row, x), i] 
                            for i, x in enumerate(df['Text']) if x != row)
                        ).to_list(),
                        columns=['ratio', 'closest']
            )

这给你:

   ratio  closest
0    100        2
1     38        0
2    100        0
3     42        2

然后您可以使用 df_compare:

过滤您的初始 df
df[~((df_compare['ratio']>=75) & (df_compare['closest'] < df_compare.index))]

输出:

       ID                              Text
0   11213          I am going to the cinema
1   23213      Black is my favourite colour
3  421323  My friends think I am a good guy

编辑:

计算完整的比较矩阵会得到相同的结果:

df_compare = pd.DataFrame(
            df['Text'].apply(lambda row: [fuzz.partial_ratio(x, row)
                            for x in df['Text']]
                        ).to_list()
            )

for i in df_compare.index:
    for j in df_compare.columns[i:]:
        df_compare.iloc[i,j] = 0

这给出了以下内容:

     0   1   2  3
0    0   0   0  0
1   38   0   0  0
2  100  33   0  0
3   42  36  41  0

你终于可以过滤了:

df[df_compare.max(axis=1)<75]