2016-04-22 4 views
3

Я очень новичок в программировании на питоне. Я пытаюсь взять файл csv, который имеет два столбца строковых значений и хочет сравнить отношение подобия строки между обоими столбцами. Затем я хочу взять значения и вывести соотношение в другой файл.Сравнение двух столбцов csv и коэффициента сходства строк в другом 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 ,

ответ

2

Вот еще один способ, чтобы это было сделано с помощью 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

Это сработало очень хорошо. Мне нужно исследовать панды еще. Благодаря! – Jimmy

2

Цикл for, который вы настраиваете здесь, ожидает нечто вроде массива, где у вас есть match_ratio, и, судя по ошибке, которую вы получаете, это не то, что у вас есть. Похоже, у вас отсутствует первый аргумент для difflib.SequenceMatcher, который, вероятно, должен быть None. См 6.3.1 здесь: https://docs.python.org/3/library/difflib.html

Без этого первого заданного аргумента, я думаю, вы получаете обратно 0.0 от difflib.SequenceMatcher, а затем пытается запустить ratio от этого. Даже если вы исправите свой вызов SequenceMatcher, я думаю, вы все равно будете пытаться перебирать одно значение с плавающей точкой, возвращаемое ratio. Я думаю, вам нужно позвонить SequenceMatcher внутри цикла для каждого набора значений, которые вы сравниваете.

Таким образом, вы могли бы позвонить с вызовом, как это в вашей функции: difflib.SequenceMatcher(None, a, b). Или, если вы хотите, поскольку они называются аргументами, вы можете сделать что-то вроде этого: difflib.SequenceMatcher(a=a, b=b).

+0

Я также добавлю, что переименование строк 'row_a' и' row_b' на 'a' и' b' на полпути через действительно запутывает. Легко забыть, что вы имеете дело с двумя списками здесь, а не с двумя строковыми значениями, которые вы можете сравнить. –

+0

А, это имеет большой смысл. Я понимаю, о чем вы говорите. – Jimmy

0

Вы получаете сообщение об ошибке, поскольку вы используете SequenceMatcher в списке строк, а не на самих строках. Когда вы это сделаете, вы получите одно значение float, а не список значений рациона, которые, как я думаю, вы ожидали.

Если я понимаю, что вы пытаетесь сделать, вам не нужно сначала читать строки. Вы можете просто найти коэффициент диффузии при повторении по строкам.

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) 
+0

Ничего себе, это намного чище, чем у меня. Я попытался запустить этот код и образец csv-файла и выдает эту ошибку: writer.writerows (match_list) _csv.Error: sequence expected – Jimmy

+0

Извините, я обновил сообщение, чтобы исправить это. writerows ожидает итерабельность итераций, но мое решение проходило с возможностью повтора поплавков. – Jggrnaut

1

Ваш образец файла выглядит так, как будто он содержит метки разметки. Предполагая, что вы действительно читаете CSV-файл, ошибка, которую вы получаете, связана с тем, что match_ratio не является итерируемым типом данных, это число с плавающей запятой - возвращаемое значение вашей функции: similar(). В вашем коде вызов функции должен содержаться в цикле for, чтобы вызвать его для каждой пары a, b string. Вот рабочий пример, который я создал, что покончила с явным для петель и использует список понимание вместо:

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 - его первый параметр не был указан в вашем коде. Вы можете найти больше на list comprehensions и SequenceMatcher в документах Python. Удачи в вашем будущем кодировании на Python.

1

Вы получаете эту ошибку, потому что записи строки [0] или строка [1] содержит, скорее всего, значения NaN. Попробуйте заставить их сначала вставлять str (строка [0]) и str (строка [1])