R에서 반 정현파 모델에 적합한 피팅을 찾는 방법은 무엇입니까?


37

발트해의 해수면 온도가 해마다 동일하다고 가정하고 함수 / 선형 모델로 설명합니다. 내가 가진 아이디어는 연도를 10 진수 (또는 num_months / 12)로 입력하고 그 시간에 대한 온도를 알아내는 것이 었습니다. R의 lm () 함수에 던지면 정현파 데이터를 인식하지 않으므로 직선을 생성합니다. 그래서 sin () 함수를 I () 괄호 안에 넣고 함수에 수동으로 맞추기 위해 몇 가지 값을 시도했는데 원하는 것에 가깝습니다. 그러나 여름에는 바다가 더 빨리 따뜻해지고 가을에는 느리게 식습니다. 그래서 첫 해에 모델이 틀렸다가 몇 년 후에 더 정확 해졌다가 나중에는 더 커질 것 같아요 그리고 더 잘못.

R이 모델을 추정하도록하려면 어떻게해야합니까? 그래서 숫자를 직접 추측 할 필요는 없습니까? 여기서 핵심은 1 년 동안 정확하지 않고 매년 동일한 값을 생성하기를 원한다는 것입니다. 수학에 대해 더 많이 알고 있다면 sin () 대신 Poisson 또는 Gaussian과 같은 것으로 추측 할 수는 있지만 그 방법을 모르겠습니다. 좋은 답변에 가까워 지도록 도움을 주시면 대단히 감사하겠습니다.

여기 내가 사용하는 데이터와 지금까지 결과를 표시하는 코드가 있습니다.

# SST from Bradtke et al 2010
ToY <- c(1/12,2/12,3/12,4/12,5/12,6/12,7/12,8/12,9/12,10/12,11/12,12/12,13/12,14/12,15/12,16/12,17/12,18/12,19/12,20/12,21/12,22/12,23/12,24/12,25/12,26/12,27/12,28/12,29/12,30/12,31/12,32/12,33/12,34/12,35/12,36/12,37/12,38/12,39/12,40/12,41/12,42/12,43/12,44/12,45/12,46/12,47/12,48/12)
Degrees <- c(3,2,2.2,4,7.6,13,16,16.1,14,10.1,7,4.5,3,2,2.2,4,7.6,13,16,16.1,14,10.1,7,4.5,3,2,2.2,4,7.6,13,16,16.1,14,10.1,7,4.5,3,2,2.2,4,7.6,13,16,16.1,14,10.1,7,4.5)
SST <- data.frame(ToY, Degrees)
SSTlm <- lm(SST$Degrees ~ I(sin(pi*2.07*SST$ToY)))
summary(SSTlm)
plot(SST,xlim=c(0,4),ylim=c(0,17))
par(new=T)
plot(data.frame(ToY=SST$ToY,Degrees=8.4418-6.9431*sin(2.07*pi*SST$ToY)),type="l",xlim=c(0,4),ylim=c(0,17))

답변:


44

선형 회귀로 수행 할 수 있습니다-

넌 그냥 둘 필요가 와 각 주파수에서 용어.sincos

진폭 및 위상으로 계절성을 처리하기 위해 선형 회귀 분석에서 및 항을 사용할 수있는 이유 는 다음 삼각법 ID 때문입니다 .sincos

진폭 와 위상 , 인 '일반'사인파를 선형 조합 로 쓸 수 있습니다. 여기서 와 는 과 . 이 둘이 동일하다는 것을 보자.AφAsin(x+φ)asinx+bcosxabA=a2+b2sinφ=ba2+b2

asin(x)+bcos(x)=a2+b2(aa2+b2sin(x)+ba2+b2cos(x))=A[sin(x)cos(φ)+cos(x)sin(φ)]=Asin(x+φ).

'기본'모델은 다음과 같습니다.

 SSTlm <- lm(Degrees ~ sin(2*pi*ToY)+cos(2*pi*ToY),data=SST)
 summary(SSTlm)

[한조각]

Coefficients:
                      Estimate Std. Error t value Pr(>|t|)    
(Intercept)              8.292      0.135   61.41   <2e-16 *** 
sin(2 * pi * ToY)       -5.916      0.191  -30.98   <2e-16 ***  
cos(2 * pi * ToY)       -4.046      0.191  -21.19   <2e-16 *** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1   1 

Residual standard error: 0.9355 on 45 degrees of freedom
Multiple R-squared: 0.969,      Adjusted R-squared: 0.9677 
F-statistic: 704.3 on 2 and 45 DF,  p-value: < 2.2e-16 

 plot(Degrees~ToY,ylim=c(1.5,16.5),data=SST)
 lines(SST$ToY,SSTlm$fitted,col=2)

죄가 맞다

편집 : 중요 사항- 함수의 기간이 하나의 기간 = 1 단위의 가되도록 설정되었으므로 항이 작동합니다 . 주기가 1과 다른 경우주기가 이면 대신 가 필요 합니다.2πttω(2π/ω)t

