एक वेक्टर के अंतिम n तत्वों को प्राप्त करना। क्या लंबाई () फ़ंक्शन का उपयोग करने से बेहतर तरीका है?


84

यदि, तर्क के लिए, मैं पायथन में 10-लंबाई वाले वेक्टर के अंतिम पांच तत्वों को चाहता हूं, तो मैं "-" ऑपरेटर को रेंज इंडेक्स में उपयोग कर सकता हूं:

>>> x = range(10)
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x[-5:]
[5, 6, 7, 8, 9]
>>>

आर में यह करने का सबसे अच्छा तरीका क्या है? क्या मेरी वर्तमान तकनीक की तुलना में एक क्लीनर तरीका है जो लंबाई () फ़ंक्शन का उपयोग करना है?

> x <- 0:9
> x
 [1] 0 1 2 3 4 5 6 7 8 9
> x[(length(x) - 4):length(x)]
[1] 5 6 7 8 9
> 

प्रश्न समय श्रृंखला विश्लेषण btw से संबंधित है जहां यह केवल हालिया डेटा पर काम करने के लिए अक्सर उपयोगी होता है।

जवाबों:


120

देखें ?tailऔर ?headकुछ सुविधाजनक कार्यों के लिए:

> x <- 1:10
> tail(x,5)
[1]  6  7  8  9 10

तर्क के लिए: सब कुछ लेकिन अंतिम पांच तत्व होंगे:

> head(x,n=-5)
[1] 1 2 3 4 5

जैसा कि @ मॉर्टिन मॉर्गन टिप्पणियों में कहते हैं, दो अन्य संभावनाएं हैं जो पूंछ समाधान की तुलना में तेज हैं, अगर आपको इसे 100 मिलियन मूल्यों के वेक्टर पर एक लाख बार ले जाना है। पठनीयता के लिए, मैं पूंछ के साथ जाऊँगा।

test                                        elapsed    relative 
tail(x, 5)                                    38.70     5.724852     
x[length(x) - (4:0)]                           6.76     1.000000     
x[seq.int(to = length(x), length.out = 5)]     7.53     1.113905     

बेंचमार्किंग कोड:

require(rbenchmark)
x <- 1:1e8
do.call(
  benchmark,
  c(list(
    expression(tail(x,5)),
    expression(x[seq.int(to=length(x), length.out=5)]),
    expression(x[length(x)-(4:0)])
  ),  replications=1e6)
)

लेकिन स्लाइसिंग से तेज नहीं - परीक्षण यह बाहर भालू।
निक बैस्टिन

1
धन्यवाद निक दिलचस्प हाँ पायथन स्लाइसिंग भाषा की एक अच्छी विशेषता है।
थॉमस ब्राउन

5
@ निक: वास्तव में। लंबाई 1e6 और 1000 प्रतिकृति के वेक्टर पर, यह लगभग 0.3 सेकंड धीमा है। कल्पना कीजिए कि आप बचाए गए 0.3 सेकंड के साथ क्या कर सकते हैं ...
जोरिस मेयस

6
बर्तनों का कार्यान्वयन ::: tail.default, x[seq.int(to=length(x), length.out=5)]जो लगभग 10x से अधिक तेज़ लगता है, tail()लेकिन संन्यास की जाँच के बिना; x[length(x)-(4:0)]अभी भी तेज है।
मार्टिन मॉर्गन

1
@ जॉरिस: मैं कल्पना कर सकता हूं कि एक विशेष लूप में एक अरब बार उस विशेष ऑपरेशन को चलाने के बाद मैं उनके साथ क्या करूंगा .. :-) मुद्दा यह है कि टुकड़ा करने की क्रिया कम स्पष्ट नहीं है, लेकिन अधिक इष्टतम है, इसलिए सामान्य तौर पर मैं उस मार्ग पर जाना है।
निक बैस्टिन

6

आप R में ठीक उसी तरह से कर सकते हैं जैसे दो और अक्षर:

x <- 0:9
x[-5:-1]
[1] 5 6 7 8 9

या

x[-(1:5)]

क्या होगा अगर मैं वेक्टर की लंबाई नहीं जानता, लेकिन मैं हमेशा अंतिम 5 तत्व चाहता हूं? अजगर संस्करण अभी भी काम करता है लेकिन आपका आर उदाहरण पिछले 15 तत्वों को वापस करता है और इसलिए अभी भी लंबाई () के लिए कॉल की आवश्यकता होगी?
थॉमस ब्राउन

