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( ToDTôi) + f2( DoYTôi) + f3( NămTôi) + f4( xTôi, yTôi) +f5( DoYTôi, NămTôi) + f6( xTôi, yTôi, ToDTôi) +f7( xTôi, yTôi, ĐỗTôi) + fsố 8( xTôi,yTôi,NămTôi)
Ở đâu
- α là mô hình chặn,
- f1( ToDTô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, ToDTôi) sản phẩm trơn tru về vị trí và thời gian trong ngày
- f7( xTôi, yTôi, ĐỗTô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
- thời gian trong ngày,
- Mùa,
- xu hướng dài hạn,
- 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
- mô hình nhiệt độ theo mùa thay đổi theo thời gian như thế nào
- Làm thế nào thời gian của hiệu ứng trong ngày thay đổi theo không gian,
- hiệu ứng theo mùa thay đổi theo không gian và
- 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 knots
tượ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)
Đối scale = 0
số ở đó đặ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)
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, NA
các giá trị dự đoán fit
cho 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 NA
như 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
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)
Để 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_ID
13364 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
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_ID
riê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.