如何使用文本相似性删除pandas dataframe中的相似(不重复)行?

hivapdat  于 2023-09-29  发布在  其他
关注(0)|答案(1)|浏览(66)

我有成千上万的数据,它们可能彼此相似,也可能不相似。使用python的默认函数drop_duplicates()并没有真正的帮助,因为它们只检测类似的数据,例如,如果我的数据包含这样的东西:
1.早上好!
1.早上好啊
Python不会将它们检测为重复。有很多变化,这真的,简单地清理文本是不够的,所以我选择文本相似性。
我尝试了以下代码:

import textdistance
from tqdm import tqdm 
tqdm.pandas()

all_sims = []

for id1, text1 in tqdm(enumerate(df1['cleaned'])):
    for id2, text2 in enumerate(df1['cleaned'].iloc[id1:]):
        if id1==id2:
            continue
        sim = textdistance.jaro_winkler(text1, text2)
        if sim>=0.9:
#             print("similarity value: ",sim)
#             print("text 1 >> ",text1)
#             print("text 2 >> ",text2)
#             print("====><====")
            all_sims.append(id1)

基本上,我试着把列中的所有行都检查一遍,然后自己检查。如果检测到的jaro-winkler值>= 0.9,则索引将被保存到列表中。
然后,我将使用以下代码删除所有这些类似的索引。

df1[~df1.index.isin(all_sims)]

但是我的代码真的很慢,效率很低,我不确定这是否是正确的方法。你有什么想法来改善这一点吗?

mnemlml8

mnemlml81#

你可以试试这个:

import pandas as pd
import textdistance

# Toy dataframe
df = pd.DataFrame(
    {
        "name": [
            "Mulligan Nick",
            "Hitt S C",
            "Breda Joy Mulligen",
            "David James Tsan",
            "Mulligan Nick",
            "Htti S C ",
            "Brenda Joy Mulligan",
            "Dave James Tsan",
        ],
    }
)

# Calculate similarities between rows
# and save corresponding indexes in a new column "match"
df["match"] = df["name"].map(
    lambda x: [
        i
        for i, text in enumerate(df["name"])
        if textdistance.jaro_winkler(x, text) >= 0.9
    ]
)

# Iterate to remove similar rows (keeping only the first one)
indices = []
for i, row in df.iterrows():
    indices.append(i)
    df = df.drop(
        index=[item for item in row["match"] if item not in indices], errors="ignore"
    )

# Clean up
df = df.drop(columns="match")

print(df)
# Outputs
                 name
0       Mulligan Nick
1            Hitt S C
2  Breda Joy Mulligen
3    David James Tsan

相关问题