2012-09-09 24 views
68

प्रलेखन कहते हैं'स्प्ली' से 'सुरक्षित' सुरक्षित क्यों है?

vapplysapply के समान है, लेकिन बदले मूल्य का एक पूर्व निर्धारित प्रकार है, तो यह सुरक्षित [...] का उपयोग हो सकता है।

क्या आप कृपया विस्तार से बता सकते हैं कि यह आम तौर पर सुरक्षित क्यों है, शायद उदाहरण प्रदान कर रहा है?


पी.एस .: मैं जवाब पता है और मैं पहले से ही sapply से बचने के लिए करते हैं। मेरी इच्छा है कि यहां SO पर एक अच्छा जवाब दिया गया था, इसलिए मैं अपने सहकर्मियों को यह इंगित कर सकता हूं। कृपया, "मैन्युअल पढ़ें" उत्तर नहीं।

+1

यह अधिक अनुमानित है, कोड को कम अस्पष्ट बना रहा है, और अधिक मजबूत है। विशेष रूप से बड़ी परियोजनाओं में, एक बड़ा पैकेज कहें, यह प्रासंगिक है। –

+3

"पीएस" की कोई ज़रूरत नहीं है ... केवल सवाल का जवाब दें। –

+5

@ कोनराड्रूडॉल्फ कभी-कभी उस प्रभाव को नोट करता है कि सवाल पर ध्यान केंद्रित किया जा सके और "आरटीएफएम" उत्तरों से बचें। :-) –

उत्तर

58

जैसा कि पहले ही उल्लेख किया गया है, vapply दो बातें करता है:

  • थोड़ा सा गति सुधार
  • सीमित वापसी प्रकार के चेक प्रदान करके स्थिरता में सुधार करता है।

दूसरा बिंदु अधिक लाभ है, क्योंकि यह होने से पहले त्रुटियों को पकड़ने में मदद करता है और अधिक मजबूत कोड की ओर जाता है। sapply का उपयोग करके का उपयोग करके यह वापसी मूल्य जांच अलग-अलग किया जा सकता है ताकि यह सुनिश्चित किया जा सके कि वापसी मूल्य आपके द्वारा अपेक्षित चीज़ों के अनुरूप हैं, लेकिन vapply थोड़ा आसान है (यदि अधिक सीमित है, क्योंकि कस्टम त्रुटि जांच कोड सीमाओं के भीतर मूल्यों की जांच कर सकता है , आदि।)।

यहां vapply का एक उदाहरण है जो आपके परिणाम की अपेक्षा है। यह समानांतर कुछ है जो मैं पीडीएफ स्क्रैपिंग पर काम कर रहा था, जहां findD कच्चे टेक्स्ट डेटा में एक पैटर्न से मेल खाने के लिए का उपयोग करेगा (उदाहरण के लिए मेरे पास एक सूची होगी जो split इकाई द्वारा, और प्रत्येक इकाई के भीतर पते से मिलान करने के लिए एक रेगेक्स होगा। कभी-कभी पीडीएफ को आदेश के रूप में परिवर्तित कर दिया गया था और एक इकाई के लिए दो पते होंगे, जिससे बुरेपन का कारण बनता है)।

> input1 <- list(letters[1:5], letters[3:12], letters[c(5,2,4,7,1)]) 
> input2 <- list(letters[1:5], letters[3:12], letters[c(2,5,4,7,15,4)]) 
> findD <- function(x) x[x=="d"] 
> sapply(input1, findD) 
[1] "d" "d" "d" 
> sapply(input2, findD) 
[[1]] 
[1] "d" 

[[2]] 
[1] "d" 

[[3]] 
[1] "d" "d" 

> vapply(input1, findD, "") 
[1] "d" "d" "d" 
> vapply(input2, findD, "") 
Error in vapply(input2, findD, "") : values must be length 1, 
but FUN(X[[3]]) result is length 2 

