2012-04-05 13 views
12

मैं फ़ंक्शन कॉल उत्पन्न करने के लिए 'do.call' का बहुत उपयोग करता हूं। E.g:do.call संयोजन में "::"

myfun <- "rnorm"; 
myargs <- list(n=10, mean=5); 
do.call(myfun, myargs); 

हालांकि, कभी-कभी मैं एक निश्चित पैकेज से स्पष्ट रूप से एक फ़ंक्शन को कॉल करना चाहता हूं। उदा। stats::rnorm(n=10, mean=5)

myfun <- "stats::rnorm"; 
myargs <- list(n=10, mean=5); 
do.call(myfun, myargs); 
+1

कैसे के बारे में 'do.call (आँकड़े :: rnorm, myargs)'? – kohske

+1

@kohske - तो ऐसा लगता है कि 'आँकड़े :: rnorm (n = 10, mean = 5)' यह भी आसान है :-) – Tommy

+1

लेकिन उस स्थिति में आप सूची का उपयोग अपने तर्क के रूप में नहीं कर सकते :-( – kohske

उत्तर

18

कोई समारोह "आँकड़े :: rnorm" कहा जाता है: वहाँ किसी भी तरह से मैं do.call उपयोग कर सकते हैं, या एक समारोह है कि सिर्फ do.call तरह बर्ताव करता है काम करने के लिए इसे पाने के लिए पैदा करते हैं। आप "आंकड़े" के नाम स्थान में rnorm समारोह को खोजने चाहिए:

myfun <- get("rnorm", asNamespace("stats")) 
myargs <- list(n=10, mean=5); 
do.call(myfun, myargs); 

अब आप निश्चित रूप से भी "आँकड़े :: rnorm" की तरह एक नाम से जा सकते हैं और यह नाम स्थान हिस्सा है और समारोह नाम में अलग अलग:

funname <- "stats::rnorm" 
fn <- strsplit(funname, "::")[[1]] 
myfun <- if (length(fn)==1) fn[[1]] else get(fn[[2]], asNamespace(fn[[1]])) 
myargs <- list(n=10, mean=5); 
do.call(myfun, myargs); 

अद्यतन मैं सिर्फ दिखाने के लिए कि इस दृष्टिकोण 2.5x तेजी @Jeroen से एक की तुलना में है चाहता था ...

do.call.tommy <- function(what, args, ...) { 
    if(is.character(what)){ 
    fn <- strsplit(what, "::")[[1]] 
    what <- if(length(fn)==1) { 
     get(fn[[1]], envir=parent.frame(), mode="function") 
    } else { 
     get(fn[[2]], envir=asNamespace(fn[[1]]), mode="function") 
    } 
    } 

    do.call(what, as.list(args), ...) 
} 

# Test it 
do.call.tommy(runif, 10) 
f1 <- function(FUN) do.call.tommy(FUN, list(5)) 
f2 <- function() { myfun<-function(x) x; do.call.tommy(myfun, list(5)) } 
f1(runif) 
f1("stats::runif") 
f2() 

# Test the performance...  
system.time(for(i in 1:1e4) do.call.jeroen("stats::runif", list(n=1, max=50))) # 1.07 secs 
system.time(for(i in 1:1e4) do.call.tommy("stats::runif", list(n=1, max=50))) # 0.42 secs 
11

आप उद्धरणों को हटा सकते हैं: यह अपने नाम के बजाए कार्य ही होगा।

myfun <- stats::rnorm 
myargs <- list(n=10, mean=5) 
do.call(myfun, myargs) 
0

प्रतिक्रियाओं के लिए धन्यवाद। मुझे लगता है कि मैं कुछ इस तरह के लिए जा रहा हूँ:

do.call.jeroen <- function(what, args, ...){ 
    if(is.function(what)){ 
    what <- deparse(as.list(match.call())$what); 
    } 
    myfuncall <- parse(text=what)[[1]]; 
    mycall <- as.call(c(list(myfuncall), args)); 
    eval(mycall, ...); 
} 

do.call का एक अच्छा सामान्यीकरण होने के लिए इतना है कि मैं अभी भी what तर्क के लिए एक चरित्र स्ट्रिंग पर पारित कर सकते हैं, फिर भी यह बड़े करीने से एक stats::rnorm(n=10, mean=5) कॉल emulates लगता है यही कारण है कि।

myfun1 <- "rnorm"; 
myfun2 <- "stats::rnorm"; 
myargs <- list(n=10, mean=5); 
do.call.jeroen(myfun1, myargs); 
do.call.jeroen(myfun2, myargs); 
do.call.jeroen(rnorm, myargs); 
do.call.jeroen(stats::rnorm, myargs); 

एक बात यह है कि इस बारे में अच्छा है यह है कि अगर समारोह है कि मैं का उपयोग करता है बोल रहा हूँ match.call() कहीं कॉल स्टोर करने के लिए, यह वास्तविक समारोह नाम भी सुरक्षित रहेंगे। उदाहरण के लिए:

do.call.jeroen ("आँकड़े :: GLM", सूची (सूत्र = गति ~ जिले, डेटा = as.name ('कार')))

Call: stats::glm(formula = speed ~ dist, data = cars) 

Coefficients: 
(Intercept)   dist 
    8.2839  0.1656 

Degrees of Freedom: 49 Total (i.e. Null); 48 Residual 
Null Deviance:  1370 
Residual Deviance: 478 AIC: 260.8 
+0

मुझे वास्तव में प्यार नहीं है तथ्य यह है कि आप इसे हल करने के लिए 'पर्स', 'पार्स' और 'eval' का सहारा लेते हैं। एक के लिए, यह' f <-function (x) do.call.jeroen (x, list (n = 10 को संभाल नहीं करता है))); एफ (runif) ', और यह' do.call' को कॉल करने के रूप में धीमी गति से दोगुनी है ... मैंने एक विकल्प के साथ अपना जवाब अपडेट किया। – Tommy

+0

धन्यवाद। मैंने अपनी प्रतिक्रिया को थोड़ा सा भी अपडेट किया। एक चीज जो मुझे पसंद है 'do.call.jeroen' के बारे में यह है कि मूल कार्य नाम इसे एक अज्ञात फ़ंक्शन के साथ बदलने के बजाय संरक्षित रहता है। – Jeroen

संबंधित मुद्दे