`Vapply` सुरक्षित` sapply` से क्यों है?


84

दस्तावेज कहता है

vapplyके समान है sapply, लेकिन इसमें पूर्व-निर्दिष्ट प्रकार का रिटर्न वैल्यू है, इसलिए इसे उपयोग करने के लिए सुरक्षित [...] किया जा सकता है।

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


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


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

1
FUN.VALUE के लिए vapply मैन्युअल उदाहरण बहुत ही जटिल और नीलम उपयोगकर्ताओं के लिए डराने वाले हैं।
jsta

जवाबों:


73

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

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

दूसरा बिंदु अधिक से अधिक लाभ है, क्योंकि यह होने से पहले त्रुटियों को पकड़ने में मदद करता है और अधिक मजबूत कोड की ओर जाता है। इस वापसी मान की जाँच का उपयोग कर से अलग किया जा सकता है sapply, जिसके बाद stopifnotयह सुनिश्चित करें कि वापसी मान जिसकी आपको उम्मीद के अनुरूप हैं बनाने के लिए है, लेकिन 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


15

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

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

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

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


13

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

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

is.logical(a)
is.logical(b)

4
मुझे लगता है कि logical(1)इस मामले में सबसे स्पष्ट बात है , जैसा कि FALSE दिखता है कि यह एक प्रकार को निर्दिष्ट करने के बजाय "बंद" करने का एक विकल्प सेट करता है
उड़ान भेड़
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.