R에서 슬라이딩 윈도우의 평균


19

작은 슬라이드를 따라 창에서 평균을보고 싶은 값으로 구성된 벡터가 있습니다.

예를 들어 다음 값으로 구성된 벡터의 경우

4, 5, 7, 3, 9, 8

창 크기 3과 슬라이드 2는 다음을 수행합니다.

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

다음 값으로 구성된 벡터를 반환하십시오.

5.33, 6.33, 5.67

나를 위해 이것을 할 간단한 기능이 있습니까? 그것이 창 시작 지수를 반환하면 추가 보너스가 될 것입니다. 이 예에서는 1,3,5가됩니다.


4
당신은 본 적 ?
JM은 통계가 아닙니다.

이 "슬라이드"아이디어에 대한 배경 지식을 줄 수 있습니까?
Shane

@JM-나는하지 않았다! 감사합니다! 그것이 어떻게 작동하는지 보려고합니다.
T-Burns

@Shane-예! 명확하지 않은 것이 유감입니다. 슬라이드는 다음 평균 창 계산을 시작하기 위해 이동하는 위치 / 표시 수입니다. 따라서 마지막이 끝난 후 시작되는 다음 창이 아니라 슬라이드가 창 크기보다 작을 때 겹치는 부분이 있습니다. 아이디어는 데이터 포인트를 약간 부드럽게하는 것입니다.
T-Burns

고마워, 나는 같은 질문을했다. 이제 "rollapply"기능이 유용하다는 것을 알았습니다.
Angelous

답변:


24

rollapply패키지 동물원의 기능 은 당신을 닫습니다 :

> 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 개의 관측치가 없으므로 마지막 값은 계산하지 않습니다. 어쩌면 이것이 실제 문제에 충분할까요? 또한 반환 된 객체에는 names반환 된 벡터 의 인덱스로 원하는 인덱스가 있습니다 .

귀하의 예는 마지막 창에 관찰되지 않은 0이 있다고 가정합니다. NA누락 된 정보를 표시하고 누락 mean된 값을 처리 하도록 지시하는 것이 더 유용하거나 현실적 일 수 있습니다 . 이 경우 최종 창 값으로 (8 + 9) / 2가됩니다.

> 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, 나는 한때 "quantile loess"의 개념을 구현하기 위해이 함수의 사용법에 대해 썼다 : r-statistics.com/2010/04/…
Tal Galili

x ( x<-c(x,0)) 끝에 0을 추가 하여 마지막 답을 얻을 수 있습니다.

1
@mbq; 그것은이 관측치가 0이라고 강력하게 가정하고 있습니다. 저는이 점을 숙이고 있었고 T- 번즈도 같은 가정을하고 있습니다 (관찰되지 않은 0). 나는 아마도 NA로 패딩하고에 na.rm = TRUE논쟁을 전달하는 것을 선호 합니다 mean. 답변은 OP가 요청한 것과 같지 않지만 더 유용합니다. 이것을 포함하도록 답변을 편집하겠습니다.
복원 Monica Monica-G. Simpson

@ucfagls 그러나 이것은 쉽게 변경 될 수 있으며이 가정은 OP에 의해 만들어 졌다고합니다. 반면에, 나는 더 제한적이고 마지막 평균을 제거 할 것입니다.

감사! 특히 마지막 값을 제로 가정으로 언급하기 위해 나는 그것을 고려하지 않았습니다. 나는 그 마지막 창을 확실히 걱정한다!!
T-Burns

12

Rollapply는 작은 데이터 세트에서 훌륭하게 작동합니다. 그러나 수백만 행 (게놈)으로 작업하는 경우 속도가 매우 느립니다.

다음 기능은 매우 빠릅니다.

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


매우 도움이됩니다. 그러나 window = 3은 -1(범위에) 및 +1(루프에) 를 추가하지 않는 한 평균 4 (!) 값을 반환합니다 .
BurninLeo

5

이 간단한 코드 행은 다음을 수행합니다.

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

문제 x의 벡터가 있다면.


이것은 asker가 원하는 것을 반환하지 않지만 5.33 5.00 6.33을 반환합니다. 그러나 그것은 매우 흥미로워 보입니다. 나는 그것을 얻지 못하기 때문에 당신의 아이디어를 설명 할 수 있습니까?
Henrik

