R में खाली वेक्टर के लिए मान जोड़ें?


160

मैं आर सीखने की कोशिश कर रहा हूं और मैं यह पता नहीं लगा सकता कि सूची में कैसे जोड़ा जाए।

अगर यह अजगर मैं होता। । ।

#Python
vector = []
values = ['a','b','c','d','e','f','g']

for i in range(0,len(values)):
    vector.append(values[i])

आप आर में यह कैसे करते हैं?

#R Programming
> vector = c()
> values = c('a','b','c','d','e','f','g')
> for (i in 1:length(values))
+ #append value[i] to empty vector

सिर्फ स्पष्टता के लिए, यह नहीं है कि आप अजगर में ऐसा कैसे करेंगे, कम से कम अगर मैं आपको सही तरीके से समझूं। आप बस कर सकते हैं vector = values; या आप वेक्टर = वेक्टर + मान कर सकते हैं। लेकिन मुझे आपके उपयोग के मामले में गलतफहमी हो सकती है
निजी

जवाबों:


209

एक लूप के लिए किसी ऑब्जेक्ट पर लागू करने से पूरी वस्तु को हर पुनरावृत्ति पर कॉपी किया जा सकता है, जिससे बहुत सारे लोगों को "आर धीमा है" या "आर लूप्स से बचा जाना चाहिए"।

जैसा कि ब्रॉडी जी ने टिप्पणियों में उल्लेख किया है: वांछित लंबाई के एक वेक्टर को पूर्व-आवंटित करना बेहतर है, फिर तत्व मानों को लूप में सेट करें।

यहां वेक्टर के मानों को जोड़ने के कई तरीके दिए गए हैं। उन सभी को हतोत्साहित किया जाता है।

लूप में एक वेक्टर के लिए आवेदन करना

# one way
for (i in 1:length(values))
  vector[i] <- values[i]
# another way
for (i in 1:length(values))
  vector <- c(vector, values[i])
# yet another way?!?
for (v in values)
  vector <- c(vector, v)
# ... more ways

help("append")आपके प्रश्न का उत्तर देता और इस प्रश्न को लिखने में लगने वाले समय को बचाता (लेकिन इससे आपकी बुरी आदतों का विकास होता)। ;-)

ध्यान दें कि vector <- c()एक खाली वेक्टर नहीं है; यह है NULL। यदि आप एक खाली वर्ण वेक्टर चाहते हैं, तो उपयोग करें vector <- character()

लूपिंग से पहले वेक्टर को पूर्व-आवंटित करें

यदि आप पूरी तरह से लूप के लिए उपयोग करते हैं, तो आपको लूप से पहले पूरे वेक्टर को पूर्व-आवंटित करना चाहिए। यह बड़े वैक्टर के लिए बहुत तेजी से बढ़ेगा।

set.seed(21)
values <- sample(letters, 1e4, TRUE)
vector <- character(0)
# slow
system.time( for (i in 1:length(values)) vector[i] <- values[i] )
#   user  system elapsed 
#  0.340   0.000   0.343 
vector <- character(length(values))
# fast(er)
system.time( for (i in 1:length(values)) vector[i] <- values[i] )
#   user  system elapsed 
#  0.024   0.000   0.023 

2
मैंने इसे आज़माया लेकिन जब मैंने (वेक्टर) प्रिंट किया तो NULL लिस्ट मिली
O.rka

