我有描述亲子关系的数据:
df <- tibble::tribble(
~Child, ~Parent,
"Fruit", "Food",
"Vegetable", "Food",
"Apple", "Fruit",
"Banana", "Fruit",
"Pear", "Fruit",
"Carrot", "Vegetable",
"Celery", "Vegetable",
"Bike", "Not Food",
"Car", "Not Food"
)
df
#> # A tibble: 9 x 2
#> Child Parent
#> <chr> <chr>
#> 1 Fruit Food
#> 2 Vegetable Food
#> 3 Apple Fruit
#> 4 Banana Fruit
#> 5 Pear Fruit
#> 6 Carrot Vegetable
#> 7 Celery Vegetable
#> 8 Bike Not Food
#> 9 Car Not Food
在视觉上,这看起来像:
最终,我想要的结果是将其“扁平化”为看起来更像这样的结构:
results <- tibble::tribble(
~Level.03, ~Level.02, ~Level.01,
"Apple", "Fruit", "Food",
"Banana", "Fruit", "Food",
"Pear", "Fruit", "Food",
NA, "Bike", "Not Food",
NA, "Car", "Not Food"
)
results
#> # A tibble: 5 x 3
#> Level.03 Level.02 Level.01
#> <chr> <chr> <chr>
#> 1 Apple Fruit Food
#> 2 Banana Fruit Food
#> 3 Pear Fruit Food
#> 4 <NA> Bike Not Food
#> 5 <NA> Car Not Food
注意:并非所有元素都具有所有级别。例如,bike
和 car
没有 Level.03
元素。
我觉得有一种方法可以使用 tidyr
或来自 jsonlite
的某种类型的 next/unnest
函数优雅地完成此操作?我从递归连接开始,但我觉得我正在重新发明轮子,而且可能有一种直接的方法。
最佳答案
这是一个带有 while 循环的函数:
fun <- function(s){
i <- 1
while(i<=length(s)){
if(any(s[[i]] %in% names(s)))
{
nms <- s[[i]]
s[[i]] <- stack(s[nms])
s[nms] <- NULL
}
else
s[[i]] <- data.frame(values = NA, ind = s[[i]])
i <- i+1
}
s
}
dplyr::bind_rows(fun(unstack(df)), .id = 'Level.01')[c(2:3,1)]
values ind Level.01
1 Apple Fruit Food
2 Banana Fruit Food
3 Pear Fruit Food
4 Carrot Vegetable Food
5 Celery Vegetable Food
6 <NA> Bike Not Food
7 <NA> Car Not Food
如果你有更多的层次,你可以概括这一点
关于r - 如何在给定 R 中的父子关系的情况下展平分层数据结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68897832/