2017-11-20 7 views
0

R data.frameのすべての非数値列にtidyr :: completeを適用する関数を作成したいとします。値のゼロは新しい値の行に挿入する必要があります。これには標準の評価ソリューションが必要だと私は理解していますが、これまでのところ成功していません。ここでtidyr :: completeの標準的な評価 - すべての非数値列によって完了する関数

は、私がこれまで持っているものです。

completeDf <- function(df){ 

     vars <- names(df) 

     chVars <- vars[!(sapply(df, is.numeric))] 
     nmVars <- vars[!(vars %in% chVars)] 

     quoChVars <- quos(chVars) 

     nmList <- vector("list", length(nmVars)) 
     nmList <- setNames(lapply(nmList, function(x) x <- 0), nmVars) 
     quoNmVars <- quos(nmList) 

     df <- df %>% 
      complete(!!!quoChVars, fill = !!!quoNmVars) 
} 

この作業を行う方法の任意のアイデア?

答えて

2

1)rlang/tidyreval!!!syms(notnum_names)を使用して、変数名をcomplete引数として挿入します。 Fillは単なる普通のリストであり、それに対してrlang/tidyeval計算は必要ありません。与え

library(dplyr) 
library(tidyr) 
library(rlang) 

completeDF <- function(data) { 
    is_num <- sapply(data, is.numeric) 
    num_names <- names(data)[ is_num ] 
    notnum_names <- names(data)[ !is_num ] 
    fill <- Map(function(x) 0, num_names) 
    data %>% complete(!!!syms(notnum_names), fill = fill) 
} 

DF <- data.frame(a = c("A", "B", "B"), b = c("a", "a", "b"), c = 1:3) # test data 
completeDF(DF) 

# A tibble: 4 x 3 
     a  b  c 
    <fctr> <fctr> <dbl> 
1  A  a  1 
2  A  b  0 
3  B  a  2 
4  B  b  3 

をここではそれを動作させるために修正質問から元のコードです。変更された行には、##の末尾に印がついています。 wrapr

completeDf <- function(df){ 

     vars <- names(df) 

     chVars <- vars[!(sapply(df, is.numeric))] 
     nmVars <- vars[!(vars %in% chVars)] 

     symsChVars <- rlang::syms(chVars) ## 

     nmList <- vector("list", length(nmVars)) 
     nmList <- setNames(lapply(nmList, function(x) 0), nmVars) ## 
     # quoNmVars <- quos(nmList ## 

     df %>% ## 
      complete(!!!symsChVars, fill = nmList) ## 
} 

completeDf(DF) 

2)/ tidyevalをrlangする代替wraprパッケージです。

ここでのコードは、私たちが代わりにlibrary(rlang)library(wrapr)を使用してcompleteDFの最後の行がcompleteDF2を与えるletの文に置き換えられ除いて(1)と同じです。

library(dplyr) 
library(tidyr) 
library(wrapr) 

completeDF2 <- function(data) { 
    is_num <- sapply(data, is.numeric) 
    num_names <- names(data)[ is_num ] 
    notnum_names <- names(data)[ !is_num ] 
    fill <- Map(function(x) 0, num_names) 
    let(c(NOTNUM = toString(notnum_names)), 
     data %>% complete(NOTNUM, fill = fill), 
     strict = FALSE, 
     subsMethod = "stringsubs") 
} 

completeDF2(DF) 

アップデート:修正と改善。 wraprアプローチを追加してください。

関連する問題