2011-01-14 29 views
13

पर अभिव्यक्ति उत्तीर्ण करना आर मूल्यांकन के रहस्यों में आगे बढ़ रहा है ... यह मेरे पिछले प्रश्न (How to write an R function that evaluates an expression within a data-frame) से निकटता से संबंधित है। मान लीजिए कि मैं एक फ़ंक्शन topfn लिखना चाहता हूं जो डेटा-फ्रेम और उस डेटा-फ्रेम के कॉलम-नामों वाली अभिव्यक्ति लेता है। मैं इन दोनों तर्कों को किसी अन्य फ़ंक्शन fn पर पास करना चाहता हूं जो वास्तव में डेटा-फ्रेम के "पर्यावरण" के भीतर अभिव्यक्ति का मूल्यांकन करता है। और मैं के रूप में ऊपर सवाल का जवाब में सुझाव दोनों fn और topfn सही ढंग से काम करने के लिए जब एक डेटा फ्रेम और एक अभिव्यक्तिआर: एक आंतरिक फ़ंक्शन

मेरा पहला प्रयास पारित कर दिया, चाहते हैं, परिभाषित करने के लिए है:

fn <- function(dfr, expr) { 
    mf <- match.call() 
    eval(mf$expr, envir = dfr) 
} 

और topfn इस तरह परिभाषित करते हैं:

topfn <- function(df, ex) { 
    mf <- match.call() 
    fn(df, mf$ex) 
} 
अब

अगर मैं एक डेटा फ्रेम

है 210
df <- data.frame(a = 1:5, b = 1:5) 

भीतरी समारोह fn ठीक काम करता है:

> fn(df,a) 
[1] 1 2 3 4 5 

लेकिन topfn काम नहीं करता:

> topfn(df,a) 
mf$ex 

इसे ठीक करने के मैं पहली बार topfn(df,a) के वर्ग की जाँच करें,

> class(topfn(df,a)) 
[1] "call" 

यह मुझेको फिर से परिभाषित करने के लिए एक बदसूरत हैक के लिए एक विचार देता हैइस प्रकार है:

fn <- function(dfr, expr) { 
    mf <- match.call() 
    res <- eval(mf$expr, envir = dfr) 
    if(class(res) == 'call') 
    eval(expr, envir = dfr) else 
    res 
} 

और अब दोनों फ़ंक्शन कार्य:

> fn(df,a) 
[1] 1 2 3 4 5 
> topfn(df,a) 
[1] 1 2 3 4 5 

जैसा कि मैंने कहा, यह एक बदसूरत हैक तरह दिखता है। क्या यह काम करने के लिए एक बेहतर तरीका (या अधिक मानक मुहावरे) है? मैंने लुमली के उत्सुकता से नामित मानक गैर-मानक मूल्यांकन नियम दस्तावेज़ http://developer.r-project.org/nonstandard-eval.pdf से परामर्श लिया है लेकिन इसे पढ़ने के बाद विशेष रूप से प्रबुद्ध नहीं किया गया था। उदाहरण के लिए देखे जा सकने वाले कार्यों के स्रोत-कोड के लिए कोई भी संकेतक भी उपयोगी होगा।

+0

हैडली विकहैम द्वारा आर मूल्यांकन के विषय यहाँ पर एक बड़ा विकी है:

यह काम करने के लिए लगता है: //github.com/hadley/devtools/wiki/Evaluation –

+1

और जैसा कि मैंने सुझाव दिया है कि आप उन कार्यों के बीच ध्यान से अंतर करना चाहते हैं जो इंटरैक्टिव रूप से उपयोग किए जाते हैं, और कार्य करते हैं अन्य कार्यों से बुलाया जाता है। विकल्प और अन्य चाल का उपयोग करने वाले किसी भी फ़ंक्शन को कॉल करना बहुत मुश्किल है। दूसरे शब्दों में, समान प्रकार के इनपुट के साथ काम करने के लिए 'fn' और 'topfn' दोनों के लिए कोई साफ तरीका नहीं है - और यह एक अच्छी बात है। – hadley

