2013-05-06 107 views
6

我對NLTK的樹函數有一些疑問。我試圖從樹結構中提取某個單詞,如下所示。用Python從nltk樹結構中提取特定的葉子值

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

我可以使用leaves()函數找到所有單詞的列表。有沒有辦法只得到一個特定的葉子?例如:我想只從NP短語中得到第一個/最後一個名詞?對於第一個名詞和「日期」作爲最後一個名詞,答案會是「陌生人」。

回答

10

儘管名詞短語可以嵌套在其他類型的短語中,但我相信大多數語法在名詞短語中總是有名詞。所以你的問題可以改爲:你如何找到第一個和最後一個名詞?

你可以簡單地讓所有tuple的話和POS標籤和過濾器這樣,

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

在這種情況下是隻有兩個,所以你就大功告成了。如果你有更多的名詞,你只需要索引[0][-1]


如果你正在尋找能在不同階段使用,但您只希望它使用一個特定的內部或者如果你有一個奇怪的語法,允許納米顆粒的外面名詞,你可以做以下的另一POS ...

您可以通過執行發現的'NP'subtrees

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

繼續縮小子樹,我們可以用這個結果來尋找'NN'話,

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

所以這是listlist A S所有'NN' s分別'NP'短語內的。在這種情況下,每個短語中只有零個或一個名詞。

現在我們只需要經過'NP' S和獲取單個名詞的所有leaves(這實際上意味着,我們只是想訪問的Tree('NN', ['stranger'])'stranger'部分)。

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

感謝它的工作。現在我只需要列出第一個項目。 – Cryssie 2013-05-07 10:19:23

+1

使用Python 3.4.1和NLTK 3.2.1,使用'x.label()'而不是'x.node'來查找結果,否則將得到一個'NotImplementedError(「使用label()來訪問節點標籤。「)例外。 I.e:'t = list(r.subtrees(filter = lambda x:x.label()=='NP'))' – InfectedPacket 2016-10-20 22:52:59