2015-02-22 16 views
6

मैं वास्तविक पुस्तकालयोंdplyr :: mutate_each के साथ नेमस्पेस्ड फ़ंक्शन का उपयोग कैसे करें?

dplyr::tbl_df(iris) %>% 
    dplyr::mutate_each(dplyr::funs(stringi::stri_trim_both)) 

संलग्न बिना कुछ बाहरी कार्यों के साथ dplyr::mutate_each उपयोग करने के लिए कोशिश कर रहा हूँ, लेकिन यह निम्न त्रुटि के साथ विफल:

Error: unsupported type for column 'Sepal.Length' (CLOSXP, classes = function)

जब मैं data.tabledata.frame के बजाय का उपयोग करें:

Error in `[.data.table`(`_dt`, , `:=`(Sepal.Length, stringi::stri_trim_both), : RHS of assignment is not NULL, not an an atomic vector (see ?is.atomic) and not a list column.

यदि मैं स्थानीय वैरिएबल का उपयोग करता हूं तो नीचे की तरह काम करता है।

trim_both <- stringi::stri_trim_both 
dplyr::tbl_df(iris) %>% dplyr::mutate_each(dplyr::funs(trim_both)) 

यह एक इष्टतम समाधान नहीं है लेकिन मैं इसके साथ रह सकता हूं। फिर भी मैं एक स्पष्टीकरण के लिए आभारी हूं कि समस्या का स्रोत क्या है।

सत्र जानकारी:

R version 3.1.1 (2014-07-10) 
Platform: x86_64-pc-linux-gnu (64-bit) 

locale: 
[1] LC_CTYPE=en_US.UTF-8  LC_NUMERIC=C    
[3] LC_TIME=en_US.UTF-8  LC_COLLATE=en_US.UTF-8  
[5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 
[7] LC_PAPER=en_US.UTF-8  LC_NAME=C     
[9] LC_ADDRESS=C    LC_TELEPHONE=C    
[11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C  

attached base packages: 
[1] stats  graphics grDevices utils  datasets methods base  

other attached packages: 
[1] dplyr_0.4.1 

loaded via a namespace (and not attached): 
[1] assertthat_0.1  DBI_0.3.1   lazyeval_0.1.10.9000 
[4] magrittr_1.5   parallel_3.1.1  Rcpp_0.11.4   
[7] stringi_0.4-1  tools_3.1.1   

नोट: यह समस्या नहीं रह गया है dplyr 0.7.2 में होता है।

उत्तर

7

अंतर्निहित कारण यह है कि dplyr::funs_dplyr:::make_call पर कॉल करता है। और dplyr:::make_calllazyeval::lazy_dots द्वारा उत्पन्न ऑब्जेक्ट के class का उपयोग कर मामलों के बीच अंतर करता है।

class(lazyeval::lazy_dots(trim_both)[[1]]$expr) 
## "name" 
class(lazyeval::lazy_dots(stringi::stri_trim_both)[[1]]$expr) 
## "call" 

इस समाधान के लिए नीचे my_funs फ़ंक्शन देखें। मैंने किसी भी विवरण में इसका परीक्षण नहीं किया है और मुझे यकीन है कि dplyr में यह अलग था, इसलिए इसे डिफ़ॉल्ट के रूप में उपयोग न करें। यह ज्यादातर समस्या को स्पष्ट करने के लिए है

# calling my_funs_ (instead of funs_) 
my_funs <- function (...) 
    my_funs_(lazyeval::lazy_dots(...)) 

my_funs_ <- function(dots){ 
    dots <- lazyeval::as.lazy_dots(dots) 
    env <- lazyeval::common_env(dots) 
    names(dots) <- dplyr:::names2(dots) 
    # difference here 
    dots[] <- lapply(dots, function(x) { 
    if (is.character(x$expr)) { 
     x$expr <- substitute(f(.), list(f = as.name(x$expr))) 
    } 
    else if (is.name(x$expr)) { 
     x$expr <- substitute(f(.), list(f = x$expr)) 
    } 
    else if (is.call(x$expr)) { 
     x$expr <- substitute(f(.), list(f = x$expr)) #### this line was different 
     # originally x$expr <- x$expr 
    } 
    else { 
     stop("Unknown inputs") 
    } 
    x 
    }) 
    missing_names <- names(dots) == "" 
    ### this is also different 
    default_names <- vapply(dots[missing_names], function(x) as.character(x)[1], 
          character(1)) 
    ## originally dplyr:::make_name(x) instead of as.character(x)[1] 
    names(dots)[missing_names] <- default_names 
    class(dots) <- c("fun_list", "lazy_dots") 
    dots 
} 

dplyr::tbl_df(iris) %>% 
    dplyr::mutate_each(my_funs(stringi::stri_trim_both)) 
संबंधित मुद्दे