แนวโน้ม STL ของอนุกรมเวลาโดยใช้ R


27

ฉันยังใหม่กับ R และการวิเคราะห์อนุกรมเวลา ฉันพยายามค้นหาแนวโน้มของอนุกรมเวลาอุณหภูมิรายวัน (40 ปี) ที่ยาวนานและพยายามประมาณที่แตกต่างกัน อันแรกเป็นเพียงการถดถอยเชิงเส้นอย่างง่ายและอันที่สองคือการสลายตัวตามฤดูกาลของอนุกรมเวลาโดย Loess

ในระยะหลังปรากฏว่าองค์ประกอบตามฤดูกาลมากกว่าแนวโน้ม แต่ฉันจะหาแนวโน้มได้อย่างไร ฉันต้องการตัวเลขที่บอกว่าแนวโน้มนั้นแข็งแกร่งเพียงใด

     Call:  stl(x = tsdata, s.window = "periodic")
     Time.series components:
        seasonal                trend            remainder               
Min.   :-8.482470191   Min.   :20.76670   Min.   :-11.863290365      
1st Qu.:-5.799037090   1st Qu.:22.17939   1st Qu.: -1.661246674 
Median :-0.756729578   Median :22.56694   Median :  0.026579468      
Mean   :-0.005442784   Mean   :22.53063   Mean   : -0.003716813 
3rd Qu.:5.695720249    3rd Qu.:22.91756   3rd Qu.:  1.700826647    
Max.   :9.919315613    Max.   :24.98834   Max.   : 12.305103891   

 IQR:
         STL.seasonal STL.trend STL.remainder data   
         11.4948       0.7382    3.3621       10.8051
       % 106.4          6.8      31.1         100.0  
     Weights: all == 1
     Other components: List of 5   
$ win  : Named num [1:3] 153411 549 365  
$ deg  : Named int [1:3] 0 1 1   
$ jump : Named num [1:3] 15342 55 37  
$ inner: int 2  
$ outer: int 0

ป้อนคำอธิบายรูปภาพที่นี่

คำตอบ:


20

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

require(mgcv)
require(gamair)
data(cairo)
cairo2 <- within(cairo, Date <- as.Date(paste(year, month, day.of.month, 
                                              sep = "-")))
plot(temp ~ Date, data = cairo2, type = "l")

ข้อมูลอุณหภูมิไคโร

ติดตั้งโมเดลที่มีแนวโน้มและส่วนประกอบตามฤดูกาลเตือนว่าช้า:

mod <- gamm(temp ~ s(day.of.year, bs = "cc") + s(time, bs = "cr"),
            data = cairo2, method = "REML",
            correlation = corAR1(form = ~ 1 | year),
            knots = list(day.of.year = c(0, 366)))

โมเดลที่ติดตั้งมีลักษณะดังนี้:

> summary(mod$gam)

Family: gaussian 
Link function: identity 

Formula:
temp ~ s(day.of.year, bs = "cc") + s(time, bs = "cr")

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)  71.6603     0.1523   470.7   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1   1 

Approximate significance of smooth terms:
                 edf Ref.df       F p-value    
s(day.of.year) 7.092  7.092 555.407 < 2e-16 ***
s(time)        1.383  1.383   7.035 0.00345 ** 
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1   1 

R-sq.(adj) =  0.848  Scale est. = 16.572    n = 3780

และเราสามารถเห็นภาพแนวโน้มและข้อกำหนดตามฤดูกาลผ่านทาง

plot(mod$gam, pages = 1)

ไคโรติดตั้งแนวโน้มและฤดูกาล

และถ้าเราต้องการพล็อตแนวโน้มของข้อมูลที่สังเกตได้เราสามารถทำได้ด้วยการทำนายผ่าน:

pred <- predict(mod$gam, newdata = cairo2, type = "terms")
ptemp <- attr(pred, "constant") + pred[,2]
plot(temp ~ Date, data = cairo2, type = "l",
     xlab = "year",
     ylab = expression(Temperature ~ (degree*F)))
