提问人:akshay bholee 提问时间:10/25/2023 最后编辑:ismirsehregalakshay bholee 更新时间:10/27/2023 访问量:51
根据需要将 R 数据帧转换为嵌套列表
Convert the R dataframe to the nested list as required
问:
我有一个数据帧,如下所示:
df <- data.frame(
all = c("All product","All product","All product","All product","All product","All product","All product","All product",
"All product","All product","All product","All product","All product","All product","All product","All product"),
category = c("Agriculture","Agriculture","Agriculture","Agriculture", "Agriculture","Agriculture","Agriculture","Agriculture",
"Non Agriculture", "Non Agriculture", "Non Agriculture", "Non Agriculture","Non Agriculture", "Non Agriculture", "Non Agriculture", "Non Agriculture"),
HS2 = c("01","01","01","01","02","02","02","02","03","03","03","03","04","04","04","04"),
HS4 = c("0101","0101","0102","0102","0201","0201","0202","0202","0301","0301","0302","0302","0401","0401","0402","0402"),
HS6 = c("010101","010102", "010201","010202","020101","020102","020201","020202","030101","030102", "030201","030202","040101","040102","040201","040202")
)
我希望能够在嵌套列表中转换此数据帧,如下所示:
nodes <- list(
list(
text = "All product",
type = "root",
children = list(
list(
text = "Agriculture",
type = "child",
children= list(
list(
text = "01",
type = "child",
children= list(
list(
text = "0101",
type = "child",
children= list(
list(
text = "010101",
type = "child"
),
list(
text = "010102",
type = "child"
)
)
),
list(
text = "0102",
type = "child",
children= list(
list(
text = "010201",
type = "child"
),
list(
text = "010202",
type = "child"
)
)
)
)
),
list(
text = "02",
type = "child",
children= list(
list(
text = "0201",
type = "child",
children= list(
list(
text = "020101",
type = "child"
),
list(
text = "020102",
type = "child"
)
)
),
list(
text = "0202",
type = "child",
children= list(
list(
text = "020201",
type = "child"
),
list(
text = "020202",
type = "child"
)
)
)
)
)
)
),
list(
text = "Non Agriculture",
type = "child",
children= list(
list(
text = "03",
type = "child",
children= list(
list(
text = "0301",
type = "child",
children= list(
list(
text = "030101",
type = "child"
),
list(
text = "030102",
type = "child"
)
)
),
list(
text = "0302",
type = "child",
children= list(
list(
text = "030201",
type = "child"
),
list(
text = "030202",
type = "child"
)
)
)
)
),
list(
text = "04",
type = "child",
children= list(
list(
text = "0401",
type = "child",
children= list(
list(
text = "040101",
type = "child"
),
list(
text = "040102",
type = "child"
)
)
),
list(
text = "0402",
type = "child",
children= list(
list(
text = "040201",
type = "child"
),
list(
text = "040202",
type = "child"
)
)
)
)
)
)
)
)
)
)
我已经手动编写了列表。但是,我的情况是,如上所述,我将有一个数据帧,并且数据帧数据可以随时更改,但结构不会更改。如何将数据帧转换为我共享的嵌套列表。
答:
4赞
Stéphane Laurent
10/25/2023
#1
这是一种方法。我从 jsTreeR 包中给出的示例中获取了该函数。makeNodes
# make the nodes list from a vector of file paths
makeNodes <- function(leaves){
dfs <- lapply(strsplit(leaves, "/"), function(s){
item <-
Reduce(function(a,b) paste0(a,"/",b), s[-1], s[1], accumulate = TRUE)
data.frame(
item = item,
parent = c("root", item[-length(item)]),
stringsAsFactors = FALSE
)
})
dat <- dfs[[1]]
for(i in 2:length(dfs)){
dat <- merge(dat, dfs[[i]], all = TRUE)
}
f <- function(parent){
i <- match(parent, dat$item)
item <- dat$item[i]
children <- dat$item[dat$parent==item]
label <- tail(strsplit(item, "/")[[1]], 1)
if(length(children)){
list(
text = label,
type = "child",
children = lapply(children, f)
)
}else{
list(text = label, type = "child")
}
}
lapply(dat$item[dat$parent == "root"], f)
}
# the dataframe
df <- data.frame(
all = c("All product","All product","All product","All product","All product","All product","All product","All product",
"All product","All product","All product","All product","All product","All product","All product","All product"),
category = c("Agriculture","Agriculture","Agriculture","Agriculture", "Agriculture","Agriculture","Agriculture","Agriculture",
"Non Agriculture", "Non Agriculture", "Non Agriculture", "Non Agriculture","Non Agriculture", "Non Agriculture", "Non Agriculture", "Non Agriculture"),
HS2 = c("01","01","01","01","02","02","02","02","03","03","03","03","04","04","04","04"),
HS4 = c("0101","0101","0102","0102","0201","0201","0202","0202","0301","0301","0302","0302","0401","0401","0402","0402"),
HS6 = c("010101","010102", "010201","010202","020101","020102","020201","020202","030101","030102", "030201","030202","040101","040102","040201","040202")
)
# transform it to a vector of paths
paths <- apply(df, 1, function(x) paste0(x, collapse = "/"))
# make the nodes list
nodes <- makeNodes(paths)
# we just have to replace 'type="child"' with 'type="root"' at the root
nodes[[1]]$type <- "root"
# let's visualize the result as JSON
jsonlite::toJSON(nodes, auto_unbox = TRUE, pretty = TRUE)
# [
# {
# "text": "All product",
# "type": "root",
# "children": [
# {
# "text": "Agriculture",
# "type": "child",
# "children": [
# {
# "text": "01",
# "type": "child",
# "children": [
# {
# "text": "0101",
# "type": "child",
# "children": [
# {
# "text": "010101",
# "type": "child"
# },
# {
# "text": "010102",
# "type": "child"
# }
# ]
# },
# {
# "text": "0102",
# "type": "child",
# "children": [
# {
# "text": "010201",
# "type": "child"
# },
# {
# "text": "010202",
# "type": "child"
# }
# ]
# }
# ]
# },
# {
# "text": "02",
# "type": "child",
# "children": [
# {
# "text": "0201",
# "type": "child",
# "children": [
# {
# "text": "020101",
# "type": "child"
# },
# {
# "text": "020102",
# "type": "child"
# }
# ]
# },
# {
# "text": "0202",
# "type": "child",
# "children": [
# {
# "text": "020201",
# "type": "child"
# },
# {
# "text": "020202",
# "type": "child"
# }
# ]
# }
# ]
# }
# ]
# },
# {
# "text": "Non Agriculture",
# "type": "child",
# "children": [
# {
# "text": "03",
# "type": "child",
# "children": [
# {
# "text": "0301",
# "type": "child",
# "children": [
# {
# "text": "030101",
# "type": "child"
# },
# {
# "text": "030102",
# "type": "child"
# }
# ]
# },
# {
# "text": "0302",
# "type": "child",
# "children": [
# {
# "text": "030201",
# "type": "child"
# },
# {
# "text": "030202",
# "type": "child"
# }
# ]
# }
# ]
# },
# {
# "text": "04",
# "type": "child",
# "children": [
# {
# "text": "0401",
# "type": "child",
# "children": [
# {
# "text": "040101",
# "type": "child"
# },
# {
# "text": "040102",
# "type": "child"
# }
# ]
# },
# {
# "text": "0402",
# "type": "child",
# "children": [
# {
# "text": "040201",
# "type": "child"
# },
# {
# "text": "040202",
# "type": "child"
# }
# ]
# }
# ]
# }
# ]
# }
# ]
# }
# ]
评论
0赞
akshay bholee
10/25/2023
非常感谢。我已经试过了,效果很好。我刚刚在列表中添加了icon = FALSE,因为我不需要图标。还有一件事确实,我正在将其用于jstree本身。如何根据所选内容从最后一个子项中检索所有文本值,以便可以使用它们来筛选其他数据帧?
0赞
Stéphane Laurent
10/25/2023
@akshaybholee 包中可能有一个示例。看。jsTreeExamples()
0赞
akshay bholee
10/25/2023
看不到任何示例,显示如何根据 jstree 中的选定节点过滤 DataFrame。
0赞
Stéphane Laurent
10/25/2023
@akshaybholee 如果您愿意,请提出一个新问题
1赞
ismirsehregal
10/27/2023
我认为在{jsTreeR}中导出函数会很有用。makeNodes()
评论