使节点集连接到R中的主父节点

时间:2016-05-24 06:30:36

标签: r

我有一个有6行3列的数据集。第一列表示子项,而第二列表示相应子项的直接父项。 enter image description here

上面,人们可以看到" a"和" b"没有父母。而" c"只有父母,那是" a"。 " d"有父母" b"和" c"等等。

我需要的是:如果给孩子输入,它应该给我孩子的所有祖先,包括孩子。

e.g。 " F"是我选择的孩子然后所需的输出应该是: {" f"," d"," b"},{" f"," d",&# 34; c"," a"},{" f"," e"," b"},{&#34 ; f"," e"," c"," a"}。

注意:节点的顺序无关紧要。

提前非常感谢你。

2 个答案:

答案 0 :(得分:2)

创建样本数据。注意在这里使用stringsAsFactors,我假设您的数据是字符而不是因素:

> d <- data.frame(list("c" = c("a", "b", "c", "d", "e", "f"), "p1" = c(NA, NA, "a", "b", "b", "d"), "p2" = c(NA, NA, NA, "c", "c", "e")),stringsAsFactors=FALSE)

首先整理它 - 使数据变长而不是宽,每行都是子父对:

> pairs = subset(reshape2::melt(d,id.vars="c",value.name="parent"), !is.na(parent))[,c("c","parent")]
> pairs
   c parent
3  c      a
4  d      b
5  e      b
6  f      d
10 d      c
11 e      c
12 f      e

现在我们可以制作父子关系图。这是定向的图,因此将child-parent绘制为箭头:

> g = graph.data.frame(pairs)
> plot(g)

enter image description here

现在我不确定你想要什么,但是igraph函数可以做任何事情......例如,在这里搜索从d开始的图表我们可以获得各种信息:

> d_search = bfs(g,"d",neimode="out", unreachable=FALSE, order=TRUE, dist=TRUE)

首先,哪些节点是d的祖先?它可以通过详尽的(这里,广度优先)搜索从d到达:

> d_search$order
+ 6/6 vertices, named:
[1] d    c    b    a    <NA> <NA>

请注意,它也包含d。足够琐碎从这个列表中删除。这为你提供了d的祖先,这就是你所要求的。

这些节点与d的关系是什么?

> d_search$dist
  c   d   e   f   a   b 
  1   0 NaN NaN   2   1

我们发现ef无法访问,因此不是d的祖先。 cb是直接父母,a是祖父母。您可以从图表中查看。

您还可以使用shortest_paths等功能从任何孩子向上获取所有路径。

答案 1 :(得分:1)

这是一个递归函数,它可以生成所有可能的族行:

d <- data.frame(list("c" = c("a", "b", "c", "d", "e", "f"), 
      "p1" = c(NA, NA, "a", "b", "b", "d"), 
      "p2" = c(NA, NA, NA, "c", "c", "e")), stringsAsFactors = F)

# Make data more convenient for the task.
library(reshape2)
dp <-  melt(d, id = c("c"), value.name = "p") 

# Recursive function builds ancestor vectors.
getAncestors <- function(data, x, ancestors = list(x)) {

  parents <- subset(data, c %in% x & !is.na(p), select = c("c", "p"))

  if(nrow(parents) == 0) {
    return(ancestors)
  }

  x.c <- parents$c
  p.c <- parents$p

  ancestors <- lapply(ancestors, function(x) {
    if (is.null(x)) return(NULL)

    # Here we want to repeat ancestor chain for each new parent.
    res <- list()
    matches <- 0
    for (i in 1:nrow(parents)) {
      if (tail(x, 1) == parents[i, ]$c){
       res[[i]] <- c(x, parents[i, ]$p)
       matches <- matches + 1
      }
    }

    if (matches == 0) { # There are no more parents. 
      res[[1]] <- x
    }

    return (res)
  })

  # remove one level of lists.
  ancestors <- unlist(ancestors, recursive = F)

  res <- getAncestors(data, p.c, ancestors)
  return (res)

}

# Demo of results for the lowest level.
res <- getAncestors(dp, "f")
res
#[[1]]
#[1] "f" "d" "b"

#[[2]]
#[1] "f" "d" "c" "a"

#[[3]]
#[1] "f" "e" "b"

#[[4]]
#[1] "f" "e" "c" "a"

您需要通过递归或while循环以类似的方式实现它。