जैसा कि मैंने अपने छात्रों बताओ, एक प्रोग्रामर अपने सोच बदल रही है बनने के भाग से "त्रुटियों कष्टप्रद रहे हैं" के लिए "त्रुटियों मेरे दोस्त हैं।"

शून्य लंबाई आदानों
एक संबंधित मुद्दा यह है कि अगर इनपुट लंबाई शून्य है, sapply हमेशा एक खाली सूची प्रदान करेगा इनपुट प्रकार की परवाह किए बिना, है। की तुलना करें:

sapply(1:5, identity) 
## [1] 1 2 3 4 5 
sapply(integer(), identity) 
## list()  
vapply(1:5, identity) 
## [1] 1 2 3 4 5 
vapply(integer(), identity) 
## integer(0) 

vapply के साथ, आप उत्पादन का एक विशेष प्रकार है की गारंटी दी जाती है, तो आप शून्य लम्बाई आदानों के लिए अतिरिक्त चेक लिखने की जरूरत नहीं है। क्योंकि यह पहले से ही जानता है क्या प्रारूप में परिणामों की उम्मीद की जानी चाहिए

मानक

vapply थोड़ा तेजी से हो सकता है।

input1.long <- rep(input1,10000) 

library(microbenchmark) 
m <- microbenchmark(
    sapply(input1.long, findD), 
    vapply(input1.long, findD, "") 
) 
library(ggplot2) 
library(taRifx) # autoplot.microbenchmark is moving to the microbenchmark package in the next release so this should be unnecessary soon 
autoplot(m) 

autoplot

12

यदि आप हमेशा अपने परिणाम को विशेष रूप से कुछ चाहते हैं ... उदा। एक तार्किक वेक्टर। vapply यह सुनिश्चित करता है कि ऐसा होता है लेकिन sapply आवश्यक नहीं है।

a<-vapply(NULL, is.factor, FUN.VALUE=logical(1)) 
b<-sapply(NULL, is.factor) 

is.logical(a) 
is.logical(b) 
+3

मुझे लगता है कि ऐसा करने के लिए सबसे स्पष्ट बात यह है कि इस मामले में 'तार्किक (1)' है, क्योंकि FALSE ऐसा लगता है कि यह एक प्रकार निर्दिष्ट करने के बजाय "बंद" करने का विकल्प सेट करता है –

13

अतिरिक्त कुंजी vapply के साथ शामिल स्ट्रोक आप समय बाद भ्रामक परिणाम डिबगिंग बचा सकता है। यदि आप जिस फ़ंक्शन को कॉल कर रहे हैं, वह अलग-अलग डेटाटाइप लौटा सकता है, vapply निश्चित रूप से उपयोग किया जाना चाहिए।

RODBC पैकेज में दिमाग में आने वाला एक उदाहरण sqlQuery होगा। यदि कोई क्वेरी निष्पादित करने में कोई त्रुटि है, तो यह फ़ंक्शन संदेश के साथ character वेक्टर देता है। तो, उदाहरण के लिए, मान लीजिए कि आप तालिका नाम tnames का एक वेक्टर से अधिक पुनरावृति और प्रत्येक के साथ तालिका में संख्यात्मक कॉलम 'NumCol' से अधिकतम मूल्य द्वारा चुने जा रहे:

sapply(tnames, 
    function(tname) sqlQuery(cnxn, paste("SELECT MAX(NumCol) FROM", tname))[[1]]) 

सभी तालिका नाम मान्य हैं तो , इसका परिणाम numeric वेक्टर होगा। लेकिन यदि तालिका में से किसी एक तालिका में डेटाबेस में परिवर्तन होता है और क्वेरी विफल हो जाती है, तो परिणाम मोड character में घुमाए जा रहे हैं। vapplyFUN.VALUE=numeric(1) के साथ, हालांकि, यहां त्रुटि को रोक देगा और इसे लाइन के नीचे कहीं भी पॉप-अप करने से रोक देगा --- या इससे भी बदतर नहीं।