किसी सूची या डेटाफ़्रेम के तत्वों तक पहुँचने के लिए ब्रैकेट [] और डबल ब्रैकेट [[]] के बीच का अंतर


521

आर सूची या data.frame के तत्वों तक पहुँचने के लिए दो अलग अलग तरीकों प्रदान करता है: []और [[]]

दो जिसमें एक स्थितियों मैं एक दूसरे के ऊपर का उपयोग करना चाहिए के बीच क्या अंतर है?

जवाबों:


327

इस प्रकार के प्रश्नों का उत्तर देने के लिए आर लैंग्वेज डेफिनेशन आसान है:

निम्नलिखित उदाहरणों द्वारा प्रदर्शित वाक्य रचना के साथ R के तीन बुनियादी अनुक्रमण संचालक हैं

    x[i]
    x[i, j]
    x[[i]]
    x[[i, j]]
    x$a
    x$"a"

वैक्टर और मैट्रिस के लिए [[रूपों का उपयोग शायद ही कभी किया जाता है, हालांकि उनके पास [फॉर्म से कुछ मामूली शब्दार्थ अंतर होते हैं (जैसे कि यह किसी भी नाम या डिमनेम्स विशेषता को छोड़ देता है, और यह कि आंशिक मिलान वर्ण सूचकांकों के लिए उपयोग किया जाता है)। एक एकल सूचकांक के साथ बहुआयामी संरचनाओं को अनुक्रमित करते समय, x[[i]]या वें अनुक्रमिक तत्व x[i]को वापस कर देगा । ix

सूचियों के लिए, आमतौर पर [[कोई भी किसी एक तत्व का चयन करने के लिए उपयोग करता है, जबकि [चयनित तत्वों की सूची देता है।

[[फार्म, केवल एक ही तत्व पूर्णांक या चरित्र सूचकांकों का उपयोग कर चयन किया जा करने की अनुमति देता है, जबकि [वैक्टर द्वारा अनुक्रमण अनुमति देता है। ध्यान दें कि एक सूची के लिए, सूचकांक एक वेक्टर हो सकता है और वेक्टर का प्रत्येक तत्व सूची में चयनित घटक, उस घटक के चयनित घटक, और इसी तरह लागू होता है। परिणाम अभी भी एक ही तत्व है।


6
[[बनाम] [एक एकल संख्या बनाम वेक्टर के साथ अनुक्रमण करने के लिए उपयोग करने के पीछे क्या तर्क है? क्यों नहीं दोनों के लिए [का उपयोग करें? मुझे लगता है कि आप [[एक प्रविष्टि वापस पाने के लिए [और एक सूचकांक के साथ लंबाई १ की सूची का उपयोग कर सकते हैं ...] लेकिन क्यों नहीं [सूची के बजाय एक सूचकांक के साथ एक एकल प्रविष्टि लौटाएं? आप कभी भी एक लंबाई -1 सूची क्यों चाहते हैं?
शब्दफोरवाइज

4
जब आप अनुक्रमण के लिए उपयोग करना चाहते हैं तो अपरिभाषित लंबाई का वेक्टर हो सकता है। [हमेशा एक सूची वापस करने का मतलब है कि आपको x[v]लंबाई की परवाह किए बिना एक ही आउटपुट क्लास मिलता है v। उदाहरण के लिए, lapplyकोई सूची के सबसेट को पार करना चाहेगा lapply(x[v], fun):। यदि [लंबाई के वैक्टर के लिए सूची को छोड़ दिया जाएगा, तो जब vभी लंबाई होगी, यह एक त्रुटि लौटाएगा ।
एक्समेन

1
मुझे लगता है कि यह अधिक स्पष्ट रूप से समझाता है, adv-r.had.co.nz/Subsetting.html
रेड मटर

171

दो तरीकों के बीच महत्वपूर्ण अंतर उन वस्तुओं का वर्ग है जो वे निष्कर्षण के लिए उपयोग किए जाने पर वापस लौटते हैं और चाहे वे मानों की एक सीमा को स्वीकार कर सकते हैं, या असाइनमेंट के दौरान सिर्फ एक मूल्य।

निम्नलिखित सूची में डेटा निष्कर्षण के मामले पर विचार करें:

foo <- list( str='R', vec=c(1,2,3), bool=TRUE )

कहें कि हम फू से बूल द्वारा संग्रहीत मूल्य निकालना चाहते हैं और इसे एक if()बयान के अंदर उपयोग करना चाहते हैं । यह डेटा के निष्कर्षण के लिए []और [[]]जब वे डेटा निष्कर्षण के लिए उपयोग किया जाता है, के बीच के अंतर को चित्रित करेगा । []कक्षा सूची की विधि रिटर्न वस्तुओं (या data.frame foo अगर एक data.frame था), जबकि [[]]विधि रिटर्न वस्तुओं जिसका वर्ग उनके मूल्यों के प्रकार से निर्धारित होता है।

तो, []निम्नलिखित में विधि परिणाम का उपयोग कर :

if( foo[ 'bool' ] ){ print("Hi!") }
Error in if (foo["bool"]) { : argument is not interpretable as logical

class( foo[ 'bool' ] )
[1] "list"

ऐसा इसलिए है क्योंकि []विधि ने एक सूची लौटा दी है और एक सूची एक if()बयान में सीधे पारित करने के लिए एक वैध वस्तु नहीं है । इस मामले में हमें उपयोग करने की आवश्यकता है [[]]क्योंकि यह 'बूल' में संग्रहीत "नंगे" ऑब्जेक्ट को लौटा देगा जिसमें उपयुक्त वर्ग होगा:

if( foo[[ 'bool' ]] ){ print("Hi!") }
[1] "Hi!"

class( foo[[ 'bool' ]] )
[1] "logical"

दूसरा अंतर यह है कि []ऑपरेटर का उपयोग किसी सूची या कॉलम में डेटा फ्रेम में स्लॉट की एक श्रृंखला तक पहुंचने के लिए किया जा सकता है जबकि [[]]ऑपरेटर एकल स्लॉट या कॉलम तक पहुंचने के लिए सीमित है । एक दूसरी सूची का उपयोग करके मूल्य असाइनमेंट के मामले पर विचार करें bar():

bar <- list( mat=matrix(0,nrow=2,ncol=2), rand=rnorm(1) )

मान लें कि हम बार में निहित डेटा के साथ फू के अंतिम दो स्लॉट को अधिलेखित करना चाहते हैं। यदि हम [[]]ऑपरेटर का उपयोग करने की कोशिश करते हैं , तो यही होता है:

foo[[ 2:3 ]] <- bar
Error in foo[[2:3]] <- bar : 
more elements supplied than there are to replace

ऐसा इसलिए है क्योंकि यह [[]]किसी एक तत्व तक पहुँचने के लिए सीमित है। हमें उपयोग करने की आवश्यकता है []:

foo[ 2:3 ] <- bar
print( foo )

$str
[1] "R"

$vec
     [,1] [,2]
[1,]    0    0
[2,]    0    0

$bool
[1] -0.6291121

ध्यान दें कि असाइनमेंट सफल होने के दौरान, foo में स्लॉट्स ने अपने मूल नाम रखे।


111

डबल कोष्ठक एक सूची तत्व को एक्सेस करता है , जबकि एक एकल ब्रैकेट आपको एकल तत्व के साथ एक सूची देता है।

lst <- list('one','two','three')

a <- lst[1]
class(a)
## returns "list"

a <- lst[[1]]
class(a)
## returns "character"

66

हैडली विकम से:

हैडली विकम से

Tidyverse / purrr का उपयोग करके दिखाने के लिए मेरा (भद्दा दिखने वाला) संशोधन:

यहाँ छवि विवरण दर्ज करें


2
ठंडा! आपको ग्रेस हॉपर के कुछ पिकोसॉन्ड मिल गए हैं !
स्टीव पिचर्स

@StevePitchers हुह?
जजदरा

लेटरमैन पर ग्रेस हॉपर, नैनो सेकंड का प्रदर्शन dailymotion.com/video/x35dsz7
स्टीव पिचर्स

48

[]एक सूची निकालता है, सूची के [[]]भीतर तत्वों को निकालता है

alist <- list(c("a", "b", "c"), c(1,2,3,4), c(8e6, 5.2e9, -9.3e7))

str(alist[[1]])
 chr [1:3] "a" "b" "c"

str(alist[1])
List of 1
 $ : chr [1:3] "a" "b" "c"

str(alist[[1]][1])
 chr "a"

18

यहाँ जोड़ने के [[लिए भी पुनरावर्ती अनुक्रमण के लिए सुसज्जित है ।

यह @JijoMatthew द्वारा जवाब में संकेत दिया गया था, लेकिन पता नहीं चला।

जैसा कि कहा गया है ?"[[", वाक्य-विन्यास, जैसे x[[y]], जहाँ length(y) > 1पर व्याख्या की गई है:

x[[ y[1] ]][[ y[2] ]][[ y[3] ]] ... [[ y[length(y)] ]]

ध्यान दें कि यह नहीं बदलता है कि आपके और मुख्य अंतर में क्या होना चाहिए [और [[- अर्थात्, पूर्व उपसमुच्चय के लिए उपयोग किया जाता है , और बाद का उपयोग एकल सूची तत्वों को निकालने के लिए किया जाता है ।

उदाहरण के लिए,

x <- list(list(list(1), 2), list(list(list(3), 4), 5), 6)
x
# [[1]]
# [[1]][[1]]
# [[1]][[1]][[1]]
# [1] 1
#
# [[1]][[2]]
# [1] 2
#
# [[2]]
# [[2]][[1]]
# [[2]][[1]][[1]]
# [[2]][[1]][[1]][[1]]
# [1] 3
#
# [[2]][[1]][[2]]
# [1] 4
#
# [[2]][[2]]
# [1] 5
#
# [[3]]
# [1] 6

मान 3 प्राप्त करने के लिए, हम कर सकते हैं:

x[[c(2, 1, 1, 1)]]
# [1] 3

@ JijoMatthew के ऊपर दिए गए उत्तर पर वापस जाएं, याद करें r:

r <- list(1:10, foo=1, far=2)

विशेष रूप से, यह उन त्रुटियों की व्याख्या करता है जो हम गलत उपयोग करते समय प्राप्त करते हैं [[, अर्थात्:

r[[1:3]]

त्रुटि r[[1:3]]: पुनरावर्ती अनुक्रमण 2 स्तर पर विफल

चूंकि इस कोड ने वास्तव में मूल्यांकन करने की कोशिश की r[[1]][[2]][[3]], और rस्तर एक पर स्टॉप का घोंसला , पुनरावर्ती इंडेक्सिंग के माध्यम से निकालने का प्रयास [[2]]2 स्तर पर असफल रहा , अर्थात।

इसमें त्रुटि r[[c("foo", "far")]]: सीमा से बाहर सबस्क्रिप्ट

यहाँ, R की तलाश थी r[["foo"]][["far"]], जो मौजूद नहीं है, इसलिए हम सीमा त्रुटि से सबस्क्रिप्ट प्राप्त करते हैं।

यह शायद थोड़ा और अधिक उपयोगी / सुसंगत होगा यदि इन दोनों त्रुटियों ने एक ही संदेश दिया।


नमस्कार मिसेल सर हम कई इंडेक्सिंग के लिए [[]] का उपयोग कर सकते हैं ??
थेरि

14

ये दोनों ही निर्वाह के तरीके हैं। एकल ब्रैकेट सूची का एक सबसेट लौटाएगा, जो अपने आप में एक सूची होगी। अर्थात: इसमें एक से अधिक तत्व हो सकते हैं या नहीं भी हो सकते हैं। दूसरी ओर एक डबल ब्रैकेट सूची से केवल एक तत्व वापस करेगा।

-Single ब्रैकेट हमें एक सूची देगा। यदि हम सूची से कई तत्वों को वापस करना चाहते हैं तो हम एकल ब्रैकेट का भी उपयोग कर सकते हैं। निम्नलिखित सूची पर विचार करें: -

>r<-list(c(1:10),foo=1,far=2);

अब कृपया ध्यान दें कि जब मैं इसे प्रदर्शित करने का प्रयास करता हूं तो सूची वापस आ जाती है। मैं r टाइप करता हूं और एंटर दबाता हूं

>r

#the result is:-

[[1]]

 [1]  1  2  3  4  5  6  7  8  9 10

$foo

[1] 1

$far

[1] 2

अब हम देखेंगे सिंगल ब्रैकेट का जादू: -

>r[c(1,2,3)]

#the above command will return a list with all three elements of the actual list r as below

[[1]]

 [1]  1  2  3  4  5  6  7  8  9 10

$foo

[1] 1


$far

[1] 2

जो वास्तव में वैसा ही है जब हमने स्क्रीन पर r का मान प्रदर्शित करने का प्रयास किया, जिसका अर्थ है कि एकल ब्रैकेट के उपयोग ने एक सूची वापस कर दी है, जहां सूचकांक 1 पर हमारे पास 10 तत्वों का वेक्टर है, फिर हमारे पास दो और तत्व हैं जिनके नाम foo हैं और बहुत दूर। हम एकल ब्रैकेट में इनपुट के रूप में एकल इंडेक्स या एलिमेंट नाम देना भी चुन सकते हैं। उदाहरण के लिए:

> r[1]

[[1]]

 [1]  1  2  3  4  5  6  7  8  9 10

इस उदाहरण में हमने एक सूचकांक "1" दिया और बदले में एक तत्व के साथ एक सूची मिली (जो कि 10 संख्याओं की एक सरणी है)

> r[2]

$foo

[1] 1

उपरोक्त उदाहरण में हमने एक सूचकांक "2" दिया और बदले में एक तत्व के साथ एक सूची मिली

> r["foo"];

$foo

[1] 1

इस उदाहरण में हमने एक तत्व का नाम दिया और बदले में एक तत्व के साथ एक सूची दी गई।

आप तत्वों के नामों का वेक्टर भी पास कर सकते हैं जैसे: -

> x<-c("foo","far")

> r[x];

$foo

[1] 1

$far
[1] 2

इस उदाहरण में हमने दो तत्वों के नाम "फू" और "सुदूर" के साथ एक वेक्टर पास किया

बदले में हमें दो तत्वों के साथ एक सूची मिली।

छोटे एकल ब्रैकेट में हमेशा आप तत्वों की संख्या या एक ही ब्रैकेट में जाने वाले सूचकांकों की संख्या के बराबर तत्वों की संख्या के साथ एक और सूची वापस करेंगे।

इसके विपरीत, एक डबल ब्रैकेट हमेशा केवल एक तत्व लौटाएगा। डबल ब्रैकेट में जाने से पहले एक नोट को ध्यान में रखा जाना चाहिए। NOTE:THE MAJOR DIFFERENCE BETWEEN THE TWO IS THAT SINGLE BRACKET RETURNS YOU A LIST WITH AS MANY ELEMENTS AS YOU WISH WHILE A DOUBLE BRACKET WILL NEVER RETURN A LIST. RATHER A DOUBLE BRACKET WILL RETURN ONLY A SINGLE ELEMENT FROM THE LIST.

मैं कुछ उदाहरण दूंगा। कृपया नीचे दिए गए उदाहरणों के साथ बोल्ड शब्दों को ध्यान में रखें और इसे वापस करें:

डबल ब्रैकेट आपको इंडेक्स पर वास्तविक मूल्य लौटाएगा। (यह एक सूची नहीं लौटाएगा)

  > r[[1]]

     [1]  1  2  3  4  5  6  7  8  9 10


  >r[["foo"]]

    [1] 1

डबल ब्रैकेट्स के लिए यदि हम एक वेक्टर पास करके एक से अधिक तत्वों को देखने की कोशिश करते हैं, तो यह केवल एक त्रुटि के परिणामस्वरूप होगा क्योंकि यह उस आवश्यकता को पूरा करने के लिए नहीं बनाया गया था, लेकिन सिर्फ एक तत्व को वापस करने के लिए।

निम्नलिखित को धयान मे रखते हुए

> r[[c(1:3)]]
Error in r[[c(1:3)]] : recursive indexing failed at level 2
> r[[c(1,2,3)]]
Error in r[[c(1, 2, 3)]] : recursive indexing failed at level 2
> r[[c("foo","far")]]
Error in r[[c("foo", "far")]] : subscript out of bounds

1
नीचा दिखाया गया है क्योंकि "एक वेक्टर पासिंग ... एक त्रुटि का परिणाम होगा क्योंकि यह उस आवश्यकता को पूरा करने के लिए नहीं बनाया गया था" गलत है; मेरा नया उत्तर देखें।
माइकलचिरिको

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

13

मैनुअल कोहरे के माध्यम से नेविगेट करने में न्यूबियों की मदद करने के लिए, यह [[ ... ]]एक ढहते हुए कार्य के रूप में संकेतन को देखने के लिए सहायक हो सकता है - दूसरे शब्दों में, यह तब है जब आप किसी नामित वेक्टर, सूची या डेटा फ़्रेम से डेटा प्राप्त करना चाहते हैं। ऐसा करना अच्छा है यदि आप गणना के लिए इन वस्तुओं के डेटा का उपयोग करना चाहते हैं। ये सरल उदाहरण बताएंगे।

(x <- c(x=1, y=2)); x[1]; x[[1]]
(x <- list(x=1, y=2, z=3)); x[1]; x[[1]]
(x <- data.frame(x=1, y=2, z=3)); x[1]; x[[1]]

तो तीसरे उदाहरण से:

> 2 * x[1]
  x
1 2
> 2 * x[[1]]
[1] 2

1
नौसिखिया के रूप में, मैंने इसे 3 असाइनमेंट्स में x ("<-" का उपयोग करके) को x = 1 से बदलने के लिए w = 1 से बदलने में मददगार पाया, एक्स के साथ भ्रम से बचने के लिए "<-"
user36800

हालांकि बहुत सरल, मैं वास्तव में इस स्पष्टीकरण को पसंद करता हूं। एक और सरल प्रदर्शन: iris[[1]]एक वेक्टर देता है, जबकि iris[1]रिटर्न एक data.frame
stevec

11

पारिभाषिक होने के नाते, [[ऑपरेटर तत्व को एक सूची से निकालता है जबकि [ऑपरेटर एक सूची का सबसेट लेता है ।


7

एक और ठोस उपयोग के मामले के लिए, जब आप split()फ़ंक्शन द्वारा बनाई गई डेटा फ़्रेम का चयन करना चाहते हैं, तो डबल ब्रैकेट का उपयोग करें । यदि आप नहीं जानते हैं, तो split()एक सूची / डेटा फ़्रेम को एक मुख्य फ़ील्ड के आधार पर सबसेट में समूहित करता है। यदि आप कई समूहों पर काम करना चाहते हैं, तो उन्हें प्लॉट करना इत्यादि उपयोगी है।

> class(data)
[1] "data.frame"

> dsplit<-split(data, data$id)
> class(dsplit)
[1] "list"

> class(dsplit['ID-1'])
[1] "list"

> class(dsplit[['ID-1']])
[1] "data.frame"

-1

कृपया नीचे विस्तृत विवरण देखें।

मैंने R में निर्मित डेटा फ्रेम का उपयोग किया है, जिसे mtcars कहा जाता है।

> mtcars 
               mpg cyl disp  hp drat   wt ... 
Mazda RX4     21.0   6  160 110 3.90 2.62 ... 
Mazda RX4 Wag 21.0   6  160 110 3.90 2.88 ... 
Datsun 710    22.8   4  108  93 3.85 2.32 ... 
           ............

तालिका की शीर्ष पंक्ति को हेडर कहा जाता है जिसमें कॉलम नाम होते हैं। प्रत्येक क्षैतिज रेखा बाद में एक डेटा पंक्ति को दर्शाती है, जो पंक्ति के नाम से शुरू होती है, और फिर वास्तविक डेटा के बाद होती है। पंक्ति के प्रत्येक डेटा सदस्य को सेल कहा जाता है।

सिंगल स्क्वायर ब्रैकेट "[]" ऑपरेटर

किसी कक्ष में डेटा पुनर्प्राप्त करने के लिए, हम एकल वर्ग ब्रैकेट "[]" ऑपरेटर में इसकी पंक्ति और स्तंभ निर्देशांक दर्ज करेंगे। दो निर्देशांक एक अल्पविराम द्वारा अलग किए जाते हैं। दूसरे शब्दों में, निर्देशांक पंक्ति की स्थिति से शुरू होते हैं, फिर उसके बाद अल्पविराम से होते हैं, और स्तंभ की स्थिति के साथ समाप्त होते हैं। आदेश महत्वपूर्ण है।

उदाहरण 1: - यहाँ mtcars की पहली पंक्ति, दूसरे कॉलम से सेल वैल्यू है।

> mtcars[1, 2] 
[1] 6

उदाहरण 2: - इसके अलावा, हम संख्यात्मक निर्देशांक के बजाय पंक्ति और स्तंभ नामों का उपयोग कर सकते हैं।

> mtcars["Mazda RX4", "cyl"] 
[1] 6 

डबल वर्ग ब्रैकेट "[[]]" ऑपरेटर

हम डबल वर्ग ब्रैकेट "[[]]" ऑपरेटर के साथ एक डेटा फ्रेम कॉलम का संदर्भ देते हैं।

उदाहरण 1: - अंतर्निहित डेटा सेट mtcars के नौवें कॉलम वेक्टर को पुनः प्राप्त करने के लिए, हम mtcars [[9]] लिखते हैं।

mtcars [[९]] [१] १ १ १ ० ० ० ० ० ० ० ...

उदाहरण 2: - हम उसी कॉलम वेक्टर को उसके नाम से पुनः प्राप्त कर सकते हैं।

mtcars [["हूँ"]] [१] १ १ १ ० ० ० ० ० ० ० ० ...


-1

के अतिरिक्त:

ANSWER के लिंक के बादयहां ।

यहाँ निम्नलिखित बिंदु को संबोधित करते हुए एक छोटा सा उदाहरण दिया गया है:

x[i, j] vs x[[i, j]]

df1   <- data.frame(a = 1:3)
df1$b <- list(4:5, 6:7, 8:9)

df1[[1,2]]
df1[1,2]

str(df1[[1,2]])
str(df1[1,2])
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.