子树提取NLTK树

时间:2016-06-16 15:01:57

标签: python nltk subtree

我需要一些NLTK树的帮助。

我试图从这个法国树中提取一些子树:

Original Tree

(SENT (NP-SUJ↓ (PRO=H Personne)) (VN=H (ADV* ne) (V=H sait)) (ADV* exactement) (PONCT* .))

我只想提取POS标签末尾有'= H'的树,然后添加父节点:

像这样:(NP-SUJ↓ (PRO=H Personne)) and this: (VN=H (V=H sait))

我写了一个函数:

def AddParent(tree):
    grammar = []
    for subtree in tree.subtrees():
        if subtree.height()==2 and subtree.label().endswith("=H"):
            PartialTree = ParentedTree(subtree.parent().label(), 
                               [ParentedTree(subtree.label(), subtree)])
            grammar.append(PartialTree)
    return grammar

#Test
pt = ParentedTree.fromstring("(SENT (NP-SUJ↓ (PRO=H Personne)) (VN=H (ADV* ne) (V=H sait)) (ADV* exactement) (PONCT* .))")
AddParent(pt)
[ParentedTree('NP-SUJ↓', [ParentedTree('PRO=H', ['Personne'])]), 
ParentedTree('VN=H', [ParentedTree('V=H', ['sait'])])]

我在这里有两个问题:首先,我想继续向原始树中的子树添加信息。例如,我想继续添加祖先节点,然后添加子节点,以执行以下操作:

(SENT (NP-SUJ↓ ) (VN=H (V=H sait)))

Subtree

但是我忘记了原来的树......

其次,parent()函数返回其中包含的所有子树。我只想拥有特定的节点。

提取最后一个子树的好方法是什么?

非常感谢你的帮助!我是新手,但我真的很喜欢!

1 个答案:

答案 0 :(得分:3)

我不能说我理解您对parent()的抱怨(也许您的意思是subtrees()?),但是有更简单的方法来接触子树:

  1. 表面改进:subtrees()函数接受filter参数,因此您无需在代码中检查返回的子树:

    for subtree in tree.subtrees(filter=lambda t: t.label().endswith("=H"))
    
  2. 子树是对原始树的子部分的引用。如果你不修改它,它仍然是原始的一部分,你可以提升树(因为你使用"父级"树。)事实上,请注意,如果你修改内容对于子树,将修改原始树。但是,不是嵌入您在新节点下找到的树,而是构建一个全新的副本:

    partial = ParentedTree(subtree.parent().label(), [ subtree.copy() ])
    

    然后,您可以自由删除或更改副本中的分支,并且仍然可以使用原始treesubtree

  3. 虽然您可以使用parent()方法爬上树,但我经常发现使用"树位置"更方便。树位置是整数元组,它作为树下的路径(使用它像列表中的整数索引)。要查找父级,您只需要切掉树位置的最后一个元素:

    for postn in tree.treepositions():
        if tree.label().endswith("=H"):
            parentpos = postn[:-1]   # everything but the last element
            partial = Tree(tree[parentpos].label(), [ tree[postn] ])
    

    请注意,如果您使用此方法,则不再需要parent()方法,因此您也可以使用Tree,而不是ParentedTree

  4. 上述内容可能并不能完全符合您的要求(很难看到您正在做的事情),但我希望您能够了解到这一点。