आर

2012-07-04 11 views
9

के साथ विधि चेनिंग आर में कार्यों को श्रृंखला करना संभव है?आर

नमूना डेटा:

m <- matrix(c(1:10, 11:20), nrow = 10, ncol = 2) 

उदाहरण के लिए, मैं नीचे निम्नलिखित बयानों को बदलने के लिए करना चाहते हैं:

step1 <- mean(m) 
step2 <- sum(step1) 
res <- step2 

या,

res <- sum(mean(m)) 

कुछ इस तरह है:

res <- [email protected]()@sum() 

कुछ मामलों में, यह मेरे कोड को काफी स्पष्ट करेगा।

EDIT1 यह एक डमी उदाहरण है। मैंने यादृच्छिक रूप से 'योग' और 'माध्य' चुना।

बेन जवाब का पहला टुकड़ा दे दी है लेकिन का उपयोग कर% @%, यह काम करता है के भीतर अतिरिक्त तर्कों का उपयोग करने से रोकता है:

m %@% function1(arg1, arg2) %@% function2(arg1, arg2) 

मुझे लगता है कि चारों ओर कैसे काम कर सकते हैं?

EDIT2 एक उदाहरण

require(xts) 
require(PerformanceAnalytics) 
xts.ts <- xts(rnorm(231),as.Date(13514:13744,origin="1970-01-01")) 
plot(na.omit(lag(rollapply(xts.ts, width=rolling.per-1, FUN= function(x){sqrt(var(x))*sqrt(252)}), k=1)), main = "Dummy Example") 

यह उदाहरण चार्ल्स समाधान के साथ ठीक से काम करने लगता है जोड़ना:

`%@%` <- function(x, f) eval.parent(as.call(append(as.list(substitute(f)), list(x), 1))) 
xts.ts %@% rollapply(width = rolling.per-1, FUN= function(x) x%@%var%@%sqrt * sqrt(252)) %@% lag(k=1) %@% na.omit %@% plot(main = "Dummy Example") 

कम मेरे मामले के लिए महत्वपूर्ण है, लेकिन woth उल्लेख है, तो निम्न बयान चार्ल्स के समाधान के साथ विफल रहता है :

xts.ts %@% names <- 'ts name' 
+2

'res <- sum (mean (m)) 'में क्या गलत है? –

+0

कुछ भी नहीं, लेकिन यह लंबाई 1 वेक्टर के 'योग' को लेने के लिए बहुत अधिक समझ में नहीं आता है (जिसे मैट्रिक्स पर 'माध्य' द्वारा वापस किया जाता है)। – Henrik

+0

हालांकि यह "जल्द ही" जा रहा है, फिर भी एक 'mean.data.frame' फ़ंक्शन है जो एक वेक्टर लौटाता है। –

उत्तर

4

बेन जवाब देने के लिए इसी तरह की एक नस में, लेकिन बहस की इजाजत दी:

`%@%` <- function(x, f) eval.parent(as.call(append(as.list(substitute(f)), list(x), 1))) 

x %@% mean %@% sqr # => 6.25 
c(1, 2, NA, 3, 4) %@% mean(na.rm=T) %@% sqr # => 6.25 
m %@% colMeans() %@% sum() # => 21 
+0

काम करने के लिए आखिरी व्यक्ति प्राप्त करने के लिए आपको 'नाम <-' या' setNames', जैसे 'xts.ts% @% setNames ('ts name') 'का उपयोग करना होगा, जैसा कि <-' विशेष हैंडलिंग है lhs फ़ंक्शन कॉल के लिए जो यहां काम नहीं करेगा। – Charles

+0

मैंने इसे पहले नहीं देखा था। यह सुपर चालाक है। मैं इसे उत्पादन कोड में उपयोग करने से बहुत डरता हूं क्योंकि यह नाजुक होगा ... –

+0

