比较数据框中的不同行并删除不需要的行: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]
我正在比较数据框中不同行的值。如果数据框中的一行与任何其他行匹配至少 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_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]