2017-10-06 19 views
0

データフレーム内の複数の列に複数の機能を適用したいと考えています。データフレーム内のすべての列に1つの関数を適用する方法を検討しましたが、invoke_mapを使用して関数のリストを適用しようとするのは難しいです。私はquoとenquoで遊んだことがありますが、私は適切な組み合わせを持っていません(または、まだ把握しています)。r map_dfからinvoke_mapへの変換

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、fill = NA):関数 "name"が見つかりませんでした

第2の問題は、最初の例の結果の「テスト」データフレームで、最初の変数の名前が正しくない(var1。〜)一方、2番目の名前はどのように予想されたか(var2.roll_sdr) 1つはなぜ私に言う?

解決策や教育があれば幸いです。

EDIT: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

これには2つの問題があります。

最初の問題は、map_df(temp[, 2:3], ~ name(.x, 5, fill= NA))という構成にあります。これは、nameが何を参照しているのか分からないために機能しません。これらのタイプのケースでは、関数オブジェクトを渡すだけで、関数の名前ではなく、引用符で囲まないほうがはるかに簡単です。

2番目の問題は、構成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個のデータフレームまたは1つのデータフレームを返したいとしますか? –

+0

これは、リストのリストを渡すことですぐれています。命名部分はちょうど良いボーナスになるでしょう。これを反映するために元の投稿の最後に編集を追加しました。 – RoseS

関連する問題