2012-08-11 8 views
6

Non mi sono reso conto che la funzione di set Python separa effettivamente la stringa in singoli caratteri. Ho scritto la funzione Python per Jaccard e ho usato il metodo di intersezione python. Ho passato due set in questo metodo e prima di passare i due set nella mia funzione jaccard uso la funzione set sul setring.Python: Jaccard Distance utilizzando l'intersezione di parole ma non l'intersezione di caratteri

esempio: suppongo di avere una stringa NEW Fujifilm 16MP 5x Optical Zoom Point and Shoot CAMERA 2 7 screen.jpg che chiamerei set(NEW Fujifilm 16MP 5x Optical Zoom Point and Shoot CAMERA 2 7 screen.jpg) che separerà la stringa in caratteri. Quindi, quando lo mando all'intersezione della funzione jaccard, in realtà guardo l'intersezione del carattere anziché l'intersezione tra parole e parole. Come posso fare l'intersezione parola per parola.

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

se io non chiamo set funzione mia stringa NEW Fujifilm 16MP 5x Optical Zoom Point and Shoot CAMERA 2 7 screen.jpg ricevo il seguente errore:

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

Invece di carattere a carattere di intersezione che voglio fare parola per parola incrocio e ottenere il Jaccard somiglianza.

risposta

9

provare a dividere la stringa in parole prima:

word_set = set(your_string.split()) 

Esempio:

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

In realtà questa è la cosa esatta che stavo cercando quando uso la funzione add durante l'intersezione che cerca la corrispondenza completa. –

2

Questa proprietà non è unico al set:

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

Che cosa sta succedendo qui è che la stringa viene trattato come una sequenza iterabile e in fase di elaborazione carattere per carattere.

Stessa cosa si sta vedendo con il set:

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

da risolvere, utilizzare .add() su un set esistente, dal momento che .add() non usa un 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']) 

in alternativa, utilizzare split(), una tupla, un elenco, o qualche iterabile si alternano in modo che la stringa non è trattato come un iterabile:

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

aggiungere altro elemento s in base alla stringa su una base parola per parola:

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

Oppure, se avete bisogno di una comprensione per una certa logica quando si aggiungono al set:

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

E farlo funzionare come si si aspettano ora:

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

Dalla "parola per parola di intersezione" Penso che l'OP sia in realtà dopo 'set (a.split()). Intersezione (b.split())' (modulo case e dettagli di punteggiatura.) – DSM

+0

@drewk grazie per l'esempio e ottima spiegazione. Brillante!!! –

6

mia funzione per calcolare Jaccard distanza:

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 
2

Questo è quello che ho scritto sulla base della funzione 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 
Problemi correlati