2013-02-12 48 views
18

पैकेज data.table में कुछ विशेष वाक्यविन्यास हैं जिनके लिए i और j तर्कों के रूप में अभिव्यक्तियों का उपयोग करने की आवश्यकता है।कोई फ़ंक्शन कैसे लिखें जो फ़ंक्शन को कॉल करता है जो डेटा.table को कॉल करता है?

इस पर कुछ प्रभाव पड़ता है कि कैसे एक लेख लिखता है जो डेटा टेबल पर तर्क स्वीकार करता है और पास करता है, जैसा कि section 1.16 of the FAQs में वास्तव में अच्छी तरह से समझाया गया है।

लेकिन मैं यह नहीं समझ सकता कि यह एक अतिरिक्त स्तर कैसे लेना है।

यहां एक उदाहरण है। ,

library(data.table) 


foo <- function(data, by){ 
    by <- substitute(by) 
    data[, .N, by=list(eval(by))] 
} 

DT <- data.table(mtcars) 
foo(DT, gear) 

ठीक है, यह काम करता है क्योंकि मैं अपने सारणीबद्ध परिणाम प्राप्त: मैं एक आवरण समारोह foo() कि मेरे डेटा का विशिष्ट सारांश बनाता है, और फिर एक दूसरे आवरण plotfoo() कि foo() कॉल करता है और परिणाम भूखंडों लिखना चाहते कहो :

by N 
1: 4 12 
2: 3 15 
3: 5 5 

अब, मैं जब plotfoo() लेखन सिर्फ एक ही करने की कोशिश, लेकिन मैं बुरी तरह असफल:

plotfoo <- function(data, by){ 
    by <- substitute(by) 
    foo(data, eval(by)) 
} 
plotfoo(DT, gear) 

लेकिन इस बार मैंने एक त्रुटि संदेश मिलता है:

Error: evaluation nested too deeply: infinite recursion/options(expressions=)? 

ठीक है, तो eval() एक समस्या खड़ी कर रहा है। के इसे हटाने करते हैं:

plotfoo <- function(data, by){ 
    by <- substitute(by) 
    foo(data, by) 
} 
plotfoo(DT, gear) 

एक नया त्रुटि संदेश अरे नहीं, मैं:

Error in `[.data.table`(data, , .N, by = list(eval(by))) : 
    column or expression 1 of 'by' or 'keyby' is type symbol. Do not quote column names. Useage: DT[,sum(colC),by=list(colA,month(colB))] 

और यहाँ है मैं कहाँ अटक रहते हैं।

प्रश्न: एक फ़ंक्शन कैसे लिखें जो डेटा.table को कॉल करने वाले फ़ंक्शन को कॉल करता है?

+0

नहीं एक समाधान है, लेकिन आप 'विकल्प को दूर करता है, तो (द्वारा) 'और' eval' और 'goo' को' चर (डीटी, "गियर") जैसे चरित्र चर के रूप में पास करें, फिर दोनों कार्य। – Arun

उत्तर

13

यह काम करेगा:

plotfoo <- function(data, by) { 
    by <- substitute(by) 
    do.call(foo, list(quote(data), by)) 
} 

plotfoo(DT, gear) 
# by N 
# 1: 4 12 
# 2: 3 15 
# 3: 5 5 

स्पष्टीकरण:

समस्या यह है कि है आपकेमें foo() पर कॉल करेंनिम्न में से एक की तरह लग रहा:

foo(data, eval(by)) 
foo(data, by) 

जब foo प्रक्रियाओं उन कॉल दूसरा औपचारिक तर्क (by) by के मूल्य प्रतीकों eval(by) या by के रूप में प्राप्त करने के लिए, यह कर्तव्यनिष्ठा substitute रों। लेकिन आप पर कॉल के रूप में by का मान gear मानना ​​चाहते हैं।

do.call() उस कॉल का निर्माण करने से पहले अपने दूसरे तर्क के तत्वों का मूल्यांकन करके इस समस्या को हल करता है जिसे उसके बाद मूल्यांकन किया जाता है। नतीजतन, जब आप इसे by पारित रूप में, यह एक फोन है कि (अनिवार्य) लग रहा है इस तरह के निर्माण से पहले अपने मूल्य (प्रतीक gear) करने के लिए इसे का मूल्यांकन करता है:

foo(data, gear) 
+0

बहुत अच्छी व्याख्या! धन्यवाद। – Arun

+0

+1 यह 'i' और' j' तर्कों को पारित करने के लिए मेरी निहित लेकिन अस्थिर आवश्यकता के लिए भी बहुत अच्छा काम करता है। – Andrie

5

मुझे लगता है कि आप अपने आप को गठबंधन में बांध सकते हैं।यह काम करता है:

library(data.table) 
foo <- function(data, by){ 
    by <- by 
    data[, .N, by=by] 
} 

DT <- data.table(mtcars) 
foo(DT, 'gear') 

plotfoo <- function(data, by){ 
    foo(data, by) 
} 
plotfoo(DT, 'gear') 

और वह विधि चरित्र मूल्यों में गुजर समर्थन करता है:

> gg <- 'gear' 
> plotfoo <- function(data, by){ 
+ foo(data, by) 
+ } 
> plotfoo(DT, gg) 
    gear N 
1: 4 12 
2: 3 15 
3: 5 5 
+1

आपको परेशान करने के लिए खेद है, लेकिन मुझे आश्चर्य है कि foo के अंदर 'by <- by'' का अर्थ क्या है। – vodka

+0

आह, हाँ, आप बिल्कुल सही हैं। मैं क्षमा चाहता हूं, मेरे उदाहरण को सरल बनाने के अपने प्रयास में, मैंने 'i' या' j' को तर्क देने की मूल समस्या को हटा दिया। मुझे खेद है - मैं अपना प्रश्न संपादित करूंगा। – Andrie

+0

@ वोदका: कोई विशेष अर्थ नहीं। बस मूल संपादन से छोड़ दिया। –

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