遍历未知层次结构 R

Loop throughout unknown hierarchy R

我正在寻找贯穿未知层次结构 R 的循环(我只在请求时才知道数据)。例如 我请求最高层次结构并将它们放入数据框

id name
1  Books
2  DVDs
3  Computer

对于下一步,我想循环进入图书类别,因此,我使用 id(1) 发出新请求并获得:

id name
11 Child books
12 Fantasy 

现在我又想查看儿童书籍的下一个父类别,并为 id(11) 做一个新请求

id  name
111 Baby
112 Education
113 History 

以此类推:

id  name
1111 Sound
1112 Touch

此刻我不知道每个层次结构有多深,但我可以看出每个不同类别的层次结构是不同的。最后我希望数据框看起来像这样:

Id name      Id name          Id name       id name     id name
1  Books     11 Child books   111 Baby      1111 Sound  ...
1  Books     11 Child books   111 Baby      1112 Touch  ...
1  Books     11 Child books   112 Education etc.
1  Books     11 Child books   113 History   etc. 
1  Books     12 Fantasy       etc.
.................
2  DVDs      etc.
.................
3  Computer  etc.
.................

所以我可以提取下一个层次结构的行数并重复该行的次数。

  df[rep(x,each=nrow(df_next)),]

但我不知道如何遍历一个未知的(并且不断变化的)i。

这是一个不太优雅的解决方案:

(i) subFn是自定义函数,根据不同的长度拆分id

subFn <- function(id){
          len <- nchar(id)
          tmp <- lapply(1:len, function(x)substring(id, x, x))
          names(tmp) <- paste0("level_", 1:length(tmp))
          return(tmp)
         }    

## example
subFn("1111")
$level_1
[1] "1"

$level_2
[1] "1"

$level_3
[1] "1"

$level_4
[1] "1"

(ii) 创建一个data.frame的列表,其中id根据其长度分成不同数量的列:

dat_list <- lapply(list(df1, df2, df3), function(x) do.call(data.frame, c(list(name=x[, "name"], stringsAsFactors=FALSE), subFn(x[, "id"]))))

(iii) 使用 dplyr left_join 一次连接两个帧:

dat_list[[1]] %>% 
    left_join(dat_list[[2]], by="level_1") %>% 
    left_join(dat_list[[3]], by=c("level_1", "level_2"))

    name.x level_1      name.y level_2      name level_3
1    Books       1 Child books       1      Baby       1
2    Books       1 Child books       1 Education       2
3    Books       1 Child books       1   History       3
4    Books       1     Fantasy       2      <NA>    <NA>
5     DVDs       2        <NA>    <NA>      <NA>    <NA>
6 Computer       3        <NA>    <NA>      <NA>    <NA>

为了避免 left_join 多个 data.frame 过程中冗长复杂的步骤,这里有一个受

启发的解决方案
func <- function(...){
   df1 <- list(...)[[1]]
   df2 <- list(...)[[2]]
   col <- grep("level", names(df1), value=T)
   left_join(..., by = col)
  }

Reduce( func, dat_list)

输入数据:

df1 <- data.frame(id = 1:3, name = c("Books", "DVDs", "Computer"))
df2 <- data.frame(id = 11:12, name = c("Child books", "Fantasy"))
df3 <- data.frame(id = 111:113, name=c("Baby", "Education", "History"))