循环遍及未知的层次结构R.

时间:2017-05-03 14:13:27

标签: r hierarchical-data

我正在寻找一个遍及未知层次结构R的循环(我只知道我请求时的数据)。例如 我请求最高层次并将它们放在数据帧中

id name
1  Books
2  DVDs
3  Computer

下一步我想循环进入图书类别,所以我用id(1)做了一个新的请求并得到:

id name
11 Child books
12 Fantasy 

现在我想再看一下Child book的下一个父类,并对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)),]

但我不知道如何循环未知(和改变)我。

1 个答案:

答案 0 :(得分:1)

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

(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_joining多个data.frame中的漫长而复杂的步骤,这里有一个受How to join multiple data frames using dplyr?

启发的解决方案
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"))