Xu hướng dữ liệu chuỗi thời gian không đều


8

Tôi có một bộ dữ liệu đo nhiệt độ nước được lấy từ một người nước lớn trong khoảng thời gian không đều trong khoảng thời gian nhiều thập kỷ. (Vịnh Galveston, TX nếu bạn quan tâm)

Đây là phần đầu của dữ liệu:

  STATION_ID     DATE  TIME LATITUDE LONGITUDE YEAR MONTH DAY SEASON MEASUREMENT
1      13296  6/20/91 11:04 29.50889 -94.75806 1991     6  20 Summer        28.0
2      13296  3/17/92  9:30 29.50889 -94.75806 1992     3  17 Spring        20.1
3      13296  9/23/91 11:24 29.50889 -94.75806 1991     9  23   Fall        26.0
4      13296  9/23/91 11:24 29.50889 -94.75806 1991     9  23   Fall        26.0
5      13296  6/20/91 11:04 29.50889 -94.75806 1991     6  20 Summer        28.0
6      13296 12/17/91 10:15 29.50889 -94.75806 1991    12  17 Winter        13.0

(ĐO LƯỜNG là phép đo nhiệt độ quan tâm.)

Toàn bộ có sẵn ở đây: https://github.com/jscarlton/galvBayData/blob/master/gbtemp.csv

Tôi muốn loại bỏ các tác động của biến đổi theo mùa để quan sát xu hướng (nếu có) trong nhiệt độ theo thời gian. Là một chuỗi thời gian phân tách là cách tốt nhất để làm điều này? Làm thế nào để tôi xử lý thực tế là các phép đo không được thực hiện trong một khoảng thời gian đều đặn? Tôi hy vọng có một gói R cho loại phân tích này, mặc dù Python hoặc Stata cũng sẽ ổn. 

(Lưu ý: đối với phân tích này, tôi chọn bỏ qua sự thay đổi không gian trong các phép đo. Lý tưởng nhất là tôi cũng tính đến điều đó, nhưng tôi nghĩ rằng làm như vậy sẽ vô cùng phức tạp.)

Câu trả lời:


18

Thay vì cố gắng phân tách chuỗi thời gian một cách rõ ràng, thay vào đó tôi sẽ đề nghị bạn mô hình hóa dữ liệu theo thời gian bởi vì, như bạn sẽ thấy bên dưới, xu hướng dài hạn có thể thay đổi theo không gian, xu hướng theo mùa thay đổi theo xu hướng dài hạn và không gian.

Tôi đã thấy rằng các mô hình phụ gia tổng quát (GAM) là một mô hình tốt để phù hợp với chuỗi thời gian không đều như bạn mô tả.

Dưới đây tôi minh họa một mô hình nhanh tôi đã chuẩn bị cho dữ liệu đầy đủ của mẫu sau

E(yTôi)= =α+f1(Con chồnTôi)+f2(DoYTôi)+f3(NămTôi)+f4(xTôi,yTôi)+f5(DoYTôi,NămTôi)+f6(xTôi,yTôi,Con chồnTôi)+f7(xTôi,yTôi,DoYTôi)+fsố 8(xTôi,yTôi,NămTôi)

