2017-10-06 70 views
0

我想在數據框中的多個列上應用多個函數。我已經研究過如何將一個函數應用於數據框架中的所有列,但我很難嘗試使用invoke_map來應用函數列表。我已經玩弄了現有和enquo,但我沒有正確的組合(或者還沒有把握,我猜)。r map_df to invoke_map translation

玩具例如設置:

library(tidyverse) 
library(RcppRoll) 
library(purrr) 

ID <- letters[1:26] 
var1 <- sample(1:100, 26, replace= T) 
var2 <- sample(100:200, 26, replace= T) 
temp <- cbind(ID, var1, var2) %>% data.frame() 

這個工程申請一個功能:

roll.var <- function(name) { 
    label <- enquo(name) 
    map_df(temp[, 2:3], ~ name(.x, 5, fill= NA)) %>% 
    rename_all(funs(paste0(., '.', (!!label)))) %>% 
    cbind(temp, .) 
} 

test <- roll.var(roll_sdr) 

這是我嘗試使用invoke_map到的功能列表應用到所選列:

roll.func <- c("roll_sdr", "roll_varr") 

invoke_map(roll.var, .x= roll.func) 

它返回:錯誤名稱(.x,51,填充= NA):找不到函數「名稱」

第二個問題是,在第一個示例的結果'測試'數據框中,第一個變量被錯誤命名(var1。〜),而第二個命名是我預期的(var2.roll_sdr),可以任何有人告訴我爲什麼?

任何解決方案和/或教育將不勝感激!

編輯:

納入麥克的解釋,即invoke_map需要列出清單的完整代碼產生我想要的是:

library(tidyverse) 
library(purrr) 
library(RcppRoll) 
library(plyr) 

options(stringsAsFactors= F) 

ID <- letters[1:26] %>% data.frame(ID= .) 
var1 <- sample(1:100, 26, replace= T) %>% data.frame(var1= .) 
var2 <- sample(100:200, 26, replace= T) %>% data.frame(var2= .) 
temp <- bind_cols(ID, var1, var2) 


roll.func <- list(list(roll_sdr, 'roll_sdr'), 
        list(roll_varr, 'roll_varr')) 

roll.var <- function(name, vname) { 
    map_df(temp[, 2:3], ~ name(.x, 5, fill= NA)) %>% 
    rename_all(funs(paste0(., '.', vname))) %>% 
    cbind(temp, .) 
} 

df <- invoke_map(roll.var, roll.func) 
## plyr statrment works much faster than purrr:reduce 
df2 <- join_all(df, by= c('ID', 'var1', 'var2')) 

是否有可能在roll.var功能添加一條語句這樣vname不必在roll.func中重複使用?不知何故在函數內引用名稱?我玩過enquo和rlang包,我沒有提出正確的組合。

roll.func <- list(list(roll_sdr), 
        list(roll_varr)) 

既可以作爲函數調用,也可以將標籤附加到變量名稱。

回答

1

這有兩個問題。

第一個問題是與構造map_df(temp[, 2:3], ~ name(.x, 5, fill= NA)) - 這不起作用,因爲它不知道什麼name是指什麼。在這些類型的案例中,你會發現只需傳遞函數對象,而不是函數的名稱 - 也就是說,不要將它放在引號中。

第二個問題是您的構造roll.func不正確。仔細閱讀invoke_map的文檔 - 該參數必須是列表。列表中的每個元素必須是一個列表,其元素將作爲參數傳遞給函數。所以,這個簡單的例子工程:

library(purrr) 

var1 <- sample(1:100, 26, replace= T) %>% as.numeric 
var2 <- sample(100:200, 26, replace= T) %>% as.numeric 
temp <- cbind(var1, var2) %>% data.frame() 

simple_example <- function(func) map(temp, func) 

roll.func <- list(
    list(mean), 
    list(sum) 
) 

invoke_map(simple_example, roll.func) 
#> [[1]] 
#> [[1]]$var1 
#> [1] 53.42308 
#> 
#> [[1]]$var2 
#> [1] 140.6154 
#> 
#> 
#> [[2]] 
#> [[2]]$var1 
#> [1] 1389 
#> 
#> [[2]]$var2 
#> [1] 3656 

,你應該能夠適應,這樣做你所需要的。

+0

謝謝,我肯定錯過了列表必須傳遞給invoke_map函數。儘管如此,我仍然對命名功能有問題。現在,它通過將標籤作爲參數添加到該函數來解決(即,列表(列表(roll_sdr,'roll_sdr'), 列表(roll_varr,'roll_varr')) – RoseS

+0

您可以更具體地瞭解您要完成的任務嗎?您想要將N個函數應用於數據幀的所有列,並返回N個數據幀或一個數據幀? –

+0

現在通過將清單列表傳遞給它很好。命名部分只是一個很好的獎勵。我在原帖的末尾添加了一個編輯來反映這一點。 – RoseS