Python: Jaccard Distance с использованием пересечения слов, но не пересечения символов

Я не осознавал, что эта функция set Python фактически разделяет строку на отдельные символы. Я написал функцию Python для Jaccard и использовал метод пересечения Python. Я передал два набора в этот метод, и перед передачей двух наборов в мою функцию жаккарда я использую функцию набора для setring.

пример: предположим, что у меня есть строка NEW Fujifilm 16MP 5x Optical Zoom Point and Shoot CAMERA 2 7 screen.jpg, я бы назвал set(NEW Fujifilm 16MP 5x Optical Zoom Point and Shoot CAMERA 2 7 screen.jpg), которая разделит строку на символы. Поэтому, когда я отправляю его на пересечение функций жаккарда, на самом деле смотрю на пересечение символов, а не на пересечение слов. Как я могу сделать слово в слово пересечение.

#implementing jaccard
def jaccard(a, b):
    c = a.intersection(b)
    return float(len(c)) / (len(a) + len(b) - len(c))

если я не вызываю функцию set для своей строки NEW Fujifilm 16MP 5x Optical Zoom Point and Shoot CAMERA 2 7 screen.jpg, я получаю следующую ошибку:

    c = a.intersection(b)
AttributeError: 'str' object has no attribute 'intersection'

Вместо пересечения символов я хочу сделать пересечение слов и получить сходство с жаккардом.


person add-semi-colons    schedule 11.08.2012    source источник


Ответы (4)


Попробуйте сначала разбить строку на слова:

word_set = set(your_string.split())

Пример:

>>> word_set = set("NEW Fujifilm 16MP 5x".split())
>>> character_set = set("NEW Fujifilm 16MP 5x")
>>> word_set
set(['NEW', '16MP', '5x', 'Fujifilm'])
>>> character_set
set([' ', 'f', 'E', 'F', 'i', 'M', 'j', 'm', 'l', 'N', '1', 'P', 'u', 'x', 'W', '6', '5'])
person Amber    schedule 11.08.2012
comment
На самом деле это именно то, что я искал, когда использую функцию добавления во время пересечения, которое ищет полное совпадение. - person add-semi-colons; 11.08.2012

Моя функция для расчета расстояния Жаккара:

def DistJaccard(str1, str2):
    str1 = set(str1.split())
    str2 = set(str2.split())
    return float(len(str1 & str2)) / len(str1 | str2)

>>> DistJaccard("hola amigo", "chao amigo")
0.333333333333
person JBrain    schedule 07.08.2014

Это свойство не уникально для наборов:

>>> list('NEW Fujifilm')
['N', 'E', 'W', ' ', 'F', 'u', 'j', 'i', 'f', 'i', 'l', 'm']

Здесь происходит то, что строка обрабатывается как итерируемая последовательность и обрабатывается символ за символом.

То же самое вы видите с набором:

>>> set('string')
set(['g', 'i', 'n', 's', 'r', 't'])

Чтобы исправить это, используйте .add() в существующем наборе, поскольку .add() не использует интерактивный объект:

>>> se=set()
>>> se.add('NEW Fujifilm 16MP 5x Optical Zoom Point and Shoot CAMERA 2 7 screen.jpg')
>>> se
set(['NEW Fujifilm 16MP 5x Optical Zoom Point and Shoot CAMERA 2 7 screen.jpg'])

Или используйте split(), кортеж, список или какую-либо альтернативную итерацию, чтобы строка не рассматривалась как итерация:

>>> set('something'.split())
set(['something'])
>>> set(('something',))
set(['something'])
>>> set(['something'])
set(['something'])

Добавьте больше элементов на основе вашей строки пословно:

>>> se=set(('Something',)) | set('NEW Fujifilm 16MP 5x Optical Zoom Point and Shoot CAMERA 2 7 screen.jpg'.split())   

Или, если вам нужно понимание какой-то логики при добавлении в набор:

>>> se={w for w in 'NEW Fujifilm 16MP 5x Optical Zoom Point and Shoot CAMERA 2 7 screen.jpg'.split() 
         if len(w)>3}
>>> se
set(['Shoot', 'CAMERA', 'Point', 'screen.jpg', 'Zoom', 'Fujifilm', '16MP', 'Optical'])

И это работает так, как вы ожидаете сейчас:

>>> 'Zoom' in se
True
>>> s1=set('NEW Fujifilm 16MP 5x Optical Zoom Point and Shoot CAMERA 2 7 screen.jpg'.split())
>>> s2=set('Fujifilm Optical Zoom CAMERA NONE'.split())
>>> s1.intersection(s2)
set(['Optical', 'CAMERA', 'Zoom', 'Fujifilm'])
person dawg    schedule 11.08.2012
comment
От пересечения слова к слову я думаю, что ОП действительно после set(a.split()).intersection(b.split()) (по модулю регистра и пунктуации). - person DSM; 11.08.2012

Это тот, который я написал на основе функции set -

def jaccard(a,b):
    a=a.split()
    b=a.split()
    union = list(set(a+b))
    intersection = list(set(a) - (set(a)-set(b)))
    print "Union - %s" % union
    print "Intersection - %s" % intersection
    jaccard_coeff = float(len(intersection))/len(union)
    print "Jaccard Coefficient is = %f " % jaccard_coeff
person medakeshav    schedule 03.06.2015