Ở đâu

  • α là mô hình chặn,
  • f1(Con chồnTôi) là một chức năng trơn tru của thời gian trong ngày,
  • f2(DoYTôi) là một chức năng trơn tru của ngày trong năm,
  • f3(NămTôi) là một hàm trơn tru của năm,
  • f4(xTôi,yTôi) là một 2D mịn về kinh độ và vĩ độ,
  • f5(DoYTôi,NămTôi) là một sản phẩm trơn tru của ngày và năm,
  • f6(xTôi,yTôi,Con chồnTôi) sản phẩm trơn tru về vị trí và thời gian trong ngày
  • f7(xTôi,yTôi,DoYTôi) sản phẩm kéo căng mịn của vị trí ngày trong năm &
  • fsố 8(xTôi,yTôi,NămTôi sản phẩm mịn của vị trí & năm

Có hiệu quả, bốn mịn đầu tiên là tác dụng chính của

  1. thời gian trong ngày,
  2. Mùa,
  3. xu hướng dài hạn,
  4. biến đổi không gian

Trong khi bốn sản phẩm tenor còn lại làm mịn mô hình tương tác trơn tru giữa các hiệp phương đã nêu, mô hình nào

  1. mô hình nhiệt độ theo mùa thay đổi theo thời gian như thế nào
  2. Làm thế nào thời gian của hiệu ứng trong ngày thay đổi theo không gian,
  3. hiệu ứng theo mùa thay đổi theo không gian và
  4. xu hướng dài hạn thay đổi theo không gian như thế nào

Dữ liệu được tải vào R và được mát xa một chút với đoạn mã sau

library('mgcv')
library('ggplot2')
library('viridis')
theme_set(theme_bw())
library('gganimate')

galveston <- read.csv('gbtemp.csv')
galveston <- transform(galveston,
                       datetime = as.POSIXct(paste(DATE, TIME),
                                             format = '%m/%d/%y %H:%M', tz = "CDT"))
galveston <- transform(galveston,
                       STATION_ID = factor(STATION_ID),
                       DoY = as.numeric(format(datetime, format = '%j')),
                       ToD = as.numeric(format(datetime, format = '%H')) +
                            (as.numeric(format(datetime, format = '%M')) / 60))

Bản thân mô hình được trang bị sử dụng bam()chức năng được thiết kế để phù hợp với GAM cho các tập dữ liệu lớn hơn như thế này. Bạn cũng có thể sử dụng gam()cho mô hình này, nhưng sẽ mất nhiều thời gian hơn để phù hợp.

knots <- list(DoY = c(0.5, 366.5))
M <- list(c(1, 0.5), NA)
m <- bam(MEASUREMENT ~
         s(ToD, k = 10) +
         s(DoY, k = 30, bs = 'cc') +
         s(YEAR, k = 30) +
         s(LONGITUDE, LATITUDE, k = 100, bs = 'ds', m = c(1, 0.5)) +
         ti(DoY, YEAR, bs = c('cc', 'tp'), k = c(15, 15)) +
         ti(LONGITUDE, LATITUDE, ToD, d = c(2,1), bs = c('ds','tp'), 
            m = M, k = c(20, 10)) +
         ti(LONGITUDE, LATITUDE, DoY, d = c(2,1), bs = c('ds','cc'),
            m = M, k = c(25, 15)) +
         ti(LONGITUDE, LATITUDE, YEAR, d = c(2,1), bs = c('ds','tp'),
            m = M), k = c(25, 15)),
         data = galveston, method = 'fREML', knots = knots,
         nthreads = 4, discrete = TRUE)

Các s()thuật ngữ là các hiệu ứng chính, trong khi các ti()thuật ngữ là các tương tác sản phẩm tenor trơn tru trong đó các hiệu ứng chính của các hiệp phương thức được đặt tên đã bị loại bỏ khỏi cơ sở. Các độ ti()mịn này là một cách để bao gồm các tương tác của các biến đã nêu theo cách ổn định về số.

Đối knotstượng chỉ đang thiết lập các điểm cuối của chu kỳ trơn mà tôi đã sử dụng cho hiệu ứng ngày của năm - chúng tôi muốn 23:59 ngày 31 tháng 12 để tham gia suôn sẻ với 00:01 ngày 1 tháng 1. Điều này đến một mức độ nào đó trong năm nhuận.

Tóm tắt mô hình cho thấy tất cả các hiệu ứng này là đáng kể;

> summary(m)

Family: gaussian 
Link function: identity 

Formula:
MEASUREMENT ~ s(ToD, k = 10) + s(DoY, k = 12, bs = "cc") + s(YEAR, 
    k = 30) + s(LONGITUDE, LATITUDE, k = 100, bs = "ds", m = c(1, 
    0.5)) + ti(DoY, YEAR, bs = c("cc", "tp"), k = c(12, 15)) + 
    ti(LONGITUDE, LATITUDE, ToD, d = c(2, 1), bs = c("ds", "tp"), 
        m = list(c(1, 0.5), NA), k = c(20, 10)) + ti(LONGITUDE, 
    LATITUDE, DoY, d = c(2, 1), bs = c("ds", "cc"), m = list(c(1, 
        0.5), NA), k = c(25, 12)) + ti(LONGITUDE, LATITUDE, YEAR, 
    d = c(2, 1), bs = c("ds", "tp"), m = list(c(1, 0.5), NA), 
    k = c(25, 15))

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 21.75561    0.07508   289.8   <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(ToD)                        3.036   3.696    5.956 0.000189 ***
s(DoY)                        9.580  10.000 3520.098  < 2e-16 ***
s(YEAR)                      27.979  28.736   59.282  < 2e-16 ***
s(LONGITUDE,LATITUDE)        54.555  99.000    4.765  < 2e-16 ***
ti(DoY,YEAR)                131.317 140.000   34.592  < 2e-16 ***
ti(ToD,LONGITUDE,LATITUDE)   42.805 171.000    0.880  < 2e-16 ***
ti(DoY,LONGITUDE,LATITUDE)   83.277 240.000    1.225  < 2e-16 ***
ti(YEAR,LONGITUDE,LATITUDE)  84.862 329.000    1.101  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =   0.94   Deviance explained = 94.2%
fREML =  29807  Scale est. = 2.6318    n = 15276

