我有一个有6行3列的数据集。第一列表示子项,而第二列表示相应子项的直接父项。
上面,人们可以看到" 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"}。
注意:节点的顺序无关紧要。
提前非常感谢你。
答案 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)
现在我不确定你想要什么,但是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
我们发现e
和f
无法访问,因此不是d
的祖先。 c
和b
是直接父母,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循环以类似的方式实现它。