2015-11-02 144 views
6

我想从openNLP为树结构的可视化显示解析(POS标记)。下面我提供从openNLP解析树,但我不能作为Python's parsing共同的视觉树。可视化解析树结构

install.packages(
    "http://datacube.wu.ac.at/src/contrib/openNLPmodels.en_1.5-1.tar.gz", 
    repos=NULL, 
    type="source" 
) 

library(NLP) 
library(openNLP) 

x <- 'Scroll bar does not work the best either.' 
s <- as.String(x) 

## Annotators 
sent_token_annotator <- Maxent_Sent_Token_Annotator() 
word_token_annotator <- Maxent_Word_Token_Annotator() 
parse_annotator <- Parse_Annotator() 

a2 <- annotate(s, list(sent_token_annotator, word_token_annotator)) 
p <- parse_annotator(s, a2) 
ptext <- sapply(p$features, `[[`, "parse") 
ptext 
Tree_parse(ptext) 

## > ptext 
## [1] "(TOP (S (NP (NNP Scroll) (NN bar)) (VP (VBZ does) (RB not) (VP (VB work) (NP (DT the) (JJS best)) (ADVP (RB either))))(. .)))" 
## > Tree_parse(ptext) 
## (TOP 
## (S 
##  (NP (NNP Scroll) (NN bar)) 
##  (VP (VBZ does) (RB not) (VP (VB work) (NP (DT the) (JJS best)) (ADVP (RB either)))) 
##  (. .))) 

树结构应类似于此:

enter image description here

是否有显示这棵树的可视化的方法吗?

我发现this related tree viz问题密谋数字表达式,可能是使用的,但我不能一概而论判解析可视化。

+0

好创建图形,但之后呢? – Indi

+2

也许通过https://en.wikibooks.org/wiki/LaTeX/Linguistics#tikz-qtree? – Reactormonk

回答

8

这里是一个igraph版本。该函数将Parse_annotator作为输入的结果,因此在您的示例中为ptextNLP::Tree_parse已经创建了一个很好的树形结构,所以这里的想法是递归地遍历它并创建一个边界列表来插入igraph。边界列表只是头部 - >尾部值的2列矩阵。

为了适当的节点之间igraph创建的边缘,他们需要有独特的标识符。我通过在使用Tree_parse之前在文本中添加一个整数序列(使用regmatches<-)来完成此操作。

内部功能edgemaker遍历树,在edgelist填充,因为它去。可以选择将叶子与其余节点分开着色,但是如果您通过vertex.label.color选项,则它们会将它们全部着色。

## Make a graph from Tree_parse result 
parse2graph <- function(ptext, leaf.color='chartreuse4', label.color='blue4', 
         title=NULL, cex.main=.9, ...) { 
    stopifnot(require(NLP) && require(igraph)) 

    ## Replace words with unique versions 
    ms <- gregexpr("[^() ]+", ptext)          # just ignoring spaces and brackets? 
    words <- regmatches(ptext, ms)[[1]]         # just words 
    regmatches(ptext, ms) <- list(paste0(words, seq.int(length(words)))) # add id to words 

    ## Going to construct an edgelist and pass that to igraph 
    ## allocate here since we know the size (number of nodes - 1) and -1 more to exclude 'TOP' 
    edgelist <- matrix('', nrow=length(words)-2, ncol=2) 

    ## Function to fill in edgelist in place 
    edgemaker <- (function() { 
     i <- 0          # row counter 
     g <- function(node) {      # the recursive function 
      if (inherits(node, "Tree")) {   # only recurse subtrees 
       if ((val <- node$value) != 'TOP1') { # skip 'TOP' node (added '1' above) 
        for (child in node$children) { 
         childval <- if(inherits(child, "Tree")) child$value else child 
         i <<- i+1 
         edgelist[i,1:2] <<- c(val, childval) 
        } 
       } 
       invisible(lapply(node$children, g)) 
      } 
     } 
    })() 

    ## Create the edgelist from the parse tree 
    edgemaker(Tree_parse(ptext)) 

    ## Make the graph, add options for coloring leaves separately 
    g <- graph_from_edgelist(edgelist) 
    vertex_attr(g, 'label.color') <- label.color # non-leaf colors 
    vertex_attr(g, 'label.color', V(g)[!degree(g, mode='out')]) <- leaf.color 
    V(g)$label <- sub("\\d+", '', V(g)$name)  # remove the numbers for labels 
    plot(g, layout=layout.reingold.tilford, ...) 
    if (!missing(title)) title(title, cex.main=cex.main) 
} 

因此,使用您的例子中,字符串x及其注释版本ptext,它看起来像

x <- 'Scroll bar does not work the best either.' 
ptext 
# [1] "(TOP (S (NP (NNP Scroll) (NN bar)) (VP (VBZ does) (RB not) (VP (VB work) (NP (DT the) (JJS best)) (ADVP (RB either))))(. .)))" 

通过调用

library(igraph) 
library(NLP) 

parse2graph(ptext, # plus optional graphing parameters 
      title = sprintf("'%s'", x), margin=-0.05, 
      vertex.color=NA, vertex.frame.color=NA, 
      vertex.label.font=2, vertex.label.cex=1.5, asp=0.5, 
      edge.width=1.5, edge.color='black', edge.arrow.size=0) 

enter image description here

+1

我哭了:-)我很欣赏这个+500 –

+0

的工作,值得我在R 3年能够做到这一点。回到可以轻松解析的软件包,最后一部分是我想要一种绘制解析句子的方式。您能否通过电子邮件将您的实际信息发送给我,以便我可以将您作为包装上的作者? –

+0

现在不需要高效,只是在工作:-)即使速度慢/效率低下,它也比当前R可用的更好。我打算使用你的SO处理并引用这个问题来保持道德的完整性(即在到期时给予信用)。如果您随时改变主意,请告诉我,我将使用您的真实姓名。再次感谢。 –