두 번째 고조파가있는 모델은 다음과 같습니다.

 SSTlm2 <- lm(Degrees ~ sin(2*pi*ToY)+cos(2*pi*ToY)
                        +sin(4*pi*ToY)+cos(4*pi*ToY),data=SST)
 summary(SSTlm2)

[한조각]

Coefficients:
                  Estimate Std. Error  t value Pr(>|t|)    
(Intercept)        8.29167    0.02637  314.450  < 2e-16 ***  
sin(2 * pi * ToY) -5.91562    0.03729 -158.634  < 2e-16 ***  
cos(2 * pi * ToY) -4.04632    0.03729 -108.506  < 2e-16 ***  
sin(4 * pi * ToY)  1.21244    0.03729   32.513  < 2e-16 ***  
cos(4 * pi * ToY)  0.33333    0.03729    8.939 2.32e-11 ***  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1   1 

Residual standard error: 0.1827 on 43 degrees of freedom
Multiple R-squared: 0.9989,     Adjusted R-squared: 0.9988 
F-statistic:  9519 on 4 and 43 DF,  p-value: < 2.2e-16 

 plot(Degrees~ToY,ylab="Degrees",xlab="ToY",ylim=c(1.5,16.5),data=SST)
 lines(SSTlm2$fitted~ToY,col=2,data=SST)

죄는 2

... 6*pi*ToY등이 있습니다. 데이터에 약간의 노이즈가 있다면 아마도이 두 번째 모델에서 멈출 것입니다.

충분한 용어를 사용하면 비대칭 및 들쭉날쭉 한주기 시퀀스에 정확하게 맞을 수 있지만 결과에 맞는 크기는 '흔들릴 수 있습니다. 다음 톱니은 3 차 (빨간색) 및 4 차 (녹색) 고조파와 함께 비대칭 기능 ( 주기적인 기능의 스케일 버전에 추가 된 톱니- )입니다. 초록색 맞춤은 평균적으로 조금 더 가깝지만 "흔들림"입니다 (맞춤이 모든 포인트를 통과하더라도 포인트 간의 맞춤이 매우 흔들릴 수 있음).

죄 핏 3 & 4

여기서 주기성은 데이터에 계절 모델에 대해 12df 만 있음을 의미합니다. 모형에서 절편을 사용하면 11 개의 추가 계절 매개 변수에 대한 충분한 자유도 만 있습니다. 당신이 추가되기 때문에 두 개의 각 고조파 당신은 단지 당신이 수에 맞게 수있는 마지막 고조파와 용어를 하나의 마지막 기간 동안 그들의를, 여섯 번째 고조파 (그 하나는 있어야한다 하며 용어는 모든 - 것 cos는 1과 -1 사이에서 교대로 나타납니다).cossin

이 방법이 매끄러운 시리즈가 아닌 것보다 부드러운 피팅을 원한다면 주기적 스플라인 피팅 을 살펴볼 수 있습니다 .

또 다른 접근법은 계절 인형을 사용하는 것이지만, sin / cos 접근법은 부드러운주기 기능인 경우 종종 더 좋습니다.

계절성에 대한 이러한 종류의 접근은 상태 공간 모델에 삼각법 또는 더미 계절성을 사용하는 것과 같이 계절성이 변하는 상황에도 적응할 수 있습니다.


여기서 논의 된 선형 모델 접근 방식은 사용이 간단하지만 @COOLSerdash의 비선형 회귀 접근 방식의 장점 중 하나는 훨씬 더 넓은 범위의 상황을 처리 할 수 ​​있다는 것입니다. 회귀는 더 이상 적합하지 않지만 비선형 최소 제곱을 계속 사용할 수 있습니다 ( 알 수없는 기간 이있는 경우).


대박! 감사합니다. 주파수를 다루는 방법에 대해 더 많이 배우려고 노력해야합니다. 왜 cos 부분이 필요한지 이해하지 못하지만 원리를 알면 구현하기가 쉽습니다.
GaRyu

@COOLSerdash-실제로, 나는 당신이 당신의 답변을 삭제하지 않았기를 바랍니다 (실제로 그것을 upvoted); 보다 광범위한 환경에서 작업 할 수 있다는 이점이 있습니다. 문제에 대해 몇 가지 사항을 조정하면 선형성을 잃을 수 있습니다. 그러면 내 접근 방식은 쓸모가 없지만 여전히 작동합니다. 나는 그렇게 할 수 있다는 말이 많이 있다고 생각합니다.
Glen_b

@Glen_b 아 죄송합니다. 문제를 처리하는 표준 방법을 사용하지 않아서 게시물이 중복되는 것으로 생각했습니다. 삭제를 취소했습니다.
COOLSerdash

@GaRyu는 내 답변의 상단 근처에서 내 편집 내용을 볼 수 있습니다. 여기서 추가 하면 트릭이 발생하는 이유를 간략하게 설명 합니다. cos
Glen_b