1
@Henric이 트릭을 자주 사용하지만 user1414의 코드는 OP가 의도 한대로 2가 아닌 슬라이드 1 로이 롤을 반환합니다. (c(0,0,x)+c(0,x,0)+c(x,0,0))/3무슨 뜻인지 확인 하고 어떻게 작동하는지 확인하십시오 . 올바른 공식은 다음과 같습니다 : (c(0,0,x)+c(0,x,0)+c(x,0,0))[1:(length(x)-3)*2+1]/3(처음에 0- 패딩을 잘라서 짝수 요소를 선택해야합니다.

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

또는

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

이것이 2D 행렬에서 작동합니까? 어떻게? 예를 들어 창 크기가 3 * 3 인 경우
Mona Jalal

그것은 한 방향
일뿐입니다

3

R에서 shabbychef의 답변 :

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);
}

편집 : 찾고있는 인덱스는 단지 idx1...이 함수는 쉽게 반환하도록 수정할 수 있지만에 대한 다른 호출로 다시 만드는 것이 거의 동일합니다 seq(1,length(x),by=slide).


번역 해 주셔서 감사합니다. 나는 그것이 쉬운 운동이라고 생각했고, 그것으로부터 약간의 R을 배웠다
shabbychef

내 대답은 fromo::running_meanfromo 패키지 의 최첨단 버전에서 사용 하는 것 입니다.
shabbychef

3

당신이 나를 공감하는 동안 Matlab과 duck에서 이것을 쉽게 할 수 있습니다.

%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!

부작용으로 idx1합계의 요소 색인입니다. 이것이 R로 쉽게 번역 될 수 있다고 확신합니다 first:skip:last. Matlab 의 관용구 는 배열의 첫 번째 요소가 first, first + skip, first + 2skip, ..., first + n skip을 제공합니다. 여기서 배열의 마지막 요소는보다 크지 않습니다 last.

편집 : 나는 평균화 부분을 생략했다 windowsize.


+1

1
이 코드는 주석 상자가 너무 좁기 때문에 새로운 답변을 게시했습니다.

1
고맙지 만 MATLAB은 무료가 아닙니다 !!
T-Burns

@ T-Burns : 그러나 옥타브는 무료입니다. 또한 R은 Matlab에 가깝기 때문에이 코드를 쉽게 번역 할 수 있습니다. 실제로 @mbq는 그렇게했습니다.
shabbychef

1

그러면 창 평균과 창의 첫 번째 값 색인이 표시됩니다.

#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
    }

다양한 경고가 적용됩니다. 샘플 데이터 이외의 다른 것에 대해서는 이것을 테스트하지 않았습니다. 이 같은 데이터 프레임에 추가하여 얻을 수 있다고 생각합니다 정말 당신이 값 (이 때마다 data.frame을 복사 할 것이기 때문에) 많은 경우 느린; 그러나 그것은 당신이 요구 한 것을 만들어냅니다.


의견을 제시하지 않고 공감하지 마십시오. 무엇이 잘못되었는지 어떻게 알 수 있습니까?
Matt Parker

나 아니었지만 이것은 느리지 만 (보다 느리지는 않습니다 rollapply).

2
나도 아니었지만 자신이 언급했듯이 결과 개체의 사전 할당은 속도 문제를 해결하는 데 도움이됩니다. 하나의 트릭, 알지 못하거나 지루하거나 결정하기 어려운 경우 필요한 결과 개체의 크기를 결정하십시오. NA로 미리 채워져있는 합리적인 무언가를 할당하십시오. 그런 다음 루프를 채우고 사전 할당 된 객체의 한계에 도달하면 다른 큰 청크를 할당하고 채우기를 계속하는지 확인하십시오.
복원 Monica Monica-G. Simpson

1
@mbq; 중요하지만 결과의 속도는 유일한 고려 사항이 아닙니다. 커스텀 솔루션에서 while을 재발 명하고 모든 인덱스 등을 처리하는 대신 rollapply의도를 이해하고 파악하기가 훨씬 쉬운 1 선형 입니다. 또한 rollapply언젠가 오후에 요리 할 수있는 것보다 코드를 확인하는 많은 안구가 있었을 것입니다. 코스 말.
복원 Monica Monica-G. Simpson

1
변경 [i:(i+2)]하는 [i:(i+win.size-1)]코드가 더 일반적인 만들 것, 나는 생각한다.
Jota
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.