2017-08-30 45 views
1

我喜歡dplyr中的bind_rows函數,但我發現它很煩人,當通過.id參數時,它只能在新列中添加一個數字索引。在R中訪問對象名稱和綁定

我正在嘗試寫一個bind_rows_named函數,但我被卡住訪問對象名稱。這符合預期:

bind_name_to_df <- function(df){ 
    dfname <- deparse(substitute(df)) 
    df %>% mutate(label=dfname) 
} 

a <- data_frame(stuff=1:10) 
bind_name_to_df(a) 

但我不能解決如何將它應用到數據框的列表,例如,使用。點。我這工作,但我知道我有...錯誤的語義莫名其妙。任何人都可以放光?

b <- data_frame(stuff=1:10) 

bind_rows_named <- function(...){ 
    return(
    bind_rows(lapply(..., bind_name_to_df))) 
} 

bind_rows_named(a, b) 
+2

在其他上下文中,我使用了便捷函數「Hmisc :: llist」,它與「list」類似,只是它保留了名稱或標籤變量'label'屬性中的組件變量。「因此,在這裏它會是'bind_rows(Hmisc :: llist(a,b),.id =「label」)' – Henrik

+1

在這裏只找到了一些其他很好的'base'選項:[可以根據輸入創建自己的名字對象名稱?](https://stackoverflow.com/questions/16951080/can-lists-be-created-that-name-themselves-based-on-input-object-names) – Henrik

+1

來自'.id'的標籤是隻有當你不給'bind_rows'命名參數時纔是整數。請參閱'bind_rows(a = a,.id =「label」)'。當你有一個命名列表時,它可以很好地工作,這使得'Hmisc :: llist'可以方便地創建一個列表。 – aosmith

回答

1

下面是使用一種選擇base R

bind_named <- function(...){ 
    v1 <- sapply(match.call()[-1], deparse) 
    dfs <- list(...) 
    Map(cbind, dfs, label = v1) 

    } 

bind_named(a, b) 
#[1]] 
# stuff label 
#1  1  a 
#2  2  a 
#3  3  a 
#4  4  a 
#5  5  a 
#6  6  a 
#7  7  a 
#8  8  a 
#9  9  a 
#10 10  a 

#[[2]] 
# stuff label 
#1  1  b 
#2  2  b 
#3  3  b 
#4  4  b 
#5  5  b 
#6  6  b 
#7  7  b 
#8  8  b 
#9  9  b 
#10 10  b 

或者用tidyverse

library(tidyverse) 
bind_named <- function(...) { 
nm1 <- quos(...) %>% 
      map(quo_name) 
dfs <- list(...) 
dfs %>% 
    map2(nm1, ~mutate(., label = .y)) 
    } 

res <- bind_named(a, b) 
res %>% 
    map(head, 2) 
#[[1]] 
# stuff label 
#1  1  a 
#2  2  a 

#[[2]] 
# stuff label 
#1  1  b 
#2  2  b 

它也可以被製成一個單一的鏈

bind_named <- function(...) { 
    quos(...) %>% 
    map(quo_name) %>% 
    map2_df(list(...), ., ~mutate(.data = .x, label = .y)) 
    } 

bind_named(a, b) 
# A tibble: 20 x 2 
# stuff label 
# <int> <chr> 
# 1  1  a 
# 2  2  a 
# 3  3  a 
# 4  4  a 
# 5  5  a 
# 6  6  a 
# 7  7  a 
# 8  8  a 
# 9  9  a 
#10 10  a 
#11  1  b 
#12  2  b 
#13  3  b 
#14  4  b 
#15  5  b 
#16  6  b 
#17  7  b 
#18  8  b 
#19  9  b 
#20 10  b 

注意:最初,我們認爲OP想要在單獨的數據集上創建列並獲得list輸出。澄清之後,map2更改爲map2_df,它返回單個數據集

+1

@bjw好吧,我與你的函數中的'bind_rows'混淆了。我以爲你想創建一個專欄。如果您想要一個數據集,請將'map2'更改爲'map2_df'。 (如在最後一個功能改變) – akrun

相關問題