作者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://www.ptt.cc/bbs/R_Language/M.1510903800.A.010.html
※ 編輯: andrew43 (60.248.222.1), 11/17/2017 15:30:58
推 cywhale: 非常感謝,tree結構稍微修改pathString 可以拿掉NA ok~但 11/17 16:44
推 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
→ andrew43: 改了一下看看是不是符合需求? 11/17 19:14
※ 編輯: andrew43 (60.248.222.1), 11/17/2017 19:27:56
→ andrew43: 現在還有留下 ...$terminalName,但乾淨很多了,你再改 11/17 19:32
推 cywhale: 原來keepOnly是這樣用法!太感謝了! 11/17 22:28