मैं इसे कोड - उत्पादन या अन्यथा उपयोग नहीं करना चाहता! भले ही यह एक अच्छा विचार है या नहीं, मुझे आर के बारे में क्या पसंद है यह है कि इस तरह की चीज संभव है। मैं देख सकता हूं कि यह किसी ऐसे व्यक्ति से अधिक परिचित कैसे होगा जो आर के 'क्रिया (ऑब्जेक्ट)' के बजाय सामान्य ओओ 'object.verb()' के लिए उपयोग किया जाता है। – Charles

9

सॉर्ट करें, लेकिन मैं वें स्याही यह गैर-मूर्खतापूर्ण और शायद नाजुक/अच्छा विचार नहीं है। (यह ऊपर निहित है, मुझे लगता है, @ RichieCotton की टिप्पणी से।)

http://cran.r-project.org/doc/manuals/R-lang.html से:

10.3.4 विशेष ऑपरेटरों

आर उपयोगकर्ता परिभाषित इन्फ़िक्स ऑपरेटरों की अनुमति देता है। इन्हें '%' वर्ण से सीमित वर्णों की एक स्ट्रिंग का रूप है। स्ट्रिंग में '%' को छोड़कर कोई प्रिंट करने योग्य वर्ण हो सकता है। तारों के लिए भागने के दृश्य यहां लागू नहीं होते हैं।

ध्यान दें कि निम्नलिखित ऑपरेटरों पूर्वनिर्धारित रहे

%% %*% %/% %in% %o% %x% 
"%@%" <- function(x,f) { 
    f(x) 
} 

sqr <- function(x) x^2 
x <- 1:4 

x %@% mean ## 2.5 
x %@% mean %@% sqr ## 6.25 
x %@% (mean %@% sqr) ## fails 

को देखते हुए m ऊपर परिभाषित - हो सकता है कि तुम क्या मन में था?

m %@% colMeans %@% sum ## 21 

नोट्स:, इसलिए sum(mean(x)) हमेशा एक ही होने के लिए mean(x) के रूप में जा रहा है क्योंकि mean(x) हमेशा एक अदिश (यानी लंबाई -1 वेक्टर) रिटर्न

  • अपने उदाहरण, एक सा अजीब है
  • इन्फिक्स ऑपरेटरों को % से घिरा होना है, इसलिए आपके पास एक ही प्रतीक के रूप में कॉम्पैक्ट के रूप में कुछ भी नहीं हो सकता है (और %% पहले ही लिया गया है)।
  • इस प्रकार की श्रृंखला गैर-सहयोगी है, जो मुझे चिंतित करती है - ऐसा लगता है कि काम के ऊपर के उदाहरण, इसलिए आर (स्पष्ट रूप से) बाएं से दाएं का मूल्यांकन कर रहा है, लेकिन मुझे नहीं पता कि इसकी गारंटी है ...

संपादित करें: प्रश्न अब पूछता है कि अतिरिक्त तर्क कैसे शामिल किए जा सकते हैं। मुझे नहीं लगता कि वाक्यविन्यास सुझाया गया है (x %@% fun1(arg1) %@% fun2(arg2)) कुछ गंभीर जादू के बिना काम करेगा। यह सबसे नज़दीक है जो मैं इस समय प्राप्त कर सकता हूं - एक रैपर फ़ंक्शन बनाना जो मूल फ़ंक्शन का एक संशोधित संस्करण बनाता है।

F <- function(f,...) { 
    function(x) { 
     f(x,...) 
    } 
} 

परीक्षण:

pow <- function(x,b=2) { x^b } 
sqr <- function(x) x^2 
x <- 1:4 

x %@% F(mean,na.rm=TRUE) ## 2.5 
x %@% F(mean,na.rm=TRUE) %@% F(pow,3) ## 16.25 

(ध्यान दें कि मैं F एक समारोह यहां है, जो कुछ स्थितियों में dicey हो सकता है के रूप में इस्तेमाल किया है, क्योंकि यह F==FALSE शॉर्टकट अधिलेखित करता है)

+0

