Làm mịn một chuỗi thời gian tuần hoàn / định kỳ


9

Tôi có dữ liệu cho các vụ tai nạn xe máy theo giờ trong ngày. Như bạn mong đợi, chúng ở mức cao vào giữa ngày và cao điểm vào giờ cao điểm. Geom_d mật độ mặc định của ggplot2 làm mịn nó ra

Một tập hợp con của dữ liệu, cho các sự cố liên quan đến đồ uống, cao vào cuối ngày (buổi tối và buổi sáng sớm) và cao nhất ở các thái cực. Nhưng geom_d mật độ mặc định của ggplot2 vẫn giảm ở cực bên phải.

Phải làm gì về điều này? Mục đích chỉ đơn thuần là trực quan hóa - không cần (có?) Để phân tích thống kê mạnh mẽ.

Imgur

x <- structure(list(hour = c(14, 1, 1, 9, 2, 11, 20, 5, 22, 13, 21, 
                        2, 22, 10, 18, 0, 2, 1, 2, 15, 20, 23, 17, 3, 3, 16, 19, 23, 
                        3, 4, 4, 22, 2, 21, 20, 1, 19, 18, 17, 23, 23, 3, 11, 4, 23, 
                        4, 7, 2, 3, 19, 2, 18, 3, 17, 1, 9, 19, 23, 9, 6, 2, 1, 23, 21, 
                        22, 22, 22, 20, 1, 21, 6, 2, 22, 23, 19, 17, 19, 3, 22, 21, 4, 
                        10, 17, 23, 3, 7, 19, 16, 2, 23, 4, 5, 1, 20, 7, 21, 19, 2, 21)
               , count = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
                           1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
                           1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
                           1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
                           1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
                           1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
                           1L, 1L, 1L, 1L, 1L, 1L, 1L))
          , .Names = c("hour", "count")
          , row.names = c(8L, 9L, 10L, 29L, 33L, 48L, 51L, 55L, 69L, 72L, 97L, 108L, 113L, 
                          118L, 126L, 140L, 150L, 171L, 177L, 184L, 202L, 230L, 236L, 240L, 
                          242L, 261L, 262L, 280L, 284L, 286L, 287L, 301L, 318L, 322L, 372L, 
                          380L, 385L, 432L, 448L, 462L, 463L, 495L, 539L, 557L, 563L, 566L, 
                          570L, 577L, 599L, 605L, 609L, 615L, 617L, 624L, 663L, 673L, 679L, 
                          682L, 707L, 730L, 733L, 746L, 754L, 757L, 762L, 781L, 793L, 815L, 
                          817L, 823L, 826L, 856L, 864L, 869L, 877L, 895L, 899L, 918L, 929L, 
                          937L, 962L, 963L, 978L, 980L, 981L, 995L, 1004L, 1005L, 1007L, 
                          1008L, 1012L, 1015L, 1020L, 1027L, 1055L, 1060L, 1078L, 1079L, 
                          1084L)
          , class = "data.frame")

ggplot(x, aes(hour)) + 
  geom_bar(binwidth = 1, position = "dodge", fill = "grey") +
  geom_density() + 
  aes(y = ..count..) +
  scale_x_continuous(breaks = seq(0,24,4))

Chúc mừng cho bất cứ ai có từ vựng thống kê tốt hơn để chỉnh sửa câu hỏi này, đặc biệt là tiêu đề và thẻ.

Câu trả lời:


6

Để làm cho định kỳ trơn tru (trên bất kỳ nền tảng nào), chỉ cần nối thêm dữ liệu vào chính chúng, làm mịn danh sách dài hơn và cắt bỏ các kết thúc.

Đây là một Rminh họa:

y <- sqrt(table(factor(x[,"hour"], levels=0:23)))
y <- c(y,y,y)
x.mid <- 1:24; offset <- 24
plot(x.mid-1, y[x.mid+offset]^2, pch=19, xlab="Hour", ylab="Count")
y.smooth <- lowess(y, f=1/8)
lines(x.mid-1, y.smooth$y[x.mid+offset]^2, lwd=2, col="Blue")

