我正在寻找一个遍及未知层次结构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)),]
但我不知道如何循环未知(和改变)我。
答案 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"))