2013-05-06 11 views
6

Ho alcune domande sulle funzioni dell'albero di NLTK. Sto cercando di estrarre una determinata parola dalla struttura ad albero come quella indicata di seguito.Estrazione di un valore foglia specifico dalla struttura ad albero nltk con Python

test = Tree.parse('(ROOT(SBARQ(WHADVP(WRB How))(SQ(VBP do)(NP (PRP you))(VP(VB ask)(NP(DT a)(JJ total)(NN stranger))(PRT (RP out))(PP (IN on)(NP (DT a)(NN date)))))))') 

print "Input tree: ", test 
print test.leaves() 

(SBARQ 
    (WHADVP (WRB How)) 
    (SQ 
     (VBP do) 
     (NP (PRP you)) 
     (VP 
     (VB ask) 
     (NP (DT a) (JJ total) (NN stranger)) 
     (PRT (RP out)) 
     (PP (IN on) (NP (DT a) (NN date))))))) 

['How', 'do', 'you', 'ask', 'a', 'total', 'stranger', 'out', 'on', 'a', 'date'] 

È possibile trovare un elenco di tutte le parole che utilizzano la funzione leaves(). C'è un modo per ottenere solo una foglia specifica? Ad esempio: mi piacerebbe ottenere solo il nome/cognome dalla frase NP? La risposta sarebbe "straniera" per il primo nome e "data" come ultimo nome.

risposta

10

Sebbene le frasi nominali possano essere annidate all'interno di altri tipi di frasi, credo che la maggior parte delle grammatiche abbia sempre nomi in frasi nominali. Quindi la tua domanda può essere riformulata come: Come trovi il primo e l'ultimo nome?

Si può semplicemente ottenere tutti tuple s di parole e tag POS e filtrare come questo,

>>> [word for word,pos in test.pos() if pos=='NN'] 
['stranger', 'date'] 

che in questo caso è solo due così il gioco è fatto. Se avessi più nomi, dovresti semplicemente indicizzare l'elenco su [0] e [-1].


se si stesse cercando un altro POS che potrebbe essere utilizzato in diverse frasi, ma si voleva solo il suo utilizzo all'interno di un particolare di uno o se si ha una strana grammatica che ha permesso sostantivi al di fuori di NP, è possibile effettuare le seguenti operazioni ...

potete trovare subtrees di 'NP' facendo,

>>> NPs = list(test.subtrees(filter=lambda x: x.node=='NP')) 
>>> NPs 
[Tree('NP', [Tree('PRP', ['you'])]), Tree('NP', [Tree('DT', ['a']), Tree('JJ', ['total']), Tree('NN', ['stranger'])]), Tree('NP', [Tree('DT', ['a']), Tree('NN', ['date'])])] 

Continuando a restringere le sottostrutture, possiamo usare questo risultato per cercare 'NN' parole,

>>> NNs_inside_NPs = map(lambda x: list(x.subtrees(filter=lambda x: x.node=='NN')), NPs) 
>>> NNs_inside_NPs 
[[], [Tree('NN', ['stranger'])], [Tree('NN', ['date'])]] 

quindi questo è un list di list s di tutti i 'NN' s all'interno di ogni 'NP' frasi. In questo caso accade solo zero o un nome in ogni frase.

Ora abbiamo solo bisogno di passare attraverso le 'NP' s e ottenere tutte le leaves dei singoli nomi (il che significa che in realtà vogliamo solo accedere alla parte 'stranger' di Tree('NN', ['stranger'])).

>>> [noun.leaves()[0] for nouns in NNs_inside_NPs for noun in nouns] 
['stranger', 'date'] 
+0

Grazie funziona. Ora ho solo bisogno di prendere il primo oggetto della lista. – Cryssie

+1

Utilizzando Python 3.4.1 e NLTK 3.2.1, usare 'x.label()' piuttosto che 'x.node' per cercare i risultati, altrimenti si otterrà un' NotImplementedError ("Use label() per accedere a un'etichetta di nodo . ")' eccezione. I.e: 't = list (r.subtrees (filter = lambda x: x.label() == 'NP'))' – InfectedPacket

Problemi correlati