1
그건 내가 아니 었어 .... 당신은 마치 무슨 일이 일어나고있는 것처럼 위상 오프셋 을 말하고 수학적으로 수행합니다. 그러나 요점은 12 월 31 일 / 1 월 1 일이 방사선 수신 변화에 따른 온도 반응의 지연으로 인해 연중 임의의 원점 일 가능성이 높다는 것입니다. 따라서 위상 오프셋은 기록 시스템에 대한 최소 및 최대 온도의 타이밍 인 기후학의 이름입니다. (사소한 세부 사항이지만 12 개월 동안 1/24, 3/24, ..., 23/24로 연중 측정하는 것을 선호합니다.)
Nick Cox

10

질문에 제공하는 온도는 매년 정확히 반복됩니다. 나는 이것이 실제로 4 년 동안 온도를 측정하지 않았다고 생각합니다. 예를 들어 온도가 정확히 반복되기 때문에 모델이 필요하지 않습니다. 그러나 그렇지 않으면 nls사인 곡선에 맞게 함수를 사용할 수 있습니다 .

ToY <- c(1/12,2/12,3/12,4/12,5/12,6/12,7/12,8/12,9/12,10/12,11/12,12/12,13/12,14/12,15/12,16/12,17/12,18/12,19/12,20/12,21/12,22/12,23/12,24/12,25/12,26/12,27/12,28/12,29/12,30/12,31/12,32/12,33/12,34/12,35/12,36/12,37/12,38/12,39/12,40/12,41/12,42/12,43/12,44/12,45/12,46/12,47/12,48/12)
Degrees <- c(3,2,2.2,4,7.6,13,16,16.1,14,10.1,7,4.5,3,2,2.2,4,7.6,13,16,16.1,14,10.1,7,4.5,3,2,2.2,4,7.6,13,16,16.1,14,10.1,7,4.5,3,2,2.2,4,7.6,13,16,16.1,14,10.1,7,4.5)
SST <- data.frame(ToY, Degrees)

par(cex=1.5, bg="white")
plot(Degrees~ToY,xlim=c(0,4),ylim=c(0,17), pch=16, las=1)

nls.mod <-nls(Degrees ~ a + b*sin(2*pi*c*ToY), start=list(a = 1, b = 1, c=1))

co <- coef(nls.mod) 
f <- function(x, a, b, c) {a + b*sin(2*pi*c*x) }

curve(f(x, a=co["a"], b=co["b"], c=co["c"]), add=TRUE ,lwd=2, col="steelblue")

NLS 적합

그러나 특히 처음에는 적합하지 않습니다. 간단한 사인 곡선으로 데이터를 적절하게 모델링 할 수없는 것 같습니다. 더 복잡한 삼각 함수가 트릭을 수행 할 수 있습니까?

nls.mod2 <-nls(Degrees ~ a + b*sin(2*pi*c*ToY)+d*cos(2*pi*e*ToY), start=list(a = 1, b = 1, c=1, d=1, e=1))

co2 <- coef(nls.mod2) 
f <- function(x, a, b, c, d, e) {a + b*sin(2*pi*c*x)+d*cos(2*pi*e*x) }

curve(f(x, a=co2["a"], b=co2["b"], c=co2["c"], d=co2["d"], e=co2["e"]), add=TRUE ,lwd=2, col="red")

NLS 핏 2

빨간색 곡선이 데이터에 더 적합합니다. 으로 nls기능, 당신은 당신이 적절하다고 생각하는 모델에 넣을 수 있습니다.

또는 forecast패키지를 사용할 수도 있습니다 . 아래 예에서는 2010 년 1 월에 시계열이 시작되었다고 가정했습니다.

library(forecast)

Degrees.ts <- ts(Degrees, start=c(2010,1), frequency=12)

Degree.trend <- auto.arima(Degrees.ts)

degrees.forecast <- forecast(Degree.trend, h=12, level=c(80,95), fan=F)

plot(degrees.forecast, las=1, main="", xlab="Time", ylab="Degrees")

아리마

데이터가 결정적이므로 신뢰 구간이 표시되지 않습니다.


4
비선형 최소 제곱에 대한 이유는 없습니다. 합리적으로 잘 작동하지는 않습니다. 사전에 sin (2 * pi * ToY), cos (2 * pi * ToY)를 계산 lm()하여 다른 예측 변수 와 동일하게 먹이십시오 . 즉, lm()삼각법을 전혀 볼 필요가 없습니다. 그러나 표시된 비대칭을 제대로 캡처하려면 다른 모델이 필요할 수 있습니다. 나는 일반 R 사용자는 아니지만 다른 곳 에서이 방법을 자주 사용했습니다 ( stata-journal.com/sjpdf.html?articlenum=st0116 참조 ).
Nick Cox

@NickCox 감사합니다 Nick, 매우 유용한 조언입니다. 답변을 조금 업데이트하겠습니다.
COOLSerdash

글렌이었다 빨리 :)
COOLSerdash

1
@COOLserdash 나는 Nick Cox의 의견조차 보지 못했습니다. 내 대답을 생성하는 동안왔다. (이 푸리에 시리즈를 본 적이 있다면이 접근법은 매우 분명합니다.)
Glen_b

2
@Glen_b에서 알 수 있듯이 이것은 보편적으로 알려지지 않은 표준 접근법입니다.
Nick Cox
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.