比较csv的两列并在另一个csv中输出字符串相似度
Comparing two columns of a csv and outputting string similarity ratio in another csv
我对 python 编程还很陌生。我正在尝试获取一个包含两列字符串值的 csv 文件,并想比较两列之间字符串的相似率。然后我想获取值并在另一个文件中输出比率。
csv 可能如下所示:
Column 1|Column 2
tomato|tomatoe
potato|potatao
apple|appel
我希望输出文件显示每一行,第 1 列中的字符串与第 2 列中的字符串有多相似。我正在使用 difflib 输出比率得分。
这是我目前的代码:
import csv
import difflib
f = open('test.csv')
csf_f = csv.reader(f)
row_a = []
row_b = []
for row in csf_f:
row_a.append(row[0])
row_b.append(row[1])
a = row_a
b = row_b
def similar(a, b):
return difflib.SequenceMatcher(a, b).ratio()
match_ratio = similar(a, b)
match_list = []
for row in match_ratio:
match_list.append(row)
with open("output.csv", "wb") as f:
writer = csv.writer(f, delimiter=',')
writer.writerows(match_list)
f.close()
我收到错误:
Traceback (most recent call last):
File "comparison.py", line 24, in <module>
for row in match_ratio:
TypeError: 'float' object is not iterable
我觉得我没有正确导入列列表并且 运行 它与 sequencematcher 函数不符。
您在此处设置的 for
循环期望您拥有 match_ratio
的数组之类的东西,并且根据您收到的错误判断,这不是您拥有的。看起来您缺少 difflib.SequenceMatcher
的第一个参数,它可能应该是 None
。请参阅此处的 6.3.1:https://docs.python.org/3/library/difflib.html
如果没有指定第一个参数,我认为您正在从 difflib.SequenceMatcher
返回 0.0
,然后尝试 运行 ratio
。即使您更正了 SequenceMatcher
调用,我认为您仍然会尝试迭代 ratio
返回的单个浮点值。我认为您需要在循环内为要比较的每组值调用 SequenceMatcher
。
所以你会在你的函数中得到一个更像这样的调用:difflib.SequenceMatcher(None, a, b)
。或者,如果您愿意,因为这些是命名参数,您可以这样做:difflib.SequenceMatcher(a=a, b=b)
.
您收到错误消息是因为您在字符串列表上 运行 SequenceMatcher,而不是在字符串本身上。当你这样做时,你会得到一个单一的浮点值,而不是我认为你期望的口粮值列表。
如果我明白你想做什么,那么你就不需要先阅读这些行。您可以在遍历行时简单地找到差异比率。
import csv
import difflib
match_list = []
with open('test.csv') as f:
csv_f = csv.reader(f)
for row in csv_f:
match_list.append([difflib.SequenceMatcher(a=row[0], b=row[1]).ratio()])
with open('output.csv', 'w') as f:
writer = csv.writer(f, delimiter=',')
writer.writerows(match_list)
您的示例文件似乎包含标记。假设您实际上正在读取 CSV 文件,您得到的错误是因为 match_ratio 不是可迭代的数据类型,它是一个浮点数——函数的 return 值:similar()。在您的代码中,函数调用必须包含在 for 循环中才能为每个 a、b 字符串对调用它。这是我创建的一个工作示例,它取消了显式 for 循环,而是使用列表理解:
import csv
from difflib import SequenceMatcher
path_in = 'csv1.csv'
path_out = 'csv2.csv'
with open(path_in, 'r') as csv_file_in:
csv_reader = csv.reader(csv_file_in)
col_headers = csv_reader.next()
for row in csv_reader:
results = [[row[0],
row[1],
SequenceMatcher(None, row[0], row[1]).ratio()]
for row in csv_reader]
with open(path_out, 'wb') as csv_file_out:
col_headers.append('Ratio')
out_rows = [col_headers] + results
writer = csv.writer(csv_file_out, delimiter=',')
writer.writerows(out_rows)
除了您收到的错误之外,您在实例化 SequenceMatcher 对象时可能还会 运行 遇到问题 -- 它的第一个参数未在您的代码中指定。您可以在 Python 文档中找到有关 list comprehensions and SequenceMatcher 的更多信息。祝你 Python 编码好运。
这是使用 pandas
完成此操作的另一种方法:
Consider your csv data is like this:
Column 1,Column 2
tomato,tomatoe
potato,potatao
apple,appel
CODE
import pandas as pd
import difflib as diff
#Read the CSV
df = pd.read_csv('datac.csv')
#Create a new column 'diff' and get the result of comparision to it
df['diff'] = df.apply(lambda x: diff.SequenceMatcher(None, x[0].strip(), x[1].strip()).ratio(), axis=1)
#Save the dataframe to CSV and you could also save it in other formats like excel, html etc
df.to_csv('outdata.csv',index=False)
Result
Column 1,Column 2 ,diff
tomato,tomatoe ,0.923076923077
potato,potatao ,0.923076923077
apple,appel ,0.8
您收到该错误是因为记录行[0] 或行[1] 很可能包含 NaN 值。
尝试通过使 str(row[0]) 和 str(row[1])
强制他们首先串起来
我对 python 编程还很陌生。我正在尝试获取一个包含两列字符串值的 csv 文件,并想比较两列之间字符串的相似率。然后我想获取值并在另一个文件中输出比率。
csv 可能如下所示:
Column 1|Column 2
tomato|tomatoe
potato|potatao
apple|appel
我希望输出文件显示每一行,第 1 列中的字符串与第 2 列中的字符串有多相似。我正在使用 difflib 输出比率得分。
这是我目前的代码:
import csv
import difflib
f = open('test.csv')
csf_f = csv.reader(f)
row_a = []
row_b = []
for row in csf_f:
row_a.append(row[0])
row_b.append(row[1])
a = row_a
b = row_b
def similar(a, b):
return difflib.SequenceMatcher(a, b).ratio()
match_ratio = similar(a, b)
match_list = []
for row in match_ratio:
match_list.append(row)
with open("output.csv", "wb") as f:
writer = csv.writer(f, delimiter=',')
writer.writerows(match_list)
f.close()
我收到错误:
Traceback (most recent call last):
File "comparison.py", line 24, in <module>
for row in match_ratio:
TypeError: 'float' object is not iterable
我觉得我没有正确导入列列表并且 运行 它与 sequencematcher 函数不符。
您在此处设置的 for
循环期望您拥有 match_ratio
的数组之类的东西,并且根据您收到的错误判断,这不是您拥有的。看起来您缺少 difflib.SequenceMatcher
的第一个参数,它可能应该是 None
。请参阅此处的 6.3.1:https://docs.python.org/3/library/difflib.html
如果没有指定第一个参数,我认为您正在从 difflib.SequenceMatcher
返回 0.0
,然后尝试 运行 ratio
。即使您更正了 SequenceMatcher
调用,我认为您仍然会尝试迭代 ratio
返回的单个浮点值。我认为您需要在循环内为要比较的每组值调用 SequenceMatcher
。
所以你会在你的函数中得到一个更像这样的调用:difflib.SequenceMatcher(None, a, b)
。或者,如果您愿意,因为这些是命名参数,您可以这样做:difflib.SequenceMatcher(a=a, b=b)
.
您收到错误消息是因为您在字符串列表上 运行 SequenceMatcher,而不是在字符串本身上。当你这样做时,你会得到一个单一的浮点值,而不是我认为你期望的口粮值列表。
如果我明白你想做什么,那么你就不需要先阅读这些行。您可以在遍历行时简单地找到差异比率。
import csv
import difflib
match_list = []
with open('test.csv') as f:
csv_f = csv.reader(f)
for row in csv_f:
match_list.append([difflib.SequenceMatcher(a=row[0], b=row[1]).ratio()])
with open('output.csv', 'w') as f:
writer = csv.writer(f, delimiter=',')
writer.writerows(match_list)
您的示例文件似乎包含标记。假设您实际上正在读取 CSV 文件,您得到的错误是因为 match_ratio 不是可迭代的数据类型,它是一个浮点数——函数的 return 值:similar()。在您的代码中,函数调用必须包含在 for 循环中才能为每个 a、b 字符串对调用它。这是我创建的一个工作示例,它取消了显式 for 循环,而是使用列表理解:
import csv
from difflib import SequenceMatcher
path_in = 'csv1.csv'
path_out = 'csv2.csv'
with open(path_in, 'r') as csv_file_in:
csv_reader = csv.reader(csv_file_in)
col_headers = csv_reader.next()
for row in csv_reader:
results = [[row[0],
row[1],
SequenceMatcher(None, row[0], row[1]).ratio()]
for row in csv_reader]
with open(path_out, 'wb') as csv_file_out:
col_headers.append('Ratio')
out_rows = [col_headers] + results
writer = csv.writer(csv_file_out, delimiter=',')
writer.writerows(out_rows)
除了您收到的错误之外,您在实例化 SequenceMatcher 对象时可能还会 运行 遇到问题 -- 它的第一个参数未在您的代码中指定。您可以在 Python 文档中找到有关 list comprehensions and SequenceMatcher 的更多信息。祝你 Python 编码好运。
这是使用 pandas
完成此操作的另一种方法:
Consider your csv data is like this:
Column 1,Column 2
tomato,tomatoe
potato,potatao
apple,appel
CODE
import pandas as pd
import difflib as diff
#Read the CSV
df = pd.read_csv('datac.csv')
#Create a new column 'diff' and get the result of comparision to it
df['diff'] = df.apply(lambda x: diff.SequenceMatcher(None, x[0].strip(), x[1].strip()).ratio(), axis=1)
#Save the dataframe to CSV and you could also save it in other formats like excel, html etc
df.to_csv('outdata.csv',index=False)
Result
Column 1,Column 2 ,diff
tomato,tomatoe ,0.923076923077
potato,potatao ,0.923076923077
apple,appel ,0.8
您收到该错误是因为记录行[0] 或行[1] 很可能包含 NaN 值。 尝试通过使 str(row[0]) 和 str(row[1])
强制他们首先串起来