วิธีการหาแบบที่ดีสำหรับแบบกึ่งไซนัสใน R?


37

ฉันต้องการสมมติว่าอุณหภูมิผิวน้ำทะเลของทะเลบอลติกเป็นปีเดียวกันแล้วปีเล่าแล้วอธิบายด้วยแบบจำลองเชิงเส้นตรง ความคิดที่ฉันมีคือเพียงแค่ใส่ปีเป็นเลขทศนิยม (หรือ num_months / 12) และทราบว่าอุณหภูมิควรเป็นเท่าไหร่ในช่วงเวลานั้น การโยนมันลงใน lm () ฟังก์ชั่นใน R มันไม่รู้จักข้อมูลไซน์ดังนั้นมันจึงสร้างเส้นตรง ดังนั้นฉันจึงใส่ฟังก์ชั่น sin () ไว้ในวงเล็บ I () และลองใช้ค่าสองสามค่าเพื่อให้พอดีกับฟังก์ชั่นด้วยตนเองและนั่นก็ใกล้เคียงกับสิ่งที่ฉันต้องการ แต่ทะเลร้อนขึ้นเร็วกว่าในฤดูร้อนแล้วเย็นลงในฤดูใบไม้ร่วงช้าลง ... ดังนั้นแบบจำลองจึงผิดพลาดในปีแรกจากนั้นแก้ไขให้ถูกต้องมากขึ้นหลังจากสองสามปีที่ผ่านมาและในอนาคตฉันคิดว่ามันจะยิ่งมากขึ้น และผิดมากขึ้นอีกครั้ง

ฉันจะได้รับ R เพื่อประเมินโมเดลสำหรับฉันดังนั้นฉันไม่ต้องเดาตัวเลขเอง กุญแจสำคัญในที่นี้คือฉันต้องการให้มันสร้างค่าเหมือนเดิมทุกปีไม่ใช่แค่ให้ถูกต้องหนึ่งปี ถ้าฉันรู้เรื่องคณิตศาสตร์มากขึ้นฉันอาจเดาได้ว่ามันเป็นเหมือนปัวซองหรือเกาส์แทนบาป () แต่ฉันก็ไม่รู้ว่าจะทำเช่นนั้นได้อย่างไร ความช่วยเหลือใด ๆ ที่จะเข้าใกล้คำตอบที่ดีจะได้รับการชื่นชมอย่างมาก

นี่คือข้อมูลที่ฉันใช้และรหัสเพื่อแสดงผลลัพธ์:

# 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

เหตุผลที่คุณสามารถใช้คำว่าและในการถดถอยเชิงเส้นเพื่อจัดการฤดูกาลด้วยแอมพลิจูดและเฟสใด ๆ เป็นเพราะอัตลักษณ์ตรีโกณมิติต่อไปนี้:sincos

คลื่นไซน์ของนายพลที่มีแอมพลิจูดและเฟส ,สามารถเขียนเป็นชุดเชิงเส้น ที่และเป็นเช่นนั้นและ2}} ลองดูว่าทั้งสองมีค่าเท่ากัน: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)

[snip]

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)

บาปพอดี

แก้ไข: หมายเหตุสำคัญ - Theระยะทำงานเพราะระยะเวลาของการทำงานที่ได้รับการจัดตั้งขึ้นเพื่อให้ระยะเวลาหนึ่ง = 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)

[snip]

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เป็นต้นถ้ามีเสียงรบกวนเล็กน้อยในข้อมูลฉันอาจหยุดด้วยรุ่นที่สองนี้

ด้วยคำศัพท์ที่เพียงพอคุณสามารถใส่ลำดับที่ไม่สมมาตรและขรุขระได้เป็นระยะ ๆ แต่ผลลัพธ์ที่ได้อาจพอดีกับ 'กระดิก' นี่คือฟังก์ชั่นแบบอสมมาตร (เป็นฟันเลื่อย - ฟันเลื่อย) เพิ่มเข้ากับฟังก์ชันการปรับตามช่วงเวลาของคุณ) โดยมีฮาร์โมนิกส์ที่สาม (สีแดง) และสี่ (สีเขียว) พอดีสีเขียวโดยเฉลี่ยอยู่ใกล้เพียงเล็กน้อย แต่ "wiggly" (แม้ว่าจะพอดีกับทุกจุดพอดีอาจจะ wiggly มากระหว่างจุด)

บาปพอดี 3 & 4

ความเป็นระยะที่นี่หมายถึงมีเพียง 12 df สำหรับโมเดลตามฤดูกาลในข้อมูล เมื่อมีการสกัดกั้นในโมเดลคุณจะมีองศาอิสระเพียงพอสำหรับพารามิเตอร์ตามฤดูกาลเพิ่มเติมอีก 11 รายการ เนื่องจากคุณกำลังเพิ่มสองข้อตกลงกับแต่ละประสานสุดท้ายฮาร์โมนิที่คุณสามารถใส่เพียงจะช่วยให้คุณหนึ่งของพวกเขาสำหรับระยะที่ผ่านมาหกฮาร์โมนิ (และที่หนึ่งจะต้องมีนั้นระยะจะเป็น all- ศูนย์ในขณะที่ cos สลับระหว่าง 1 และ -1)cossin

หากคุณต้องการความพอดีที่เรียบเนียนกว่าวิธีนี้สร้างขึ้นในซีรีย์ที่ไม่ราบรื่นคุณอาจต้องการดูเป็นเส้นโค้งพอดี