+1

@ हैडली मैं आपका बिंदु देखता हूं: इंटरैक्टिव उपयोग के लिए डिज़ाइन किए गए फ़ंक्शंस कंसोल (यानी कोई उद्धरण, आदि) में टाइप करना आसान बनाने के लिए विकल्प/अन्य चाल का उपयोग कर सकते हैं। और फ़ंक्शंस जिन्हें केवल अन्य कार्यों द्वारा बुलाया जाने वाला डिज़ाइन किया जाना चाहिए, ऐसी चाल का उपयोग नहीं करना चाहिए क्योंकि वे अप्रत्याशित रूप से तोड़ सकते हैं। विशेष रूप से, आपके उत्तर के अंत में @ रिची द्वारा प्रदान किया गया समाधान, भले ही यह मेरे विशेष परिदृश्य में काम करता है - यह किसी अन्य परिदृश्य में उपयोग किए जाने पर (विशेष रूप से 'एफएन') तोड़ सकता है - मुझे लगता है कि यह है कि आप' फिर कह रहा है, है ना? –

उत्तर

14

यह सबसे आसानी से भाव के बजाय topfn में गुजर तार से बचा जाता है।

topfn <- function(df, ex_txt) 
{ 
    fn(df, ex_txt) 
} 

fn <- function(dfr, expr_txt) 
{   
    eval(parse(text = expr_txt), dfr) 
} 

df <- data.frame(a = 1:5, b = 1:5) 
fn(df, "a")        
fn(df, "2 * a + b") 
topfn(df, "a")    
topfn(df, "2 * a + b") 

संपादित करें:

आप में उपयोगकर्ता पास भाव दे सकता है, लेकिन आपकी सुविधा के लिए नीचे तार का उपयोग करें।

बदलें topfn को

topfn <- function(df, ex) 
{ 
    ex_txt <- deparse(substitute(ex)) 
    fn(df, ex_txt) 
} 
topfn(df, a)    
topfn(df, 2 * a + b) 

किसी अन्य संपादन का: https:

topfn <- function(df, ex) 
{ 
    eval(substitute(fn(df, ex))) 
} 

fn <- function(dfr, expr) 
{   
    eval(substitute(expr), dfr) 
} 
fn(df, a)        
fn(df, 2 * a + b) 
topfn(df, a)    
topfn(df, 2 * a + b) 
+0

@richie: धन्यवाद, हाँ, लेकिन मैं तारों को पार करने से बचने के लिए एक रास्ता तलाश रहा था। मैं चाहता हूं कि कार्य आर में इतने सारे अन्य कार्यों की तरह काम करें जो गैर-उद्धृत अभिव्यक्तियों को तर्क के रूप में लेते हैं। –

+0

'fn' के तीसरे (जाली-शैली) विनिर्देश के लिए पिछले प्रश्न का मेरा उत्तर देखें। http://stackoverflow.com/questions/4682709/how-to-write-an-r-function-that-evaluates-an-expression-within-a-data-frame –

+0

@ रिची हाँ मैंने देखा कि, धन्यवाद, यह है वास्तव में आंतरिक कार्य के लिए काम करने के लिए सबसे आसान तरीका है, लेकिन उपरोक्त घोंसला वाले मामले में इसे अपनाना उतना ही समस्याग्रस्त है। –

1

आप तर्क इकट्ठा करने और उन्हें किसी अन्य समारोह में पास करने के लिए तीन बिंदुओं का उपयोग कर सकते हैं, क्या आपका मतलब है?

ftop=function(...) f(...) 
f=function(a,b) a[b] 

a=data.frame(b=10) 

ftop(a,"b") 

f(a,"b") 
+0

काफी नहीं है। मैं बिंदुओं का उपयोग नहीं करना चाहता, मैं चाहता हूं कि स्पष्ट तर्क आंतरिक कार्य में पारित किए जाएं। –

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