¿Cómo encontrar un buen ajuste para el modelo semi-sinusoidal en R?

37

Quiero suponer que la temperatura de la superficie del mar del mar Báltico es la misma año tras año, y luego describirlo con un modelo lineal / función. La idea que tenía era ingresar el año como un número decimal (o num_months / 12) y averiguar cuál debería ser la temperatura en ese momento. Al arrojarlo a la función lm () en R, no reconoce datos sinusoidales, por lo que solo produce una línea recta. Así que puse la función sin () dentro de un paréntesis I () e intenté algunos valores para ajustar manualmente la función, y eso se acerca a lo que quiero. Pero el mar se está calentando más rápido en el verano y luego se está enfriando más lentamente en el otoño ... Entonces, el modelo se equivoca el primer año, luego se vuelve más correcto después de un par de años, y luego en el futuro, supongo que se vuelve más y más mal otra vez.

¿Cómo puedo obtener R para estimar el modelo para mí, para que no tenga que adivinar los números yo mismo? La clave aquí es que quiero que produzca los mismos valores año tras año, no solo que sea correcto durante un año. Si supiera más sobre matemáticas, tal vez podría adivinarlo como algo así como un Poisson o Gaussiano en lugar de pecado (), pero tampoco sé cómo hacerlo. Cualquier ayuda para acercarse a una buena respuesta sería muy apreciada.

Aquí están los datos que uso y el código para mostrar resultados hasta ahora:

# 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))
GaRyu
fuente

Respuestas:

44

Se puede hacer con regresión lineal -

Solo necesita los términos a y a en cada frecuencia.cospecadocos

La razón por la que puede usar un término y en una regresión lineal para manejar la estacionalidad con cualquier amplitud y fase se debe a la siguiente identidad trigonométrica :cospecadocos

Una onda sinusoidal 'general' con amplitud y fase , , se puede escribir como la combinación lineal donde y son tales que y . Veamos que los dos son equivalentes:φ A sin ( x + φ ) a sin x + b cos x a b A = UNAφUNApecado(X+φ)unapecadoX+sicosXunasi senφ=bUNA=una2+si2pecadoφ=siuna2+si2

unapecado(X)+sicos(X)=una2+si2(unauna2+si2pecado(X)+siuna2+si2cos(X))=UNA[pecado(X)cos(φ)+cos(X)pecado(φ)]=UNApecado(X+φ).

Aquí está el modelo 'básico':

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

[recorte]

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)

pecado en forma

Editar: Nota importante: el término funciona porque el período de la función se ha configurado de manera que un período = 1 unidad de . Si el período es diferente de 1, digamos que el período es , entonces necesita lugar.2πttω(2π/ /ω)t

Aquí está el modelo con el segundo armónico:

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

[recorte]

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)

sin fit 2

... y así sucesivamente, con 6*pi*ToYetc. Sin embargo , si hubiera un poco de ruido en los datos, probablemente me detendría con este segundo modelo.

Con suficientes términos, puede ajustarse exactamente a secuencias periódicas asimétricas e incluso irregulares, pero los ajustes resultantes pueden 'moverse'. Aquí hay una función asimétrica (es un diente de sierra diente de sierra) agregada a una versión escalada de su función periódica, con armónicos tercero (rojo) y cuarto (verde). El ajuste verde está en promedio un poco más cerca pero "ondulado" (incluso cuando el ajuste pasa por cada punto, el ajuste puede ser muy ondulado entre los puntos).

sin fit 3 y 4

La periodicidad aquí significa que solo hay 12 df disponibles para un modelo estacional en los datos. Con la intercepción en el modelo, solo tiene suficientes grados de libertad para 11 parámetros estacionales adicionales. Como está agregando dos términos con cada armónico, el último armónico que puede ajustar solo le permitirá uno de ellos para el último término, el sexto armónico (y ese tiene que ser un ; el término será todo- cero, mientras que el cos alterna entre 1 y -1).cospecado

Si desea ajustes que sean más suaves de lo que este enfoque produce en series no uniformes, es posible que desee buscar ajustes de spline periódicos .

Otro enfoque es usar dummies estacionales, pero el enfoque sin / cos es a menudo mejor si es una función periódica suave.