(Bởi vì đây là số đếm tôi đã chọn để làm mịn căn bậc hai của chúng; chúng được chuyển đổi thành số đếm để vẽ.) Khoảng thời gian lowessđã bị thu hẹp đáng kể so với mặc định của nó f=2/3bởi vì (a) chúng tôi hiện đang xử lý một mảng dài hơn ba lần, nên khiến chúng tôi giảm xuống và (b) Tôi muốn một sự mượt mà cục bộ để không có hiệu ứng điểm cuối đáng chú ý nào xuất hiện ở giữa thứ ba.2 / 9f2/9

Nó đã làm một công việc khá tốt với những dữ liệu này. Đặc biệt, sự bất thường ở giờ 0 đã được làm mịn ngay.

Âm mưu


Điều này trả lời nhu cầu của tôi về một hình ảnh đơn giản, nhưng không quan tâm, nó có phải là một chút bùn không? Việc sử dụng thứ gì đó từ liên kết của Nick sẽ tránh được các hiệu ứng điểm cuối?
xà cừ

1
Điều này hoàn toàn tương đương với phương pháp tôi đã sử dụng miễn là chiều rộng cửa sổ được chọn cẩn thận, như @whuber đã làm. Nhưng phần mềm R có sẵn để làm những gì tôi đã làm. (Ban đầu tôi được giao nhiệm vụ tìm kiếm nó cho các chuyên gia R, nhưng họ không để ý.)
Nick Cox

3
Tôi không xem nó như một kluge: kỹ thuật này dựa trên định nghĩa về tính tuần hoàn. Nó hoạt động cho bất kỳ địa phương trơn tru. (Nó sẽ không hoạt động cho toàn cầu trơn tru, nhưng đó không phải là vấn đề, bởi vì hầu hết các công cụ làm mịn toàn cầu đều bắt nguồn từ các phương pháp định kỳ vốn có như loạt Fourier.) @Nick One không cần phải hết sức cẩn thận: khi sử dụng một cách mượt mà cục bộ nửa chiều rộng tối đa , người ta chỉ cần xử lý các giá trị cuối cùng của chuỗi vào đầu và đầu tiên vào cuối, nhưng không có hại gì khi mở rộng chuỗi một cách bảo mật hơn - nó chỉ kém hiệu quả hơn . k - 1 k - 1kk1k1
whuber

1
@whuber Khá vậy. Tôi chỉ ám chỉ sự thật rằng những gì bạn thêm vào như bản sao trước và sau dữ liệu thực tế phải phù hợp với mức độ bạn làm trơn tru.
Nick Cox

7

Tôi không sử dụng R thường xuyên và tôi chưa bao giờ sử dụng ggplot, nhưng có một câu chuyện đơn giản ở đây, hoặc tôi đoán vậy.

Thời gian trong ngày rõ ràng là một biến số tuần hoàn hoặc định kỳ. Trong dữ liệu của bạn, bạn có giờ 0 (1) 23 bao quanh, do đó 23 được theo sau bởi 0. Tuy nhiên, ggplotkhông biết rằng, ít nhất là từ thông tin bạn đã cung cấp. Theo như có liên quan, có thể có các giá trị ở -1, -2, v.v. hoặc ở 24, 25, v.v. và do đó, một số xác suất có thể được làm mịn vượt quá giới hạn của dữ liệu được quan sát và thực sự vượt quá giới hạn của các dữ liệu có thể.

Điều này cũng sẽ xảy ra với dữ liệu chính của bạn, nhưng nó không hoàn toàn đáng chú ý.

Nếu bạn muốn ước tính mật độ hạt nhân cho dữ liệu đó, bạn cần một thói quen đủ thông minh để xử lý các biến tuần hoàn hoặc tuần hoàn như vậy. "Đúng" có nghĩa là thói quen làm mịn trên một không gian tròn, nhận ra rằng 0 theo 23. Trong một số cách, việc làm mịn các phân phối như vậy dễ dàng hơn so với trường hợp thông thường, vì không có vấn đề về ranh giới (vì không có ranh giới). Những người khác sẽ có thể tư vấn về các chức năng để sử dụng trong R.

Loại dữ liệu này nằm ở đâu đó giữa chuỗi thời gian định kỳ và thống kê vòng tròn.

