将关系数据转换为 R 中的分层列表
Turning relationship data into hierarchical list in R
这是我的第一个问题;所以,请温柔点。
我有一些数据的形式是:
library('networkD3')
Relationships<- data.frame(Parent=c("earth","earth","forest","forest","ocean","ocean","ocean","ocean"),
Child=c("ocean","forest","tree","sasquatch","fish","seaweed","mantis shrimp","sea monster"))
> Relationships
Parent Child
1 earth ocean
2 earth forest
3 forest tree
4 forest sasquatch
5 ocean fish
6 ocean seaweed
7 ocean mantis shrimp
8 ocean sea monster
本质上这是一个可用于制作网络地图的边列表:
net <- graph_from_data_frame(d = Relationships,
directed = T)
plot(net)
我想将其转换为可在下面的 diagonalNetwork
函数中使用的形式。
Hierarchical_list <- list(name = "earth",
children = list(list(name = "ocean",
children = list(list(name = "mantis shrimp"),
list(name = "fish"),
list(name = "sea monster"),
list(name = "seaweed")
)),
list(name = "forest",
children = list(list(name = "sasquatch"),
list(name = "tree")
))
))
diagonalNetwork(Hierarchical_list)
像这样:
当我尝试使用此循环生成列表时:
List_attempt <- list()
levels<- levels(factor(Relationships$Parent))
for(n in 1:length(levels)){
Children <- subset(Relationships, Relationships$Parent == levels[n], select = Child)
for(c in 1:length(Children)){
sublist <- as.list(Children)
List_attempt <- list(List_attempt, name = levels[n],children = sublist)
}
}
diagonalNetwork(List_attempt)
我收到这个错误:
Error in FUN(X[[i]], ...) :
'options' must be a fully named list, or have no names (NULL)
1) 是否有更好的方法为 diagonalNetwork
创建列表?
2) 失败;我如何修改我的循环以踢出正确结构的列表?
3) 我应该使用其他 function/package 吗?
感谢您能提供的任何帮助,我已经在这堵墙上撞了一段时间了。也欢迎就更好的方式提出有关 SO 的问题的反馈。
澄清:
在这里发现了一个类似的问题,。但是,它依赖于一种数据结构,其中根始终在第一列中,其子项在后续列中,而不是像这个问题中那样的边列表,这在 igraph 中很常用。
感谢@Symbolix 指出错误
受@MrFlick 评论的启发,建议从根开始并获得child 以递归地创建列表元素:) ...肯定可以进一步改进以增强对意外数据输入的鲁棒性
library(igraph)
library('networkD3')
Relationships<- data.frame(Parent=c("earth","earth","forest","forest","ocean","ocean","ocean","ocean"),
Child=c("ocean","forest","tree","sasquatch","fish","seaweed","mantis shrimp","sea monster"))
net <- graph_from_data_frame(d=Relationships, directed=T)
plot(net)
#net and Relationships as declared in question
#get root
root <- setdiff(Relationships$Parent, Relationships$Child)
#traverse next layer and then recurve
as.list.igraph <- function(thisNode) {
nm <- vertex_attr(net, "name", thisNode)
childNodes <- V(net)[which(shortest.paths(net, thisNode, mode="out") == 1)]
if (length(childNodes)==0) return(list(name=nm))
list(name=nm, children=unname(lapply(childNodes, as.list.igraph)))
}
#plot D3 network
diagonalNetwork(as.list.igraph(V(net)[root]))
顺便说一句,如果我没记错的话,igraph
中还有一个layout.reingold.tilford选项
您可以使用 data.tree 程序包,它可以开箱即用地进行分层数据之间的许多转换:
library('networkD3')
Relationships<- data.frame(Parent=c("earth","earth","forest","forest","ocean","ocean","ocean","ocean"),
Child=c("ocean","forest","tree","sasquatch","fish","seaweed","mantis shrimp","sea monster"))
library('data.tree')
tree <- FromDataFrameNetwork(Relationships)
tree
lol <- ToListExplicit(tree, unname = TRUE)
diagonalNetwork(lol)
这是我的第一个问题;所以,请温柔点。
我有一些数据的形式是:
library('networkD3')
Relationships<- data.frame(Parent=c("earth","earth","forest","forest","ocean","ocean","ocean","ocean"),
Child=c("ocean","forest","tree","sasquatch","fish","seaweed","mantis shrimp","sea monster"))
> Relationships
Parent Child
1 earth ocean
2 earth forest
3 forest tree
4 forest sasquatch
5 ocean fish
6 ocean seaweed
7 ocean mantis shrimp
8 ocean sea monster
本质上这是一个可用于制作网络地图的边列表:
net <- graph_from_data_frame(d = Relationships,
directed = T)
plot(net)
我想将其转换为可在下面的 diagonalNetwork
函数中使用的形式。
Hierarchical_list <- list(name = "earth",
children = list(list(name = "ocean",
children = list(list(name = "mantis shrimp"),
list(name = "fish"),
list(name = "sea monster"),
list(name = "seaweed")
)),
list(name = "forest",
children = list(list(name = "sasquatch"),
list(name = "tree")
))
))
diagonalNetwork(Hierarchical_list)
像这样:
当我尝试使用此循环生成列表时:
List_attempt <- list()
levels<- levels(factor(Relationships$Parent))
for(n in 1:length(levels)){
Children <- subset(Relationships, Relationships$Parent == levels[n], select = Child)
for(c in 1:length(Children)){
sublist <- as.list(Children)
List_attempt <- list(List_attempt, name = levels[n],children = sublist)
}
}
diagonalNetwork(List_attempt)
我收到这个错误:
Error in FUN(X[[i]], ...) :
'options' must be a fully named list, or have no names (NULL)
1) 是否有更好的方法为 diagonalNetwork
创建列表?
2) 失败;我如何修改我的循环以踢出正确结构的列表?
3) 我应该使用其他 function/package 吗?
感谢您能提供的任何帮助,我已经在这堵墙上撞了一段时间了。也欢迎就更好的方式提出有关 SO 的问题的反馈。
澄清:
在这里发现了一个类似的问题,
感谢@Symbolix 指出错误
受@MrFlick 评论的启发,建议从根开始并获得child 以递归地创建列表元素:) ...肯定可以进一步改进以增强对意外数据输入的鲁棒性
library(igraph)
library('networkD3')
Relationships<- data.frame(Parent=c("earth","earth","forest","forest","ocean","ocean","ocean","ocean"),
Child=c("ocean","forest","tree","sasquatch","fish","seaweed","mantis shrimp","sea monster"))
net <- graph_from_data_frame(d=Relationships, directed=T)
plot(net)
#net and Relationships as declared in question
#get root
root <- setdiff(Relationships$Parent, Relationships$Child)
#traverse next layer and then recurve
as.list.igraph <- function(thisNode) {
nm <- vertex_attr(net, "name", thisNode)
childNodes <- V(net)[which(shortest.paths(net, thisNode, mode="out") == 1)]
if (length(childNodes)==0) return(list(name=nm))
list(name=nm, children=unname(lapply(childNodes, as.list.igraph)))
}
#plot D3 network
diagonalNetwork(as.list.igraph(V(net)[root]))
顺便说一句,如果我没记错的话,igraph
中还有一个layout.reingold.tilford选项您可以使用 data.tree 程序包,它可以开箱即用地进行分层数据之间的许多转换:
library('networkD3')
Relationships<- data.frame(Parent=c("earth","earth","forest","forest","ocean","ocean","ocean","ocean"),
Child=c("ocean","forest","tree","sasquatch","fish","seaweed","mantis shrimp","sea monster"))
library('data.tree')
tree <- FromDataFrameNetwork(Relationships)
tree
lol <- ToListExplicit(tree, unname = TRUE)
diagonalNetwork(lol)