Python:使用单词交集而不是字符交集的Jaccard距离

2024-06-14 03:44:12 发布

您现在位置:Python中文网/ 问答频道 /正文

我没有意识到Python set函数实际上是将字符串分隔成单个字符的。我为Jaccard编写了python函数并使用python交集方法。我向这个方法传递了两个集合,在将这两个集合传递到jaccard函数之前,我在setring上使用set函数。

示例:假设我有字符串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),它将字符串分隔成字符。所以当我把它发送到jaccard函数交集时,实际上看起来是字符交集,而不是词对词交集。我怎样才能做到字字交叉。

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

如果我不对字符串NEW Fujifilm 16MP 5x Optical Zoom Point and Shoot CAMERA 2 7 screen.jpg调用set函数,则会出现以下错误:

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

我不想进行字符到字符的交集,我想做单词到单词的交集,并得到jaccard的相似度。


Tags: and函数字符串newlen字符screencamera
3条回答

尝试先将字符串拆分为单词:

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'])

此属性不是集合的唯一属性:

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

这里发生的事情是,字符串被视为一个可iterable序列,并被逐个字符处理。

你在set上看到的一样东西:

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

若要修复此问题,请对现有集使用.add(),因为.add()不使用interable:

>>> 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()、元组、列表或其他iterable,这样字符串就不会被视为iterable:

>>> 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'])

我的计算Jaccard距离的函数:

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

相关问题 更多 >