Các dữ liệu được trình bày có 99 quan sát. Cho rằng một biểu đồ hoạt động khá tốt, mặc dù tôi có thể thấy rằng bạn có thể muốn làm mịn nó một chút.

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

(CẬP NHẬT) Đó là vấn đề của hương vị và sự phán xét nhưng tôi sẽ xem xét đường cong mượt mà của bạn quá mức.

Đây là một mẫu ước tính mật độ sinh học. Tôi đã sử dụng chương trình Stata của riêng mình cho dữ liệu tròn theo độ với chuyển đổi ad hoc 15 * (giờ + 0,5) nhưng mật độ thể hiện mỗi giờ. Điều này ngược lại là một chút ít, nhưng bạn có thể điều chỉnh các lựa chọn của bạn.

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


1
Đồng ý rằng nó quá sức, nhưng đó là nguyên tắc tôi đang hướng tới. Một số googling của vocab hữu ích của bạn (tuần hoàn, định kỳ) phát hiện ra một chút ngạc nhiên ít quan tâm đến loại vấn đề này, nhưng tôi sẽ chờ thêm một thời gian nữa để bất cứ ai nghe theo lời khuyên của R.
Nacnudus


5

Thực hiện 4253H của Tukey, hai lần trên ba bản sao được ghép nối các số liệu thô và sau đó lấy tập hợp các giá trị được làm mịn ở giữa sẽ mang lại hình ảnh tương tự như mức độ thấp của các hàm số trên căn bậc hai của số đếm.
nhập mô tả hình ảnh ở đây


2
+1 Tôi thích máy làm mịn của Tukey và rất vui khi thấy một ví dụ về một chiếc được hiển thị ở đây.
whuber

1
Công thức chính xác này đã được Paul F. Velleman nghĩ ra, nhưng chắc chắn dưới sự hướng dẫn của Tukey. "42" cắt giảm các đồ tạo tác ở bậc thang.
Nick Cox

2

Ngoài ra, và như là một giải pháp thay thế phức tạp hơn, đối với những gì đã được đề xuất, bạn có thể muốn tìm đến các spline định kỳ. Bạn có thể tìm công cụ để phù hợp chúng trong các gói R splinesaand mgcv. Ưu điểm tôi thấy trên các phương pháp đã được đề xuất là bạn có thể tính toán mức độ tự do của sự phù hợp, điều này không rõ ràng với phương pháp 'ba bản sao'.


1
(+1) Một số ý kiến: Đầu tiên, "ba bản sao" là một ứng dụng cụ thể, không phải là quy tắc chung. Thứ hai, tôi tin rằng phép tính DF chỉ đơn giản như vậy: lượng dữ liệu vẫn giữ nguyên và người ta trừ đi số lượng tham số được sử dụng để khớp spline.
whuber

@whuber: tôi không rõ cách thực hiện bit cuối cùng (cách tính các tham số được sử dụng khớp với spline nếu bạn khớp với "ba bản sao").
F. Tusell

1
Phần sao chép không thay đổi lượng dữ liệu, vì vậy tất cả những gì quan trọng trong việc ước tính DF là để đếm các tham số được sử dụng bởi các spline.
whuber

1

Vẫn là một cách tiếp cận khác, các spline định kỳ (như được đề xuất trong câu trả lời của F.Tusell), nhưng ở đây chúng tôi cũng cho thấy một triển khai trong R. Chúng tôi sẽ sử dụng một glm Poisson để phù hợp với số lượng biểu đồ, dẫn đến biểu đồ sau rất trơn tru:

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

Mã được sử dụng (bắt đầu với đối tượng dữ liệu xđược đưa ra trong câu hỏi):

library(pbs) # basis for periodic spline

x.tab <- with(x, table(factor(hour,levels=as.character(0:23))))
x.df <- data.frame(time=0:23, count=as.vector(x.tab))
mod.hist <- with(x.df, glm(count ~ pbs::pbs(time, df=4, Boundary.knots=c(0,24)), family=poisson))
pred <- predict(mod.hist, type="response", newdata=data.frame(time=0:24))

with(x.df, {plot(time, count,type="h",col="blue", main="Histogram") ; lines(time, pred[1:24], col="red")} )
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.