Một phân tích cẩn thận hơn sẽ muốn kiểm tra nếu chúng ta cần tất cả các tương tác này; một số ti()thuật ngữ không gian chỉ giải thích một lượng nhỏ biến thể trong dữ liệu, như được chỉ ra bởi thống kê ; có rất nhiều dữ liệu ở đây vì vậy ngay cả kích thước hiệu ứng nhỏ cũng có thể có ý nghĩa thống kê nhưng không thú vị.F

Tuy nhiên, khi kiểm tra nhanh, loại bỏ ba độ ti()mịn không gian ( m.sub), dẫn đến kết quả kém hơn đáng kể theo đánh giá của AIC:

> AIC(m, m.sub)
            df      AIC
m     447.5680 58583.81
m.sub 239.7336 59197.05

Chúng ta có thể vẽ các hiệu ứng một phần của năm độ mịn đầu tiên bằng plot()phương pháp - độ mịn của sản phẩm kéo căng 3D không thể được vẽ dễ dàng và không theo mặc định.

plot(m, pages = 1, scheme = 2, shade = TRUE, scale = 0)

nhập mô tả hình ảnh ở đây

Đối scale = 0số ở đó đặt tất cả các ô trên thang đo của riêng chúng, để so sánh cường độ của các hiệu ứng, chúng ta có thể tắt điều này:

plot(m, pages = 1, scheme = 2, shade = TRUE)

nhập mô tả hình ảnh ở đây

Bây giờ chúng ta có thể thấy rằng hiệu ứng theo mùa chiếm ưu thế. Xu hướng dài hạn (trung bình) được thể hiện trong cốt truyện phía trên bên phải. Tuy nhiên, để thực sự nhìn vào xu hướng dài hạn, bạn cần chọn một trạm và sau đó dự đoán từ mô hình cho trạm đó, ấn định thời gian trong ngày và ngày trong năm với một số giá trị đại diện (giữa trưa, cho một ngày trong năm vào mùa hè Nói). Đầu năm hoặc hai trong số đó có một số giá trị nhiệt độ thấp so với phần còn lại của hồ sơ, có khả năng sẽ được chọn trong tất cả các thông tin liên quan YEAR. Những dữ liệu này nên được xem xét kỹ hơn.

Đây thực sự không phải là nơi để đi vào đó, nhưng đây là một vài hình ảnh của mô hình phù hợp. Đầu tiên tôi xem xét mô hình không gian của nhiệt độ và cách nó thay đổi qua các năm của chuỗi. Để làm điều đó, tôi dự đoán từ mô hình cho lưới 100x100 trên miền không gian, vào giữa trưa ngày 180 mỗi năm:

pdata <- with(galveston,
              expand.grid(ToD = 12,
                          DoY = 180,
                          YEAR = seq(min(YEAR), max(YEAR), by = 1),
                          LONGITUDE = seq(min(LONGITUDE), max(LONGITUDE), length = 100),
                          LATITUDE  = seq(min(LATITUDE), max(LATITUDE), length = 100)))
fit <- predict(m, pdata)

sau đó tôi đặt thành thiếu, NAcác giá trị dự đoán fitcho tất cả các điểm dữ liệu nằm cách xa các quan sát (tỷ lệ; dist)

ind <- exclude.too.far(pdata$LONGITUDE, pdata$LATITUDE,
                       galveston$LONGITUDE, galveston$LATITUDE, dist = 0.1)
fit[ind] <- NA

và tham gia dự đoán dữ liệu dự đoán

pred <- cbind(pdata, Fitted = fit)

Đặt các giá trị dự đoán thành NAnhư thế này sẽ ngăn chúng ta ngoại suy ngoài sự hỗ trợ của dữ liệu.

Sử dụng ggplot2

ggplot(pred, aes(x = LONGITUDE, y = LATITUDE)) +
    geom_raster(aes(fill = Fitted)) + facet_wrap(~ YEAR, ncol = 12) +
    scale_fill_viridis(name = expression(degree*C), option = 'plasma',
                       na.value = 'transparent') +
    coord_quickmap() +
    theme(legend.position = 'top', legend.key.width = unit(2, 'cm'))

chúng tôi có được những điều sau đây

nhập mô tả hình ảnh ở đây

Chúng ta có thể thấy sự thay đổi nhiệt độ theo từng năm một cách chi tiết hơn một chút nếu chúng ta làm động chứ không phải là khía cạnh của cốt truyện

p <- ggplot(pred, aes(x = LONGITUDE, y = LATITUDE, frame = YEAR)) +
    geom_raster(aes(fill = Fitted)) +
    scale_fill_viridis(name = expression(degree*C), option = 'plasma',
                       na.value = 'transparent') +
    coord_quickmap() +
    theme(legend.position = 'top', legend.key.width = unit(2, 'cm'))+
    labs(x = 'Longitude', y = 'Latitude')

