R'de kayan bir pencerenin ortalaması


19

Ben daha küçük bir slayt boyunca pencerelerde ortalama rapor etmek istiyorum değerlerin bir vektör var.

Örneğin, aşağıdaki değerlerin bir vektörü için:

4, 5, 7, 3, 9, 8

3'lük bir pencere boyutu ve 2'lik bir slayt aşağıdakileri yapar:

(4+5+7)/3 = 5.33
(7+3+9)/3 = 6.33
(9+8)/3 = 5.67

Ve bu değerlerin bir vektörünü döndürün:

5.33, 6.33, 5.67

Bunu benim için yapacak basit bir işlev var mı? Ayrıca pencere başlangıcı endeksleri döndü, bu bir avantaj olacaktır. Bu örnekte 1,3,5 olur


4
Gördünüz mü bu ?
JM bir istatistikçi değil

Bu "slayt" fikri hakkında biraz bilgi verebilir misiniz?
Shane,

@JM - Yapmadım! Teşekkür ederim! Nasıl çalıştığını görmek üzereyim.
T-Burns

@Shane - Evet! Anlaşılmadığı için üzgünüm. Slayt, ortalamaların bir sonraki penceresini hesaplamaya başlamak için taşıdığınız konumların / endekslerin sayısıdır. Dolayısıyla, son pencerenin bitiminden sonra başlayan bir sonraki pencereden ziyade, slayt pencere boyutunuzdan küçük olduğunda bir miktar çakışma olur. Fikir veri noktalarını biraz düzeltmektir.
T-Burns

Teşekkürler, ben de aynı soruyu sordum. Şimdi, "rollapply" işlevini yararlı buldum.
angelous

Yanıtlar:


24

rollapplyPaket hayvanat bahçesindeki fonksiyon sizi yakınlaştırır:

> require(zoo)
> TS <- zoo(c(4, 5, 7, 3, 9, 8))
> rollapply(TS, width = 3, by = 2, FUN = mean, align = "left")
       1        3 
5.333333 6.333333

3 gözlem içermediğinden sizin için son değeri hesaplamaz. Belki bu gerçek probleminiz için yeterli olacaktır? Ayrıca, döndürülen nesnenin, namesdöndürülen vektör için istediğiniz dizinlere sahip olduğunu unutmayın .

Örneğin, son pencerede gözlemlenmeyen bir 0 olduğu varsayımı var. NAEksik bilgileri temsil etmek ve meaneksik değerleri ele almayı söylemek için bir tuşuyla doldurmak daha yararlı veya gerçekçi olabilir . Bu durumda pencereli son değerimiz (8 + 9) / 2 olacaktır.

> TS <- zoo(c(4, 5, 7, 3, 9, 8, NA))
> rollapply(TS, width = 3, by = 2, FUN = mean, na.rm = TRUE, align = "left")
       1        3        5 
5.333333 6.333333 8.500000

BTW, bir keresinde "kantil loess
Tal Galili

x<-c(x,0)Son cevap öğesini almak için x ( ) sonuna 0 ekleyebilirsiniz .

1
@mbq; bu da gözlemin 0 olduğuna dair güçlü bir varsayım yapıyor. Bu noktayı gözden geçiriyordum ve T-Burns aynı varsayımı yapıyor (gözlemlenmemiş 0). Belki de NA ile birlikte na.rm = TRUEolmayı ve tartışmayı geçmeyi tercih ederim mean. Cevap OP'nin istediği ile aynı olmayacak, ancak daha yararlı görünüyor. Cevabımı buna dahil etmek için düzenleyeceğim.
Monica'yı eski durumuna getirin. G. Simpson

@ucfagls Ancak bunu değiştirmek kolaydır ve dediğiniz gibi bu varsayım OP tarafından yapılmıştır. Öte yandan, daha da kısıtlayıcı olurum ve son ortalamayı kaldırırdım.

Teşekkürler! Özellikle son değeri sıfır varsayım olarak not etmek için bunu düşünmemiştim. Kesinlikle bu son pencereyi önemsiyorum!
T-Burns

12

Rollapply, küçük bir veri kümesiyle harika çalışır. Ancak, birkaç milyon sıra (genomik) ile çalışıyorsanız, oldukça yavaştır.

Aşağıdaki fonksiyon süper hızlıdır.

data <- c(runif(100000, min=0, max=.1),runif(100000, min=.05, max=.1),runif(10000, min=.05, max=1), runif(100000, min=0, max=.2))

slideFunct <- function(data, window, step){
  total <- length(data)
  spots <- seq(from=1, to=(total-window), by=step)
  result <- vector(length = length(spots))
  for(i in 1:length(spots)){
    result[i] <- mean(data[spots[i]:(spots[i]+window)])
  }
  return(result)
}

http://coleoguy.blogspot.com/2014/04/sliding-window-analysis.html


Oldukça yardımcı. Ancak unutmayın ki, bir window -1(aralık) ve a +1(loop) eklemediğiniz sürece window = 3 ortalama 4 (!) Değer döndürür .
BurninLeo

5

Bu basit kod satırı şunları yapar:

((c(x,0,0) + c(0,x,0) + c(0,0,x))/3)[3:(length(x)-1)]

eğer xsöz konusu vektörüdür.


Bu, askerin istediği şeyi döndürmez, ancak 5.33 5.00 6.33. Ancak, oldukça ilginç görünüyor. Fikrinizi açıklayabilir misiniz, çünkü anlamıyorum.
Henrik