อีกวิธีหนึ่งคือการใช้หุ่นตามฤดูกาล แต่วิธีบาป / cos มักจะดีกว่าถ้ามันเป็นฟังก์ชันที่ราบรื่นเป็นระยะ

วิธีการตามฤดูกาลแบบนี้ยังสามารถปรับให้เข้ากับสถานการณ์ที่มีการเปลี่ยนแปลงตามฤดูกาลเช่นการใช้ฤดูกาลเกี่ยวกับวิชาตรีโกณมิติหรือหุ่นจำลองกับแบบจำลองพื้นที่ของรัฐ


ในขณะที่วิธีการโมเดลเชิงเส้นที่กล่าวถึงในที่นี้นั้นใช้งานง่าย แต่ข้อดีอย่างหนึ่งของ @ COOLSerdash คือวิธีการถดถอยแบบไม่เชิงเส้นคือมันสามารถจัดการกับสถานการณ์ที่หลากหลายมากขึ้น - คุณไม่ต้องเปลี่ยนแปลงอะไรมากก่อนที่คุณจะอยู่ในสถานการณ์เชิงเส้น การถดถอยจะไม่เหมาะสม แต่ไม่เชิงเส้นสี่เหลี่ยมน้อยอาจจะยังคงถูกนำมาใช้ (มีช่วงเวลาที่ไม่รู้จักจะเป็นหนึ่งในกรณีดังกล่าว)


! น่ากลัว ขอบคุณฉันควรพยายามเรียนรู้เพิ่มเติมเกี่ยวกับวิธีการจัดการกับความถี่ ฉันไม่เข้าใจว่าทำไมจึงต้องใช้ส่วน cos แต่การรู้หลักการทำให้ง่ายต่อการใช้งาน
GaRyu

@COOLSerdash - จริง ๆ แล้วฉันหวังว่าคุณจะไม่ได้ลบคำตอบของคุณ (แน่นอนฉัน upvoted มัน); มันมีความได้เปรียบในการทำงานในสถานการณ์ที่กว้างขึ้น ปรับแต่งสิ่งเล็ก ๆ น้อย ๆ เกี่ยวกับปัญหาและคุณอาจสูญเสียความเป็นเส้นตรง - แล้วแนวทางของฉันก็ไร้ประโยชน์ แต่คุณก็ยังทำงานได้ ฉันคิดว่ามีหลายสิ่งที่ต้องบอกว่าสามารถทำเช่นนั้นได้
Glen_b

@Glen_b อ่าฉันคิดว่าโพสต์ของคุณทำให้ฉันซ้ำซ้อนเพราะฉันไม่ได้ใช้วิธีมาตรฐานในการจัดการกับปัญหา ฉันยกเลิกการลบมัน
COOLSerdash

@GaRyu ดูการแก้ไขของฉันใกล้ด้านบนสุดของคำตอบของฉันที่ฉันให้รายละเอียดว่าทำไมการเพิ่มในจึงใช้กลอุบาย cos
Glen_b

1
นั่นไม่ใช่ฉัน .... คุณบอกว่าระยะชดเชยราวกับว่าตั้งชื่อว่าเกิดอะไรขึ้นและมันทำในเชิงคณิตศาสตร์ แต่สำหรับคุณประเด็นสำคัญน่าจะเป็นที่ 31 ธันวาคม / 1 ม.ค. เป็นจุดกำเนิดโดยพลการในช่วงเวลาของปีเนื่องจากความล่าช้าของอุณหภูมิในการตอบสนองต่อการเปลี่ยนแปลงของการรับรังสี ดังนั้นการชดเชยเฟสเป็นชื่อที่นี่สำหรับบางสิ่งทางอุตุนิยมวิทยาเช่นกันเวลาของอุณหภูมิต่ำสุดและสูงสุดเมื่อเทียบกับระบบการบันทึกของคุณ (มันเป็นรายละเอียดเล็ก ๆ น้อย ๆ แต่ฉันชอบช่วงเวลาของปี 12 เดือนเป็น 1/24, 3/24, ... , 23/24)
Nick Cox

10

อุณหภูมิที่คุณให้ไว้ในคำถามของคุณจะทำซ้ำทุกปี ฉันสงสัยว่านี่ไม่ใช่อุณหภูมิที่วัดได้จริงในช่วงสี่ปี ในตัวอย่างของคุณคุณไม่จำเป็นต้องมีแบบจำลองเพราะอุณหภูมิเพียงทำซ้ำอย่างแน่นอน แต่มิฉะนั้นคุณสามารถใช้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:

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

เนื่องจากข้อมูลนั้นถูกกำหนดไว้จึงไม่แสดงแถบความเชื่อมั่น


4
ไม่มีเหตุผลใด ๆ ที่ทำให้เกิดสี่เหลี่ยมจัตุรัสไม่เชิงเส้นตรงนี้ไม่ใช่ว่ามันจะไม่ทำงานได้ดีพอสมควร คำนวณบาป (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 มันมาในขณะที่ฉันกำลังสร้างคำตอบของฉัน (วิธีนี้ค่อนข้างชัดเจนถ้าคุณเคยเห็นซีรี่ส์ Fourier)
Glen_b

2
@Glen_b บอกเป็นนัยว่านี่เป็นวิธีมาตรฐานซึ่งไม่เป็นที่รู้จักในระดับสากล
Nick Cox
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.