क्यों `` `` `सबसेट` से बेहतर है?


400

जब मुझे किसी data.frame को फ़िल्टर करने की आवश्यकता होती है, अर्थात, कुछ शर्तों को पूरा करने वाली पंक्तियाँ निकालें, तो मैं subsetफ़ंक्शन का उपयोग करना पसंद करता हूं :

subset(airquality, Month == 8 & Temp > 90)

[कार्य के बजाय :

airquality[airquality$Month == 8 & airquality$Temp > 90, ]

मेरी प्राथमिकता के दो मुख्य कारण हैं:

  1. मुझे लगता है कि कोड बेहतर ढंग से पढ़ा जाता है, बाएं से दाएं। यहां तक ​​कि जिन लोगों को आर के बारे में कुछ भी नहीं पता है वे बता सकते हैं कि subsetऊपर दिया गया कथन क्या है।

  2. क्योंकि कॉलम को selectअभिव्यक्ति में चर के रूप में संदर्भित किया जा सकता है , मैं कुछ कीस्ट्रोक्स को बचा सकता हूं। ऊपर मेरे उदाहरण में, मुझे केवल airqualityएक बार टाइप करना था subset, लेकिन तीन बार [

इसलिए मैं खुश रह रहा था, subsetहर जगह का उपयोग कर रहा था क्योंकि यह छोटा है और बेहतर पढ़ता है, यहां तक ​​कि अपने साथी आर कोडर्स को इसकी सुंदरता की वकालत करता है। लेकिन कल मेरी दुनिया बिखर गई। subsetदस्तावेज़ीकरण पढ़ते समय , मैं इस खंड को नोटिस करता हूं:

चेतावनी

यह एक सुविधा फ़ंक्शन है जो अंतःक्रियात्मक रूप से उपयोग करने के लिए है। प्रोग्रामिंग के लिए मानक सब्मिटिंग फ़ंक्शंस का उपयोग करना बेहतर है [और विशेष रूप से लॉजिक सब्मिट के गैर-मानक मूल्यांकन में अप्रत्याशित परिणाम हो सकते हैं।

क्या कोई व्यक्ति यह स्पष्ट करने में मदद कर सकता है कि लेखकों का क्या मतलब है?

सबसे पहले, " अंतःक्रियात्मक उपयोग के लिए " से उनका क्या अर्थ है ? मुझे पता है कि एक संवादात्मक सत्र क्या है, जैसा कि BATCH मोड में चलने वाली स्क्रिप्ट के विपरीत है, लेकिन मुझे यह नहीं दिखता कि इससे क्या अंतर होना चाहिए।

फिर, क्या आप कृपया " तर्क उपसमिति के गैर-मानक मूल्यांकन " की व्याख्या कर सकते हैं और यह खतरनाक क्यों है, शायद एक उदाहरण प्रदान करें?


14
इसके साथ उपयोग करने के लिए यह थोड़ा कम (लेकिन उपजी से कम अखरोट) है,with(airquality, airquality[Month == 8 & Temp > 90, ])
टायलर रिंकर

7
तुम भी मंडलियों 8.2.31 पर एक नज़र और 'आर इन्फर्नो' की 8.2.32 हो सकता है burns-stat.com/pages/Tutor/R_inferno.pdf
पैट्रिक बर्न्स

9
इसके बजाय data.table का प्रयास करें, डिफ़ॉल्ट सिंटैक्स airquality [महीना == 8 & Temp> 90,] की तरह है - बहुत पठनीय, और बहुत तेज़ी से।
स्टियन हाक्लेव २

3
ठीक। तो अगर सबसेट का उपयोग करना बुरा है - क्या [बनाम dplyr :: फ़िल्टर () के बारे में?
userJT

4
सोच रहे लोगों के dplyr::filterलिए भी यही समस्या है। यानी अगर पर्यावरण में उस नाम के साथ एक चर होता है, तो वह डेटा फ्रेम में चर के बजाय इसका उपयोग करेगा। डिबगिंग भ्रमित करने के लिए बनाता है!
देलेत

जवाबों:


241

इस सवाल का जवाब अच्छी तरह से @James द्वारा टिप्पणियों में दिया गया था, subset(और इस तरह के कार्यों) के खतरों के हैडली विकम द्वारा एक उत्कृष्ट स्पष्टीकरण की ओर इशारा करते हुए [यहाँ] । इसे पढ़ो!

यह कुछ हद तक पढ़ा गया है, इसलिए हो सकता है कि यह रिकॉर्ड करने में मदद मिल जाए कि हडले इस उदाहरण का उपयोग करता है जो "सीधे गलत हो सकता है?" के सवाल को संबोधित करता है।

हैडली निम्नलिखित उदाहरण का सुझाव देते हैं: मान लें कि हम कम करना चाहते हैं और फिर निम्नलिखित कार्यों का उपयोग करके डेटा फ्रेम को फिर से व्यवस्थित करें:

scramble <- function(x) x[sample(nrow(x)), ]

subscramble <- function(x, condition) {
  scramble(subset(x, condition))
}

subscramble(mtcars, cyl == 4)

यह त्रुटि लौटाता है:

Eval में त्रुटि (expr, envir, बाड़े): ऑब्जेक्ट 'सिलेंडर' नहीं मिला

क्योंकि R अब "नहीं" जानता है कि 'सिल' नामक वस्तु को कहां ढूंढना है। उन्होंने यह भी कहा कि वास्तव में विचित्र सामान है कि अगर वैश्विक वातावरण में 'सिलेंडर' नामक एक वस्तु हो सकती है:

cyl <- 4
subscramble(mtcars, cyl == 4)

cyl <- sample(10, 100, rep = T)
subscramble(mtcars, cyl == 4)

(उन्हें चलाएं और अपने आप को देखें, यह बहुत पागल है।)


2
क्या मेरे पास स्पष्टीकरण के लिए कुछ नौसिखिया प्रश्न हैं? जब हम लिखते हैं subset(mtcars, cyl == 4)(शीर्ष स्तर पर), तो आर सिलेंडर कहां दिखता है? यदि यह उस mtcarsवस्तु को देखता है जिसे पारित किया गया है subset(), तो क्या इसे किसी अन्य फ़ंक्शन के भीतर cylभी नहीं मिल सकता scrambleहै, क्योंकि mtcarsअभी भी इसे पारित किया जा रहा है? अगर मेरे सवाल का कोई मतलब नहीं है, तो आप सिर्फ इस बात पर अधिक विस्तार कर सकते हैं कि आर अब क्यों नहीं मिल सकता है cyl। धन्यवाद!
हेइज़ेनबर्ग

4
@ अंदर subset.data.frame, हम उस बिंदु पर मूल्यांकन करने की कोशिश कर रहे हैं, बस condition। इसमें मौजूद नहीं है mtcars। तो यह सुनिश्चित करने के लिए subset.data.frameउपयोग करता enclos = parent.frame()है कि conditionइसका सही मूल्यांकन किया गया है cyl == 4। लेकिन फिर हम एन्क्लोजिंग फ्रेम में वापस आ गए हैं, और अब जब आर की तलाश है cylतो वह अंदर नहीं दिख रहा है mtcars। यदि हम उपयोग नहीं करते हैं enclos, तो ऐसा कुछ subset(mtcars,cyl == a)काम नहीं करेगा।
जोरान

क्या किसी को पता है कि सबसेट () सिर्फ तेज़ और सुरक्षित [,] विधि को पर्दे के पीछे लागू नहीं करेगा?
Bjorks नंबर एक प्रशंसक

1
@ माइकलाइपमाइस यह करता है। की अंतिम पंक्ति subset.data.frameहै x[r, vars, drop = drop]। समस्या यह है कि कैसे अयोग्य subsetऔर selectतर्क से कुछ पाने के लिए जिसे आप वैध रूप से पारित कर सकते हैं [.data.frame
जोरन

@ जोरान को मिला, धन्यवाद। आप इसके बारे में कैसे सोचते हैं कि इसके बजाय dplyr के फ़िल्टर का उपयोग करें या नहीं []?
Bjorks नंबर एक प्रशंसक

30

यह [भी तेज है:

require(microbenchmark)        
microbenchmark(subset(airquality, Month == 8 & Temp > 90),airquality[airquality$Month == 8 & airquality$Temp > 90,])
    Unit: microseconds
                                                           expr     min       lq   median       uq     max neval
                     subset(airquality, Month == 8 & Temp > 90) 301.994 312.1565 317.3600 349.4170 500.903   100
     airquality[airquality$Month == 8 & airquality$Temp > 90, ] 234.807 239.3125 244.2715 271.7885 340.058   100

36
हां और ना। मुझे लगता है कि आप जो समय अंतर देख रहे हैं, वह दो चीजों के कारण है। 1) एक छोटा सा (<100 माइक्रोसेकंड) भूमि के ऊपर और 2) subsetके विपरीत [हटा पंक्तियों जहां फिल्टर मूल्यांकन करने के लिए NA। यह करें और आप देखेंगे कि "निष्पक्ष" की तुलना में वे दोनों उतनी ही तेजी से हैं:x <- do.call(rbind, rep(list(airquality), 100)); microbenchmark(subset(x, Month == 8 & Temp > 90),{ i <- x$Month == 8 & x$Temp > 90; x[!is.na(i) & i ,] })
फ्लोडेल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.