हमने Vectors कॉन्सेप्ट में देखा था कि किसी वेक्टर का उपयोग शर्त वाले एक्सप्रेशन में किया जा सकता है, जिससे एक लॉजिकल वेक्टर मिलता है। इसका उपयोग आगे all() और any() जैसे फंक्शनों में किया जा सकता है।
v <- c(4, 7, 10)
v >= 6
#> [1] FALSE TRUE TRUE
all(v > 6)
#> [1] FALSE # not all elements match this condition
any(v > 6)
#> [1] TRUE # at least one element matches
यह तरीका इससे कहीं ज़्यादा शक्तिशाली है।
किसी वेक्टर के चुने हुए एलिमेंट इंडेक्स संख्या या इंडेक्स के वेक्टर की मदद से निकाले जा सकते हैं:
v <- 5:10
v
#> [1] 5 6 7 8 9 10
v[3]
#> [1] 7
v[c(2, 4)]
#> [1] 6 8
इसके अलावा, मूल वेक्टर को फिल्टर करने के लिए एक लॉजिकल वेक्टर इस्तेमाल कीजिए, जिससे उन एलिमेंट का सबसेट मिलता है जो TRUE वैल्यू से मेल खाते हैं:
v <- 1:3
bools <- c(FALSE, TRUE, TRUE)
v[bools]
#> [1] 2 3
यहाँ से बूलियन वेक्टर को किसी शर्त वाले एक्सप्रेशन से बनाना बहुत छोटा कदम है:
bools <- v >= 2
bools
#> [1] FALSE TRUE TRUE
v[bools]
#> [1] 2 3
# simpler form
v[v >= 2]
#> [1] 2 3
ये शर्त वाले एक्सप्रेशन कितने भी जटिल हो सकते हैं, और इनमें कई वेक्टर या फंक्शन शामिल हो सकते हैं:
v <- 1:10
w <- 10:1
# pairwise comparison
v > w
#> [1] FALSE FALSE FALSE FALSE FALSE TRUE TRUE TRUE TRUE TRUE
# shorter form
v[v > w]
#> [1] 6 7 8 9 10
हमने इस कॉन्सेप्ट को वेक्टर फिल्टरिंग कहा है, ताकि यह अधिक से अधिक तरह के प्रोग्रामरों को समझ आए।
R समुदाय में सबसेटिंग शब्द शायद अधिक आम है।
आसानी के लिए, ऊपर के सारे उदाहरणों में एक ही लंबाई के वेक्टर की तुलना की गई थी। अगर लंबाइयाँ अलग-अलग हों तो क्या होता है?
जवाब ऐसा है, जो जान-बूझकर उपयोग करने पर बहुत शक्तिशाली होता है, पर अनपेक्षित रूप से सामने आए तो भ्रमित कर देता है।
एक उदाहरण:
v <- 1:6
cond <- c(TRUE, FALSE)
v[cond]
#> [1] 1 3 5
वहाँ हुआ क्या? हमने लंबाई 6 के वेक्टर पर लंबाई 2 का बूलियन इंडेक्स लगाया, लेकिन नतीजे में लंबाई 3 का वेक्टर मिला।
अगर कोई वेक्टर जिस एक्सप्रेशन में इस्तेमाल हो रहा है उसके लिए किसी तरह "बहुत छोटा" पड़ जाए, तो R उसे तब तक दोहराता है जब तक ज़रूरी लंबाई न मिल जाए। इसे "रीसाइक्लिंग" कहते हैं। इसने हमारे c(TRUE, FALSE) वेक्टर को c(TRUE, FALSE, TRUE, FALSE, TRUE, FALSE) बना दिया, और फिर v[cond] ने v की उन वैल्यू को लौटाया जो TRUE हैं, इस मामले में विषम संख्याएँ।
तो अगले उदाहरण में क्या हो रहा है?
v <- 1:3
0.5 * v
#> [1] 0.5 1.0 1.5
2 + v
#> [1] 3 4 5
पहली नज़र में यह स्केलर गुणा और (थोड़ा अजीब) स्केलर जोड़ जैसा लगता है, लेकिन R में स्केलर होते ही नहीं।
इसके बजाय, संख्याओं को रीसाइकल करके v की लंबाई के बराबर एक वेक्टर बनाया जाता है, और फिर c(0.5, 0.5, 0.5) या c(2, 2, 2) का उपयोग करके अंकगणितीय क्रिया हर एलिमेंट पर लगाई जाती है।
रीसाइक्लिंग बहुत, बहुत काम की है, लेकिन पक्का कर लीजिए कि आप वाकई यही चाहते हैं।
वेक्टर की लंबाइयों में ज़रा-सा अंतर (जैसे 99 बनाम 100) भ्रमित करने वाले बग पैदा कर सकता है।
कुछ लेखक सलाह देते हैं कि रीसाइक्लिंग का उपयोग सिर्फ तब करना चाहिए जब वेक्टरों में से किसी एक की लंबाई 1 हो।
which() फंक्शन एक बूलियन आर्गुमेंट लेता है और ऐसे इंडेक्स का वेक्टर लौटाता है जो TRUE देते हैं।
v
#> [1] 2 7 9
v[v > 5] # returns values
#> [1] 7 9
which(v > 5) # returns indices
#> [1] 2 3
पिछले भागों में यह देखा गया था कि किसी कसौटी से मेल खाने वाले एलिमेंट कैसे ढूँढे जाते हैं।
अगर आपको सिर्फ इतना जानना है कि वेक्टर में कोई खास एलिमेंट है या नहीं, तो %in% ऑपरेटर इस्तेमाल किया जाता है।
3 %in% 1:5
#> [1] TRUE
7 %in% 1:5
#> [1] FALSE
यह काम के लिहाज़ से नीचे दिए कोड के बराबर है, लेकिन कहीं अधिक सुविधाजनक है:
length(v[v == 3]) > 0
#> [1] TRUE
एक %notin% ऑपरेटर भी है, जो %in% का लॉजिकल not देता है।