Python 比较csv的两列并在另一个csv中输出字符串相似性比率

Python 比较csv的两列并在另一个csv中输出字符串相似性比率,python,pandas,csv,difflib,sequencematcher,Python,Pandas,Csv,Difflib,Sequencematcher,我对python编程非常陌生。我试图获取一个csv文件,该文件有两列字符串值,并希望比较两列之间字符串的相似性比率。然后我想取这些值,并在另一个文件中输出比率 csv可能如下所示: Column 1|Column 2 tomato|tomatoe potato|potatao apple|appel 我希望输出文件为每一行显示第1列中的字符串与第2列中的字符串的相似程度。我使用difflib输出比率分数 这是我目前掌握的代码: import csv import difflib f

我对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
回溯(最近一次呼叫最后一次):
文件“comparison.py”,第24行,在
对于匹配比率中的行:
TypeError:“float”对象不可编辑

我觉得我没有正确导入列列表并针对sequencematcher函数运行它。

您在这里设置的
for
循环需要类似于数组的东西,其中有
匹配率
,从您得到的错误判断,这不是您所拥有的。看起来您缺少了
difflib.SequenceMatcher
的第一个参数,它可能应该是
None
。见6.3.1:

如果没有指定第一个参数,我认为您将从
difflib.SequenceMatcher
返回
0.0
,然后尝试运行
ratio
。即使您更正了
SequenceMatcher
调用,我认为您仍将尝试迭代
ratio
返回的单个浮点值。我认为您需要在循环内调用
SequenceMatcher
,以获得所比较的每一组值


因此,在函数中会有一个更像这样的调用:
difflib.SequenceMatcher(None,a,b)
。或者,如果您愿意,因为这些都是命名参数,您可以这样做:
difflib.SequenceMatcher(a=a,b=b)

您会收到错误,因为您是在字符串列表上运行SequenceMatcher,而不是在字符串本身上运行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不是一个iterable数据类型,它是一个浮点数--函数的返回值:similor()。在代码中,函数调用必须包含在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文档中找到更多信息。祝您在未来的Python编码中好运。

这里有另一种方法,可以使用:

考虑您的csv数据如下:

代码

结果


之所以出现此错误,是因为记录行[0]或行[1]很可能包含NaN值。
尝试通过使str(第[0]行)和str(第[1]行)来强制他们首先使用字符串。

我还要补充一点,将
第a行
第b行
重命名到
第a行和
第b行
中间非常混乱。很容易忘记这里处理的是两个列表,而不是两个可以比较的字符串值。啊,这很有意义。我明白你指的是什么。哇,那比我的干净多了。我尝试运行此代码和一个示例csv文件,并产生以下错误:writer.writerows(match_list)_csv.error:sequence expected抱歉,我更新了帖子以修复此问题。writerows期望一个iterable的iterable,但我的解决方案是传递一个iterable的float。这非常有效。我需要更多地探索熊猫。谢谢
Column 1,Column 2 
tomato,tomatoe 
potato,potatao 
apple,appel
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)
Column 1,Column 2 ,diff
tomato,tomatoe ,0.923076923077
potato,potatao ,0.923076923077
apple,appel ,0.8