gganimate(p, 'galveston.gif', interval = .2, ani.width = 500, ani.height = 800)

nhập mô tả hình ảnh ở đây

Để xem xét các xu hướng dài hạn chi tiết hơn, chúng ta có thể dự đoán cho các trạm cụ thể. Ví dụ: trong STATION_ID13364 và dự đoán các ngày trong bốn quý, chúng tôi có thể sử dụng cách sau để chuẩn bị các giá trị của các hiệp phương thức mà chúng tôi muốn dự đoán vào (giữa trưa, vào ngày của năm 1, 90, 180 và 270, tại trạm đã chọn và đánh giá xu hướng dài hạn ở 500 giá trị cách đều nhau)

pdata <- with(galveston,
              expand.grid(ToD = 12,
                          DoY = c(1, 90, 180, 270),
                          YEAR = seq(min(YEAR), max(YEAR), length = 500),
                          LONGITUDE = -94.8751,
                          LATITUDE  = 29.50866))

Sau đó, chúng tôi dự đoán và yêu cầu các lỗi tiêu chuẩn, để hình thành khoảng tin cậy 95% theo điểm gần đúng

fit <- data.frame(predict(m, newdata = pdata, se.fit = TRUE))
fit <- transform(fit, upper = fit + (2 * se.fit), lower = fit - (2 * se.fit))
pred <- cbind(pdata, fit)

mà chúng tôi âm mưu

ggplot(pred, aes(x = YEAR, y = fit, group = factor(DoY))) +
    geom_ribbon(aes(ymin = lower, ymax = upper), fill = 'grey', alpha = 0.5) +
    geom_line() + facet_wrap(~ DoY, scales = 'free_y') +
    labs(x = NULL, y = expression(Temperature ~ (degree * C)))

sản xuất

nhập mô tả hình ảnh ở đây

Rõ ràng, có nhiều thứ để mô hình hóa các dữ liệu này hơn những gì tôi trình bày ở đây và chúng tôi muốn kiểm tra sự tự động còn sót lại và quá mức của các spline, nhưng tiếp cận vấn đề vì một trong những mô hình hóa các tính năng của dữ liệu cho phép chi tiết hơn kiểm tra các xu hướng.

Tất nhiên bạn có thể chỉ mô hình từng cái STATION_IDriêng biệt, nhưng điều đó sẽ làm mất dữ liệu và nhiều trạm có ít quan sát. Ở đây, mô hình mượn từ tất cả các thông tin của trạm để điền vào các khoảng trống và hỗ trợ ước tính các xu hướng quan tâm.

Một số lưu ý về bam()

Các bam()mô hình được sử dụng tất cả mgcv thủ đoạn 's để ước lượng mô hình một cách nhanh chóng (nhiều chủ đề 4 ), lựa chọn êm ái REML nhanh ( method = 'fREML'), và rời rạc của biến số. Với các tùy chọn này, mô hình sẽ vừa trong chưa đầy một phút trên máy trạm Xeon 4 nhân kép thời đại 2013 của tôi với RAM 64Gb.


0

Bạn chỉ có thể sử dụng chức năng decomposephân tách chuỗi thời gian của mình theo ba thành phần, xu hướng, theo mùa và ngẫu nhiên. Bạn cũng có thể trích xuất các giá trị khác nhau từ kết quả và vẽ chúng. Hãy chắc chắn rằng bạn xác định dữ liệu của bạn là một chuỗi thời gian. Chức năng stlvề cơ bản là làm tương tự nhưng cho phép bạn linh hoạt hơn trong cách bạn có thể phân tách dữ liệu của mình.

Tôi cũng giới thiệu trang web sau

https://www.otexts.org/fpp/6

Không giúp đỡ à?


Cảm ơn câu trả lời. Tôi đang xem qua trang web bây giờ. Thách thức là ở đây: có những lỗ hổng trong dữ liệu kéo dài hàng tháng hoặc thậm chí toàn bộ các mùa mà họ không thu thập bất kỳ dữ liệu nào, điều đó khiến tôi khó có thể tìm hiểu cách xử lý cửa sổ thời gian thay đổi.
griseus

0

Một lựa chọn sẽ là sử dụng chiến lược hồi quy xử lý dữ liệu của bạn dưới dạng rút ra từ hàm cơ bản liên tục (xem thảo luận tại đây: Có tiêu chuẩn vàng nào để mô hình chuỗi thời gian cách nhau không đều không? ). Từ đó, bạn có thể sử dụng một phương pháp như Phân tích phổ số ít để phân tách tín hiệu (đối với R: https://cran.r-project.org/web/packages/Rssa/index.html ).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.