作者andrew43 (讨厌有好心推文後删文者)
看板R_Language
标题Re: [问题] data.frame依栏位顺序转成树状lists
时间Fri Nov 17 15:29:58 2017
不用刻轮子喔。这里简单地把你的例子用 package data.tree 解析。
library(data.tree)
library(data.table)
library(magrittr)
dt <- fread('A B C D
a1 b1 NA NA
a2 b2 cx1 NA
a2 b2 cx1 dxx
a2 b2 cx2 NA
a3 b3 cx3 dx1
a3 b3 cx3 dx2
a4 b4 cx4 dx3')
# append a column to describe terminals
dt[, pathString := paste("theRoot", A, B, C, D, sep = "/")]
# convert data frame to a tree
dt.tree <- as.Node(dt)
dt.tree
# levelName
# 1 theRoot
# 2 |--a1
# 3 | °--b1
# 4 | °--NA
# 5 | °--NA
# 6 |--a2
# 7 | °--b2
# 8 | |--cx1
# 9 | | |--NA
# 10 | | °--dxx
# 11 | °--cx2
# 12 | °--NA
# 13 |--a3
# 14 | °--b3
# 15 | °--cx3
# 16 | |--dx1
# 17 | °--dx2
# 18 °--a4
# 19 °--b4
# 20 °--cx4
# 21 °--dx3
plot(dt.tree)
# see
https://imgur.com/a/zja70
# convert tree to a list
dt.tree.list <- as.list(dt.tree$root)
dt.tree.list$a1
dt.tree.list$a1$b1
※ 引述《cywhale》之铭言:
: [问题叙述]:
: 想得到依栏位展开的树状结构list,且在leaf nodes 保留 names of leaf nodes
: 尝试了几次没有得到很好的结果,以下是最接近的方式,想请教~
: library(data.table)
: library(magrittr)
: dt <- fread('A B C D
: a1 b1 NA NA
: a2 b2 cx1 NA
: a2 b2 cx1 dxx
: a2 b2 cx2 NA
: a3 b3 cx3 dx1
: a3 b3 cx3 dx2
: a4 b4 cx4 dx3')
: out <- dt %>% split(.$A) %>%
: lapply(function(x)
: lapply(split(x, x$B), function(y)
: lapply(split(y, y$C), function(z) {
: sapply(z$D, function(u) {
: if (is.na(u)) return(names(u))
: list(u)})
: })))
: out
: #================以下输出结果
: $a1
: $a1$b1
: named list() #这是错的结果,想得到"b1"
: $a2
: $a2$b2
: $a2$b2$cx1
: $a2$b2$cx1$<NA> #这是错的结果 到$cx1 即停止
: NULL ##这是错的结果 ,想得到"cx1"
: $a2$b2$cx1$dxx
: $a2$b2$cx1$dxx[[1]]
: [1] "dxx" ##这是对的结果,留下name of leaf node
: $a2$b2$cx2
: $a2$b2$cx2$<NA> #这是错的结果 到$cx2 即停止
: NULL #这是错的结果 ,想得到"cx2"
: $a3
: $a3$b3
: $a3$b3$cx3
: $a3$b3$cx3$dx1
: [1] "dx1" ##这是对的结果
: $a3$b3$cx3$dx2
: [1] "dx2" ##这是对的结果
: $a4
: $a4$b4
: $a4$b4$cx4
: $a4$b4$cx4$dx3
: [1] "dx3" ##这是对的结果
: 如上结果,我想得到依栏位ABCD 展开的树状结构list,所以用了split
: 可以正确地依阶层顺序展开 ($A -> $B -> $C -> $D)
: 而且想在leaf nodes 保留 names of leaf nodes
: 比如 $a3$b3$cx3$dx1 [1] "dx1" 这是对的结果
: 但 像後面有NA 的node 在 split 时就会被抛弃,因此我得不到node名
: 我希望得到
: $a1$b1
: [1] "b1"
: $a2$b2$cx1
: [1] "cx1"
: $a2$b2$cx2
: [1] "cx2"
: 不知道有无解法?谢谢~~
: (附注,上面a1, b1, c1 字母和数字均为范例无意义,真实资料中为任意字串,请勿依数
: 字规则来当作程式一部分,仅是举例)
: ※ 编辑: cywhale (140.112.65.48), 11/17/2017 11:28:28
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 60.248.222.1
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/R_Language/M.1510903800.A.010.html
※ 编辑: andrew43 (60.248.222.1), 11/17/2017 15:30:58
1F:推 cywhale: 非常感谢,tree结构稍微修改pathString 可以拿掉NA ok~但 11/17 16:44
2F:推 cywhale: list它多了一层把names of node都留下来我想看看怎麽改.. 11/17 16:46
如果是这样呢?
library(data.tree)
library(data.table)
library(magrittr)
dt <- fread('A B C D
a1 b1 NA NA
a2 b2 cx1 NA
a2 b2 cx1 dxx
a2 b2 cx2 NA
a3 b3 cx3 dx1
a3 b3 cx3 dx2
a4 b4 cx4 dx3')
# append a column to describe structure
dt[,
pathString :=
paste("theRoot", A, B, C, D, sep = "/") %>%
gsub("/NA", "", .)]
# append a column to record terminal name
dt[, terminalName := strsplit(pathString, "/") %>%
sapply(., last)
]
# convert data frame to a tree and then convert to a list
dt.tree <- as.Node(dt)
as.list(dt.tree, keepOnly = "terminalName")
※ 编辑: andrew43 (60.248.222.1), 11/17/2017 19:13:56
3F:→ andrew43: 改了一下看看是不是符合需求? 11/17 19:14
※ 编辑: andrew43 (60.248.222.1), 11/17/2017 19:27:56
4F:→ andrew43: 现在还有留下 ...$terminalName,但乾净很多了,你再改 11/17 19:32
5F:推 cywhale: 原来keepOnly是这样用法!太感谢了! 11/17 22:28