6
अक्षमता के बारे में अनुस्मारक के लिए +1, लेकिन हो सकता है कि कैसे काम करें vector <- character(length(values)); for(...?
ब्रॉडी जी

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

इस बिंदु पर, यह भी लायक महान पुस्तक "आर नरक" जो चक्र 2 में बढ़ती वैक्टर की चर्चा का उल्लेख किया जा सकता है burns-stat.com/pages/Tutor/R_inferno.pdf
Tjebo

62

FWIW: अजगर के परिशिष्ट के अनुरूप ():

b <- 1
b <- c(b, 2)

8
आर में भी एपेंड () है। इसका उपयोग इस प्रकार किया जाएगा b <- 1; b <- append(b, 2):। लेकिन जैसा कि आप उल्लेख करते हैं, सी () चीजों को करने का एक अधिक आर तरीका है।
जुआनबेट्टी

31

आपके पास कुछ विकल्प हैं:

  • c(vector, values)

  • append(vector, values)

  • vector[(length(vector) + 1):(length(vector) + length(values))] <- values

पहला एक मानक दृष्टिकोण है। दूसरा आपको अंत के अलावा कहीं और संलग्न करने का विकल्प देता है। अंतिम एक थोड़ा विपरीत है, लेकिन संशोधित करने का लाभ है vector(हालांकि वास्तव में, आप बस आसानी से कर सकते हैं vector <- c(vector, values)

ध्यान दें कि R में आपको वैक्टर के माध्यम से साइकिल चलाने की आवश्यकता नहीं है। आप बस पूरे में उन पर काम कर सकते हैं।

इसके अलावा, यह काफी बुनियादी सामान है, इसलिए आपको कुछ संदर्भों से गुजरना चाहिए ।

ओपी फीडबैक के आधार पर कुछ और विकल्प:

for(i in values) vector <- c(vector, i)

मैं कुछ अधिक जटिल थो कुछ कर रहा हूँ। मुझे उन्हें लूप के माध्यम से जोड़ने की आवश्यकता है क्योंकि मैं उन्हें संशोधित कर रहा हूं
ओ'रका

1
@ draconisthe0ry, आप जो करने की कोशिश कर रहे हैं, उस पर अधिक विवरण क्यों नहीं देते हैं?
ब्रॉडी जी

1
ओह मैं समझा! लूप के लिए c (वेक्टर, मान [i]) करने के बजाय आपको "वेक्टर = c (वेक्टर, मान [i])
O.rka

माना कि मैं cवैक्टर के बजाय डेटाफ्रेम को जोड़ने के लिए उपयोग करना चाहता हूं ?
लोरेटोपरसी

18

पूर्णता के लिए, लूप के लिए एक वेक्टर में मानों को जोड़ना वास्तव में दर्शन नहीं है। R। R पूरी तरह से वैक्टर पर काम करके बेहतर काम करता है, जैसा कि @BrodieG ने बताया है। देखें कि क्या आपका कोड फिर से नहीं लिखा जा सकता है:

ouput <- sapply(values, function(v) return(2*v))

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


8

कभी-कभी हमें लूप्स का उपयोग करना पड़ता है, उदाहरण के लिए, जब हमें पता नहीं होता है कि परिणाम प्राप्त करने के लिए हमें कितने पुनरावृत्तियों की आवश्यकता है। उदाहरण के रूप में छोरों को लें। नीचे ऐसे तरीके दिए गए हैं जिनसे आपको बिल्कुल बचना चाहिए:

a=numeric(0)
b=1
system.time(
  {
    while(b<=1e5){
      b=b+1
      a<-c(a,pi)
    }
  }
)
# user  system elapsed 
# 13.2     0.0    13.2 

a=numeric(0)
b=1
system.time(
  {
    while(b<=1e5){
      b=b+1
      a<-append(a,pi)
    }
  }
)
# user  system elapsed 
# 11.06    5.72   16.84 

ये बहुत ही अयोग्य हैं क्योंकि आर हर बार जब यह वेक्टर को कॉपी करता है।

इंडेक्स का उपयोग करने के लिए सबसे प्रभावी तरीका है। ध्यान दें कि इस बार मैंने इसे 1e7 बार करने दिया, लेकिन यह अभी भी बहुत तेजी से है c

a=numeric(0)
system.time(
  {
    while(length(a)<1e7){
      a[length(a)+1]=pi
    }
  }
)
# user  system elapsed 
# 5.71    0.39    6.12  

यह स्वीकार्य है। और हम इसे बदल कर एक सा तेजी से कर सकते हैं [के साथ [[

a=numeric(0)
system.time(
  {
    while(length(a)<1e7){
      a[[length(a)+1]]=pi
    }
  }
)
# user  system elapsed 
# 5.29    0.38    5.69   

हो सकता है कि आपने पहले से ही ध्यान दिया lengthहो जो समय लेने वाला हो। यदि हम lengthएक काउंटर से प्रतिस्थापित करते हैं:

a=numeric(0)
b=1
system.time(
  {
    while(b<=1e7){
      a[[b]]=pi
      b=b+1
    }
  }
)
# user  system elapsed 
# 3.35    0.41    3.76

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

a=rep(NaN,2*1e7)
b=1
system.time(
  {
    while(b<=1e7){
      a[[b]]=pi
      b=b+1
    }
    a=a[!is.na(a)]
  }
)
# user  system elapsed 
# 1.57    0.06    1.63 

एक मध्यवर्ती विधि धीरे-धीरे परिणामों के ब्लॉक को जोड़ना है।

a=numeric(0)
b=0
step_count=0
step=1e6
system.time(
  {
    repeat{
      a_step=rep(NaN,step)
      for(i in seq_len(step)){
        b=b+1
        a_step[[i]]=pi
        if(b>=1e7){
          a_step=a_step[1:i]
          break
        }
      }
      a[(step_count*step+1):b]=a_step
      if(b>=1e7) break
      step_count=step_count+1
    }
  }
)
#user  system elapsed 
#1.71    0.17    1.89

2

आर में, आप इस तरह से कोशिश कर सकते हैं:

X = NULL
X
# NULL
values = letters[1:10]
values
# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
X = append(X,values)
X
# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"
X = append(X,letters[23:26])
X
# [1] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j" "w" "x" "y" "z"

2
> vec <- c(letters[1:3]) # vec <- c("a","b","c") ; or just empty vector: vec <- c()

> values<- c(1,2,3)

> for (i in 1:length(values)){
      print(paste("length of vec", length(vec))); 
      vec[length(vec)+1] <- values[i]  #Appends value at the end of vector
  }

[1] "length of vec 3"
[1] "length of vec 4"
[1] "length of vec 5"

> vec
[1] "a" "b" "c" "1" "2" "3"

0

अजगर कोड में आप जो उपयोग कर रहे हैं, उसे अजगर में एक सूची कहा जाता है, और यह आर वैक्टर से अलग है, अगर मुझे वह मिलता है जो आप करना चाहते हैं:

# you can do like this if you'll put them manually  
v <- c("a", "b", "c")

# if your values are in a list 
v <- as.vector(your_list)

# if you just need to append
v <- append(v, value, after=length(v))
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.