2015-08-02 11 views
12
vector1 = c(2, 2, 2, 2, 2, 2) 
vector2 = c(2, 2, 3, 3, 3, 3) 
vector3 = c(2, 2, 1, 2, 2, 2) 

Vektördeki sayıların aynı mı yoksa aza mı olduğunu bilmek istiyorum. vector1 ve vector2 Yani vector3 için FALSE olmalıdır oysa, o TRUE olmalıdır. Basitçe, vektörde bir geri dönüş varsa FALSE döndürmelidir. Bir döngü yazmadan bunu yapmanın hızlı bir yolu var mı?R: Bir vektörün artan/azalan olup olmadığını nasıl kontrol edeceğinizi

cevap

17

Sen diff hepsi negatif olmayan olup olmadığını kontrol etmek elemanları ve all arasındaki farkları hesaplamak için: tüm vektörler olmayan azalan ise

all(diff(vector1) >= 0) 
# [1] TRUE 
all(diff(vector2) >= 0) 
# [1] TRUE 
all(diff(vector3) >= 0) 
# [1] FALSE 

Yukarıdaki kod kontrol ettiğinde ve >= 0 yerini alabilir artmadıklarını kontrol etmek için <= 0 ile. Hedefiniz olan vektörleri tespit etmektir yerine ise ya azalmayan, basit bir değişiklik var ya (aka onlar artan ve aynı vektör içinde azalan bir adım yok) artmayan: Orada

!all(c(-1, 1) %in% sign(diff(vector1))) 
# [1] TRUE 
!all(c(-1, 1) %in% sign(diff(vector2))) 
# [1] TRUE 
!all(c(-1, 1) %in% sign(diff(vector3))) 
# [1] FALSE 
20

!is.unsorted(vector1) 
# [1] TRUE 
!is.unsorted(vector2) 
# [1] TRUE 
!is.unsorted(vector3) 
# [1] FALSE 

Bu fonksiyon çok hızlı o derlenmiş C koduna neredeyse doğrudan hitap gibidir: Bu durum için idealdir is.unsorted adında bir taban R fonksiyonudur.

Benim ilk düşünce sort ve identical, a laidentical(sort(vector1), vector1) kullanmaktı, ama bu oldukça yavaştır; dedi ki, bu yaklaşımın daha esnek durumlara genişletilebileceğini düşünüyorum. hız gerçekten çok önemliydi ise

, biz is.unsorted görülen yükün bir kısmını atlayarak doğrudan iç işlevini diyebiliriz:

.Internal(is.unsorted(vector1, FALSE)) 

(FALSE argüman strictly için FALSE geçer). Bu küçük bir vektör üzerinde ~ 4x hızlandırılmış teklif etti. Benim makinede

library(microbenchmark) 
set.seed(10101) 
srtd <- sort(sample(1e6, rep = TRUE)) # a sorted test case 
unsr <- sample(1e6, rep = TRUE) #an unsorted test case 

microbenchmark(times = 1000L, 
       josilber = {all(diff(srtd) >= 0) 
         all(diff(unsr) >= 0)}, 
       mikec = {identical(sort(srtd), srtd) 
         identical(sort(unsr), unsr)}, 
       baser = {!is.unsorted(srtd) 
         !is.unsorted(unsr)}, 
       intern = {!.Internal(is.unsorted(srtd, FALSE)) 
         !.Internal(is.unsorted(unsr, FALSE))}) 

Sonuçlar::

# Unit: microseconds 
#  expr  min   lq  mean  median  uq  max neval cld 
# josilber 30349.108 30737.6440 34550.6599 34113.5970 34964.171 155283.320 1000 c 
#  mikec 93167.836 94183.8865 97119.4493 94852.7530 97528.859 229692.328 1000 d 
#  baser 1089.670 1168.7400 1322.9341 1296.7375 1347.946 6301.866 1000 b 
# intern 514.816 532.4405 576.2867 560.5955 566.236 2456.237 1000 a 

Yani doğrudan iç işlevini çağırarak (ihtar:

Son seçenek ne kadar hızlı bir fikir edinmek için, burada kriter var sen vektör mükemmel temiz olduğundan emin olmak gerekir - hayır NA s, vs.) ~ sırayla olduğu sırayla olan taban R fonksiyonu, karşı 2x hız ~ diff kullanmaktan daha 30x daha hızlı, ~ kadar hızlı 2x verir benim ilk seçim.

+0

Gerçekten harika işlev (+1)! Biraz endişeliyim, bu OP'nin cümleye göre sormak istediği şey değil, “Basitçe, vektörde bir tersine dönüş varsa FALSE döndürmelidir”, yani yönün tersine çevrilmesi anlamında yorumladım (örn. artan ve azalan, azalan ve sonra artan). Eğer OP vektörün azalıp gitmediğini kontrol ederse, bunun benimkinden daha verimli olması gereken güzel bir yerleşik fonksiyon olduğunu kabul ediyorum (özellikle vektör nispeten erken düşerse). – josliber

+0

@josilber Onun örneklerinin aklında olan tüm vakaları kapsamadığı konusunda hemfikirim.Her neyse, ayar basit: 'is.unsorted (x)' yerine 'is.orted (-x)' kullanın. Ve aynı anda hem de kontrol etmek için, '! Is.orted (x) |! Is.unsorted (-x)'. – MichaelChirico

+0

Evet, diğer iki durumu ele almalılar. '.unsorted (-x) 'i içeren herhangi bir şeyin,' i.unsorted (x)' (5x-10x kıyaslamada daha yavaş) 'dan daha yavaş olacağını, çünkü vektörün yinelenmesi ve tüm unsurları reddetmesi gerektiğine dikkat edin. – josliber

İlgili konular