पर इसके बारे में कुछ नोट्स हैं, जो काम करते हैं लेकिन यह ठीक चाल चल सकता है! आप% @% ऑपरेटर को संशोधित करने का सुझाव कैसे देंगे ताकि मैं तर्क जोड़ सकूं? उदाहरण के लिए: एम% @% function1 (arg1, arg2)% function2 (arg1, arg2) – Sam

+1

'% @%" के साथ क्या है <- फ़ंक्शन (f, ...) f (...) '? इसके साथ ही सभी तर्कों को 'एफ', यहां तक ​​कि नामित तर्कों को भी पारित किया जाना चाहिए। (नोट: अनचाहे) – Henrik

+0

@ सैम, क्या आप मुझे एक विशिष्ट उदाहरण दे सकते हैं कि आप क्या करना चाहते हैं और इसका क्या परिणाम होना चाहिए? आपका वाक्यविन्यास बिल्कुल लिखित रूप में काम नहीं करेगा क्योंकि 'function1 (arg1, arg2) 'सामान्य रूप से एक फ़ंक्शन नहीं है। मुझे लगता है कि @ हेनरिक का विचार काम नहीं कर सकता है, क्योंकि हमें सही क्रम में तर्क रखने के लिए सावधान रहना होगा ... सही बाएं से दाएं ऑपरेशन प्राप्त करने के लिए 'f' * दूसरा * तर्क होना चाहिए ऑर्डर ... –

11

कार्यात्मक पैकेज का प्रयास करें :

library(functional) 
squared <- function(x)x*x 
Compose(sum, squared)(m) 
## [1] 44100 
squared(sum(m)) 
## [1] 44100 

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

यहां तर्कों के बारे में एक और प्रतिक्रिया की टिप्पणियों में प्रश्न के संबंध में तर्क के साथ रचना का एक उदाहरण है। Curry कार्यात्मक पैकेज से भी है:

addn <- function(n, x) x + n 
Compose(Curry(addn, 1), squared)(10) 
## [1] 121 
squared(addn(1, 10)) 
## [1] 121 

संपादित करें 2: डिबगिंग के बारे में

के बारे में सवाल, debug काम करता है अगर समारोह curried है। अगर इसके पहले से ही curried नहीं तो Curry में लपेट:

# this works since addn is curried 
debug(addn) 
Compose(Curry(addn, 1), squared)(10) 

# to debug squared put it in a Curry -- so this works: 
debug(squared) 
Compose(Curry(addn, 1), Curry(squared))(10) 
+0

मैंने सोचा कि gsubfn-package ऐसा कुछ कर सकता है, कम से कम env @ fn का पोस्टफिक्स वाक्यविन्यास? –

+0

@DWin, अच्छा बिंदु। Gsubfn में हम यह कर सकते हैं: 'लिखें (एफएन $ पहचान (~ addn (1, x)), वर्ग) (10) '। बेशक यहां तक ​​कि gsubfn के बिना हम यह भी कर सकते हैं: 'लिखें (फ़ंक्शन (एक्स) एडन (1, एक्स), वर्ग) (10) ' –

+0

@ जी। ग्रोथेंडिक, यह काम करता है लेकिन मुझे नहीं लगता कि यह आपको सामान्य फायदे देता है धाराप्रवाह इंटरफ़ेस (http://en.wikipedia.org/wiki/Fluent_interface) कुछ अन्य ऑब्जेक्ट उन्मुख भाषाओं के रूप में होगा। इसके अलावा, मेरा मानना ​​है कि यह किसी स्टेटमेंट के हिस्से को डिबग करना आसान नहीं बनाता है। – Sam

2

मैं magrittr पैकेज का प्रयोग करेंगे। संयुक्त राष्ट्र पाइप क़दम

m <- matrix(c(1:10, 11:20), nrow = 10, ncol = 2) 

m %>% mean %>% sum 

सीसी n'est: यह एक "पाइप" ऑपरेटर है कि एक समारोह का परिणाम लेता है और अगले करने के लिए पहले तर्क के रूप में में यह गुजरता है!