1
@Henric Bu numarayı sık kullanıyorum, ancak user1414'ün kodu bu ruloyu OP'nin amaçladığı gibi 2 değil, slayt 1 ile döndürüyor. Check out (c(0,0,x)+c(0,x,0)+c(x,0,0))/3ne demek istediğimi görmek için (bundan sonra da nasıl çalışır). Uygun formül şu şekildedir: (c(0,0,x)+c(0,x,0)+c(x,0,0))[1:(length(x)-3)*2+1]/3(başlangıçta 0 dolguyu kesmeli ve o zaman çift elemanları

4
library(zoo)
x=c(4, 5, 7, 3, 9, 8)
rollmean(x,3)

veya

library(TTR)
x=c(4, 5, 7, 3, 9, 8)
SMA(x,3)

Bu 2D matrisler için işe yarar mı? Ne gibi? Pencere boyutu örnek olarak 3 * 3 ise
Mona Jalal,

sadece bir yöndedir
RockScience

3

shabbychef'in R'deki cevabı :

slideMean<-function(x,windowsize=3,slide=2){
 idx1<-seq(1,length(x),by=slide);
 idx1+windowsize->idx2;
 idx2[idx2>(length(x)+1)]<-length(x)+1;
 c(0,cumsum(x))->cx;
 return((cx[idx2]-cx[idx1])/windowsize);
}

DÜZENLEME: Aradığınız endeksler sadece idx1... bu işlev onları döndürmek için kolayca değiştirilebilir, ancak başka bir çağrı ile onları yeniden oluşturmak neredeyse aynı derecede hızlıdır seq(1,length(x),by=slide).


çeviri için teşekkürler. Kolay bir egzersiz olacağını düşündüm ve ondan biraz R öğrendim
shabbychef

Güncellenmiş cevabım, fromo paketiminfromo::running_mean kanayan kenar versiyonundan kullanım .
shabbychef

3

Beni aşağı indirirken Matlab ve ördek'de bunu kolayca yapabilirim:

%given vector x, windowsize, slide 
idx1 = 1:slide:numel(x);
idx2 = min(numel(x) + 1,idx1 + windowsize);  %sic on +1 here and no -1;
cx = [0;cumsum(x(:))];  %pad out a zero, perform a cumulative sum;
rv = (cx(idx2) - cx(idx1)) / windowsize; %tada! the answer!

bir yan etki olarak, idx1toplamdaki öğenin dizinidir. Bunun kolayca R'ye çevrilebileceğinden eminim first:skip:last. Matlab'daki deyim diziyi ilk, ilk + atlama, ilk + 2 atlama, ..., ilk + n atlama, dizideki son öğenin büyük olmadığı şekilde verir last.

edit : Ortalama kısmı (bölmek windowsize) atlamıştı .


+1 Tada değil, rv / windowsize ;-)

1
Bu marg ... yorum kutusu bu kod için çok dar, bu yüzden yeni bir cevap gönderdim.

1
Teşekkürler, ancak MATLAB ücretsiz değil !!
T-Burns

@ T-Burns: oktav ücretsizdir; ayrıca R, Matlab'a bu kodun kolayca çevrilebileceği kadar yakındır. Aslında, @mbq bunu yaptı ..
shabbychef

1

Bu size pencere araçlarını ve pencerenin ilk değerinin dizinini verecektir:

#The data
x <- c(4, 5, 7, 3, 9, 8)

#Set window size and slide
win.size <- 3
slide <- 2

#Set up the table of results
results <- data.frame(index = numeric(), win.mean = numeric())

#i indexes the first value of the window (the sill?)
i <- 1
#j indexes the row of the results to be added next
j <- 1
while(i < length(x)) {
    #This mean preserves the denominator of 3
    win.mean <- sum(x[i:(i+2)], na.rm = TRUE)/win.size
    #Insert the results
    results[j, ] <- c(i, win.mean)
    #Increment the indices for the next pass
    i <- i + slide
    j <- j + 1
    }

Çeşitli uyarılar geçerlidir: bunu örnek verileriniz dışında hiçbir şeye karşı test etmediniz; Bunun gibi veri çerçevelerine eklemenin gerçekten sayıda değeriniz varsa yavaş (çünkü her seferinde data.frame'i kopyalayacaktır); Ama istediğini üretiyor.


Lütfen yorum yapmadan oy kullanmayın. Neyin yanlış olduğunu nasıl bilebilirim?
Matt Parker

Ben değildim, ama bu yavaş (ama daha yavaş değil rollapply).

2
ben de değildim, ama kendinizin de belirttiği gibi, sonuç nesnesinin ön tahsisi hız sorununa yardımcı olacaktır. Bir numara, bilmiyorsanız veya ihtiyacınız olan sonuç nesnesinin boyutunu belirlemek zor / zordur. Makul bir şey tahsis edin, belki de NA ile önceden doldurun. Ardından, döngünüzle doldurun, ancak önceden yerleştirilmiş nesnenin sınırına yaklaşıyorsanız, başka bir büyük yığın tahsis edin ve doldurmaya devam edin.
Monica'yı eski durumuna getirin. G. Simpson

1
@mbq; Sonuçların hızı, önemli olmakla birlikte, tek önemli husus değildir. Özel çözümlerde süreyi yeniden icat etmek ve tüm indeksleri vb. İşlemek yerine, tek doğrusal olanın rollapplyamacını anlamak ve grep yapmak çok daha kolaydır. Ayrıca, rollapplykodunu kontrol eden bir öğleden sonra pişirebileceğim bir şeyden çok daha fazla göz küresi olmuş olabilir. Kurslar için atlar.
Monica'yı eski durumuna getirin. G. Simpson

1
Değişen [i:(i+2)]için [i:(i+win.size-1)]kod daha genel hale getireceğini düşünüyorum.
Jota
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.