lines(ptemp ~ Date, data = cairo2, col = "red", lwd = 2)

ไคโรติดตั้งแนวโน้ม

หรือเหมือนกันสำหรับรุ่นจริง:

pred2 <- predict(mod$gam, newdata = cairo2)
plot(temp ~ Date, data = cairo2, type = "l",
     xlab = "year",
     ylab = expression(Temperature ~ (degree*F)))
lines(pred2 ~ Date, data = cairo2, col = "red", lwd = 2)

รุ่นติดตั้งไคโร

นี่เป็นเพียงตัวอย่างและการวิเคราะห์เชิงลึกเพิ่มเติมอาจต้องจัดการกับความจริงที่ว่ามีข้อมูลที่ขาดหายไปเล็กน้อย แต่ข้างต้นควรเป็นจุดเริ่มต้นที่ดี

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

> tail(pred[,2], 1) - head(pred[,2], 1)
    3794 
1.756163

โดยเฉลี่ยแล้วอุณหภูมิจะอุ่นขึ้น 1.76 องศามากกว่าตอนเริ่มบันทึก


ดูแผนภูมิฉันคิดว่าอาจมีความสับสนระหว่างฟาเรนไฮต์และเซลเซียส
Henry

เห็นเป็นอย่างดี - ฉันทำสิ่งที่คล้ายกันมาสองสามเดือนแล้วและข้อมูลอยู่ในระดับ C เป็นพลังแห่งนิสัย!
Reinstate Monica - G. Simpson

ขอบคุณ Gavin คำตอบที่ดีและเข้าใจได้ ฉันจะลองคำแนะนำของคุณ เป็นความคิดที่ดีหรือไม่ที่จะเขียนองค์ประกอบของ stl () และสร้างการถดถอยเชิงเส้น
pacomet

1
@pacomet - ไม่ไม่จริงเว้นแต่คุณจะใส่แบบจำลองที่อธิบายความสัมพันธ์แบบอัตโนมัติในส่วนที่เหลือตามที่ฉันทำ คุณสามารถใช้ GLS สำหรับสิ่งนั้นได้ ( gls()ในแพ็คเกจ nlme) แต่ดังที่แสดงด้านบนสำหรับไคโรและ STL แนะนำสำหรับข้อมูลของคุณแนวโน้มไม่เชิงเส้น ดังนั้นแนวโน้มเชิงเส้นจะไม่เหมาะสมเนื่องจากไม่สามารถอธิบายข้อมูลได้อย่างถูกต้อง คุณต้องลองใช้กับข้อมูลของคุณ แต่ AM อย่างที่ฉันแสดงจะลดลงไปเป็นแนวโน้มเชิงเส้นหากข้อมูลนั้นเหมาะสมที่สุด
Reinstate Monica - G. Simpson

1
@ andreas-h ฉันจะไม่ทำอย่างนั้น; เทรนด์ STL ติดตั้งมากกว่า ติดตั้ง GAM กับโครงสร้าง AR () และตีความแนวโน้ม นั่นจะให้รูปแบบการถดถอยที่เหมาะสมซึ่งจะมีประโยชน์มากกว่าสำหรับคุณ
Reinstate Monica - G. Simpson

4

กาวินให้คำตอบอย่างละเอียดมาก แต่สำหรับวิธีที่ง่ายและเร็วขึ้นผมขอแนะนำให้ตั้งค่าSTLฟังก์ชั่นt.windowพารามิเตอร์เป็นค่าที่มีหลายที่ความถี่ของTSข้อมูล ฉันจะใช้ช่วงเวลาที่สนใจโดยอนุมาน (เช่นค่าของ 3,660 สำหรับแนวโน้มเดคาลด์กับข้อมูลความละเอียดรายวัน) นอกจากนี้คุณยังอาจสนใจในstl2แพคเกจที่อธิบายไว้ในของผู้เขียนวิทยานิพนธ์ ฉันใช้วิธีของ Gavin กับข้อมูลของตัวเองและมันก็มีประสิทธิภาพมากเช่นกัน

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