【问题标题】:How to build an alphabetical tree from a list of words in R?如何从 R 中的单词列表构建字母树?
【发布时间】:2014-11-22 08:15:22
【问题描述】:

我的问题很简单。我有一长串单词,例如abbey, 住持, abbr, 遵守。

我想如下构建一棵树:

0A级 | 1级B / \ 2 级 B I / | \ | 3 级 E 或 R D | | | 4 级 Y T E

有没有一种简单的方法来解析单词表并在 R 中创建这样的结构?

非常感谢您的帮助!

真诚地, 克里斯

【问题讨论】:

  • 你能澄清一下输出应该是什么吗?嵌套列表?来自igraph 的有向图?或者只是上面的树打印到标准输出?还是 R 中有我不知道的树形数据结构?

标签: r dictionary tree


【解决方案1】:

这是一个基于igraph 的解决方案,它使用部分单词标记图形的每个节点,以便使用完整单词命名终端节点:

library(igraph)
library(stringr)

initgraph = function(){
    # create a graph with one empty-named node and no edges
    g=graph.empty(n=1)
    V(g)$name=""
    g
}


wordtree <- function(g=initgraph(),wordlist){
    for(word in wordlist){
        # turns "word" into c("w","wo","wor","word")
        subwords = str_sub(word, 1, 1:nchar(word))
        # make a graph long enough to hold all those sub-words plus start node
        subg = graph.lattice(length(subwords)+1,directed=TRUE)
        # set vertex nodes to start node plus sub-words
        V(subg)$name=c("",subwords)
        # merge *by name* into the existing graph
        g = graph.union(g, subg)
    }
    g
}

加载完毕,

g = wordtree(initgraph(), c("abbey","abbot","abbr","abide"))
plot(g)

得到

您可以将单词作为第一个参数传入现有树中:

> g = wordtree(g,c("now","accept","answer","please"))
> plot(g)

树总是以名称为“”的节点为根,并且所有终端节点(没有出边的节点)都有单词。 igraph 中有一些功能可以在需要时将它们取出。当你完成它时,你实际上并没有说你想用它做什么......或者当我们为你完成它时:)

请注意,有一个很好的绘制树的布局,看起来像您的 ascii 示例:

plot(g,layout=layout.reingold.tilford)

【讨论】:

  • 太棒了!感谢您的详细回答!
  • 对不起,我一开始以为这样就可以了,但仍然存在与 flodel 的解决方案相同的问题,即如果列表中的单词仅在最后一个字符上有所不同,则其中一个会盖过另一个,例如“检索”和“检索器”。换句话说,我需要知道中间节点何时也是 ast 词的结尾。我将更新问题以反映此问题。
  • 好的,仔细考虑一下,在词尾使用标记不会产生任何冲突,并且比考虑其他数据结构更容易。所以你的解决方案(以及弗洛德尔的)将完成这项工作。 (为了回答您的问题,一位朋友正在研究日语语言学,我只是想通过编写一个处理大型名词数据库并对其进行各种分析的 R 脚本来节省她的时间。许多问题之一是研究一些名词子集中的汉字耦合频率,因此我的问题。)再次感谢您的帮助!
  • 好点!我认为通过添加一个可以工作的端节点,但是你有一个所有叶子都连接到端节点的树。我认为有两行需要编辑...
【解决方案2】:

这是一个递归构建嵌套列表的解决方案,以字符为名称:

x <- c("abb", "abbey", "abbot", "abbr", "abide")

char.tree <- function(words, end = NULL) {
   first <- substr(words, 1, 1)
   rest  <- substr(words, 2, nchar(words))
   zi    <- nchar(words) == 0L 
   c(list(end)[any(zi)],
     lapply(split(rest[!zi], first[!zi]), char.tree, end = end))
}

str(char.tree(x))
# List of 1
#  $ a:List of 1
#   ..$ b:List of 2
#   .. ..$ b:List of 4
#   .. .. ..$  : NULL
#   .. .. ..$ e:List of 1
#   .. .. .. ..$ y:List of 1
#   .. .. .. .. ..$ : NULL
#   .. .. ..$ o:List of 1
#   .. .. .. ..$ t:List of 1
#   .. .. .. .. ..$ : NULL
#   .. .. ..$ r:List of 1
#   .. .. .. ..$ : NULL
#   .. ..$ i:List of 1
#   .. .. ..$ d:List of 1
#   .. .. .. ..$ e:List of 1
#   .. .. .. .. ..$ : NULL

【讨论】:

  • 嗨弗洛德尔!感谢您的精彩输入。它几乎是完美的。我的描述并不完全清楚。您的解决方案很合适,但我需要能够存储“检索”和“检索器”。如果我没记错的话,在您的解决方案中,“retrieve”将被“retriever”所掩盖(因为最终的 NULL 被覆盖)。
  • 听起来你需要一个“终端”标记,所以你有 R-E-T-R-I-E-V-E 然后分支到“终端”用于 RETRIEVE 和 -R-“终端”用于 RETRIEVER。
  • 现在应该修复了。
  • 亲爱的弗洛德尔,感谢您花时间回答我的问题。您的建议简单而优雅,但我选择了 Spacedman 的解决方案,因为它更强大。我希望我可以将您的答案标记为有用,但我没有为此所需的声誉点数。
  • 这是一个非常优雅和多功能的解决方案,我非常喜欢它并实现in my own problem。是否有可能以某种方式访问​​层次结构,正如 OP 的问题(Level 0Level 4)中所显示的那样
猜你喜欢
  • 1970-01-01
  • 2011-01-15
  • 1970-01-01
  • 2021-01-15
  • 1970-01-01
  • 2020-07-21
  • 2015-01-25
  • 1970-01-01
  • 2012-02-24
相关资源
最近更新 更多