10
सच्चा, मुझे नहीं लगता कि आपका जवाब सामान्य है। आपका कोड उदाहरण क्या करता है, पिछले पांच को रखने के बजाय पहले 5 परिणामों को छोड़ना है। इस उदाहरण में यह एक ही बात है, लेकिन निम्नलिखित काम नहीं करता है: x <- 0:20; x[-5:-1]- यह अंतिम पंद्रह तत्वों को लौटाता है।
एंड्री

मैं अजगर नहीं जानता, लेकिन ओपी में x[-5:]: इसका मतलब यह है कि पहले 5 तत्वों को छोड़ दें, या अंतिम 5 को रखें? यदि यह पहला है, तो वह अप्रत्यक्ष रूप से आपकी लंबाई का उपयोग कर रहा है, जैसे आप हैं, यहाँ (अन्यथा, आप तत्वों को छोड़ने के लिए कैसे जानते हैं?)
निक सब्बे

1
पायथन में "-" ऑपरेटर का अर्थ है पीछे की ओर गिनना। तो यह हमेशा इस मामले में अंतिम 5 तत्वों को लौटाएगा।
थॉमस ब्राउन

2
आह ठीक है, मैं अजगर को नहीं जानता और इसका मतलब यह है कि पहले 5 tail को छोड़ दें ।
सच्चा एप्सकैंप

6

tailअकेले गति के आधार पर यहाँ की अस्वीकृति वास्तव में इस बात पर जोर देने के लिए प्रतीत नहीं होती है कि धीमी गति का हिस्सा इस तथ्य से आता है कि पूंछ के साथ काम करने के लिए सुरक्षित है, यदि आप सुनिश्चित नहीं करते हैं कि x की लंबाई अधिक हो जाएगी n, तो संख्या उन तत्वों को जिन्हें आप समाप्त करना चाहते हैं:

x <- 1:10
tail(x, 20)
# [1]  1  2  3  4  5  6  7  8  9 10
x[length(x) - (0:19)]
#Error in x[length(x) - (0:19)] : 
#  only 0's may be mixed with negative subscripts

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


3

कैसे के बारे में rev(x)[1:5]?

x<-1:10
system.time(replicate(10e6,tail(x,5)))
 user  system elapsed 
 138.85    0.26  139.28 

system.time(replicate(10e6,rev(x)[1:5]))
 user  system elapsed 
 61.97    0.25   62.23

देर से टिप्पणी। वेक्टर को उलटने में लगने वाला प्रसंस्करण समय लंबे वैक्टर के लिए बहुत बड़ा है। इसे समय देने की कोशिश करेंx <- 1:10e6
क्रिस नजगुना

अच्छी बात @ChrisNjuguna लंबाई 10 के एक वेक्टर का उपयोग करके महान काम करता है: :)
ब्रायन डेविस

2

यहाँ यह करने के लिए एक समारोह है और काफी तेजी से लगता है।

endv<-function(vec,val) 
{
if(val>length(vec))
{
stop("Length of value greater than length of vector")
}else
{
vec[((length(vec)-val)+1):length(vec)]
}
}

उपयोग:

test<-c(0,1,1,0,0,1,1,NA,1,1)
endv(test,5)
endv(LETTERS,5)

बेंचमार्क:

                                                    test replications elapsed relative
1                                 expression(tail(x, 5))       100000    5.24    6.469
2 expression(x[seq.int(to = length(x), length.out = 5)])       100000    0.98    1.210
3                       expression(x[length(x) - (4:0)])       100000    0.81    1.000
4                                 expression(endv(x, 5))       100000    1.37    1.691

2

मैं सिर्फ यहां से संबंधित कुछ जोड़ता हूं। मैं बैकएंड सूचकांकों के साथ एक वेक्टर का उपयोग करना चाहता था, अर्थात कुछ ऐसा लिख ​​रहा था, tail(x, i)लेकिन वापस जाने के लिए x[length(x) - i + 1]और पूरी पूंछ नहीं।

निम्नलिखित टिप्पणियों के बाद मैंने दो समाधान निकाले:

accessRevTail <- function(x, n) {
    tail(x,n)[1]
}

accessRevLen <- function(x, n) {
  x[length(x) - n + 1]
}

microbenchmark::microbenchmark(accessRevLen(1:100, 87), accessRevTail(1:100, 87))
Unit: microseconds
                     expr    min      lq     mean median      uq     max neval
  accessRevLen(1:100, 87)  1.860  2.3775  2.84976  2.803  3.2740   6.755   100
 accessRevTail(1:100, 87) 22.214 23.5295 28.54027 25.112 28.4705 110.833   100

तो यह इस मामले में प्रकट होता है कि छोटे वैक्टर के लिए भी, tailसीधी पहुंच की तुलना में बहुत धीमी है

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