2017-05-03 65 views
1

我正在尋找遍及未知層次結構R的循環(我只在需要時才知道數據)。例如 我要求最高的等級與把它們放在一個數據幀在整個未知層次結構中循環R

id name 
1 Books 
2 DVDs 
3 Computer 

對於下一步我要循環到書籍類的話,我做了ID的新要求(1),並得到:

id name 
11 Child books 
12 Fantasy 

再現在我要考慮的兒童書籍下一個父產品類別和標識(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

這裏的一個不那麼完美的解決方案:

(ⅰ)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" 

(ⅱ)創建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加入噸WO在一個時間框架:

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"))