Este tipo de enfoque de la estacionalidad también puede adaptarse a situaciones en las que la estacionalidad está cambiando, como el uso de la estacionalidad trigonométrica o ficticia con modelos de espacio de estado.


Si bien el enfoque de modelo lineal discutido aquí es fácil de usar, una ventaja del enfoque de regresión no lineal de @ COOLSerdash es que puede manejar una gama mucho más amplia de situaciones: no tiene que cambiar mucho antes de encontrarse en una situación donde la regresión ya no es adecuada, pero todavía se pueden usar mínimos cuadrados no lineales (tener un período desconocido sería uno de esos casos).

Glen_b -Reinstate a Monica
fuente
¡Increíble! Gracias, realmente debería tratar de aprender más sobre los métodos para lidiar con las frecuencias. No entiendo por qué se necesita la parte cos, pero conocer el principio hace que sea fácil de implementar.
GaRyu
@COOLSerdash: en realidad, desearía que no hubieras eliminado tu respuesta (de hecho, la he votado); tiene la ventaja de trabajar en una gama mucho más amplia de circunstancias; modifique algunas cosas sobre el problema y puede perder la linealidad, y luego mi enfoque es inútil, pero el suyo todavía funciona. Creo que hay mucho que decir para poder hacerlo de esa manera.
Glen_b -Reinstale a Monica
@Glen_b Ah, lo siento, pensé que tu publicación hizo que la mía fuera redundante porque no utilicé la forma estándar de tratar el problema. Lo recuperé.
COOLSerdash
cos
1
Ese no fui yo ... Dices desplazamiento de fase como si eso nombrara lo que está sucediendo, y lo hace matemáticamente. Pero para usted, el punto clave es más probable que el 31 de diciembre / 1 de enero sea un origen arbitrario para la época del año dados los retrasos en la respuesta de temperatura a las variaciones en la recepción de radiación. Entonces, el desplazamiento de fase también es un nombre para algo climatológico, el tiempo de temperatura mínima y máxima en relación con su sistema de grabación. (Es un detalle menor, pero prefiero cuantificar el tiempo del año durante 12 meses como 1/24, 3/24, ..., 23/24.)
Nick Cox
10

La temperatura que proporciona en su pregunta se repite exactamente cada año. Sospecho que estas no son temperaturas realmente medidas en cuatro años. En su ejemplo, no necesitaría un modelo, porque las temperaturas solo se repiten exactamente. Pero de lo contrario, podría usar la nlsfunción para ajustar una curva sinusoidal:

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")

Ajuste NLS

Pero el ajuste no es muy bueno, especialmente al principio. Parece que sus datos no pueden ser modelados adecuadamente por una simple curva sinusoidal. ¿Quizás una función trigonométrica más compleja sea suficiente?

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 fit 2

La curva roja se ajusta mejor a los datos. Con la nlsfunción, puede poner el modelo que considere apropiado.

O tal vez podrías hacer uso del forecastpaquete. En el siguiente ejemplo, supuse que la serie temporal comenzó en enero de 2010:

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")

ARIMA

Debido a que los datos son deterministas, no se muestran bandas de confianza.

COOLSerdash
fuente
44
No hay ninguna razón para los mínimos cuadrados no lineales aquí, no es que no funcione razonablemente bien. Calcule sin (2 * pi * ToY), cos (2 * pi * ToY) por adelantado y aliméntelos lm()como cualquier otro predictor. En otras palabras, lm()no es necesario ver ninguna trigonometría en absoluto. Sin embargo, es posible que necesite otro modelo para capturar bien la asimetría marcada. No soy un usuario habitual de R, pero a menudo he utilizado este enfoque en otros lugares (consulte stata-journal.com/sjpdf.html?articlenum=st0116 ).
Nick Cox
@ NickCox Gracias Nick, ese es un consejo muy útil. Actualizaré mi respuesta en un momento.
COOLSerdash
Glen fue más rápido :)
COOLSerdash
1
@COOLserdash Ni siquiera vi el comentario de Nick Cox allí; llegó mientras estaba generando mi respuesta. (Este enfoque es bastante obvio si has visto alguna serie de Fourier.)
Glen_b -Reinstale a Monica
2
Como @Glen_b implica, este es un enfoque estándar, pero no universalmente conocido.
Nick Cox