循環/定期的な時系列を平滑化する


9

自動車事故の時間別データがあります。予想通り、それらは一日の真ん中に高く、ラッシュアワーにピークを迎えます。ggplot2のデフォルトのgeom_densityはそれを滑らかにします

飲酒運転に関連するクラッシュのデータのサブセットは、1日の終わり(夕方と早朝)に高く、極端に高くなります。しかし、ggplot2のデフォルトのgeom_densityは、依然として右端にあります。

これについて何をしますか?目的は単に視覚化であり、堅牢な統計分析の必要はありません(ありますか?)。

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))

統計ボキャブラリーが優れている人なら誰でもこの質問、特にタイトルとタグを編集できてうれしいです。

回答:


6

(任意のプラットフォームで)定期的にスムーズにするには、データを自分自身に追加し、長いリストを平滑化して、端を切り取ります。

これがRイラストです:

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")

(これらはカウントされているので、私は彼らの平方根を滑らかにすることを選んだ。彼らは、プロットするためにカウントに変換戻った。)におけるスパンはlowess、そのデフォルト値から大幅に縮小されているf=2/3()私たちが今いるべき3倍長い配列を処理しているので、をに減らします。(b)かなり局所的な滑らかさを求めて、中央の3分の1にかなりのエンドポイント効果が現れないようにします。f2/9

これらのデータについては、かなりうまくいきました。特に、0時間の異常は完全に平滑化されています。

プロット


これは、単純な視覚化に対する私のニーズに応えますが、興味の対象ではありませんが、それは少し厄介ですか?Nickのリンクからのものを使用すると、エンドポイントの影響が回避されますか?
nacnudus 2013

1
これは、@ whuberのようにウィンドウの幅が慎重に選択されている限り、私が使用した方法とまったく同じです。しかし、Rソフトウェアは私がしたことを行うためにすぐに利用できます。(私はもともとそれを見つけるタスクをRの専門家に委任していましたが、彼らは気づきませんでした。)
Nick Cox

3
kk1k1

1
@whuberなるほど。実際のデータの前後にコピーとして追加するものは、どれだけスムーズにするかと一貫していなければならないという自明の理をほのめかしていました。
Nick Cox

7

私は日常的にRを使用していませんが、使用したことはありませんggplotが、ここには簡単な話があるようです。

時刻は明らかに循環変数または周期変数です。あなたのデータには、ラップアラウンドする時間0(1)23があるため、23の後に0が続きます。しかし、ggplot少なくとも、あなたが与えた情報からはそれがわかりません。それに関する限り、-1、-2など、または24、25などの値が存在する可能性があるため、確率の一部は、観測されたデータの制限を超えて、実際には、可能なデータ。

これはメインデータでも発生しますが、それほど目立ちません。

そのようなデータのカーネル密度推定が必要な場合は、そのような周期的変数または循環変数を適切に処理するのに十分にスマートなルーチンが必要です。「適切に」とは、0が23に続くことを認識して、ルーチンが円形空間で平滑化することを意味します。境界の問題がないため(境界がないため)、このような分布の平滑化は通常の場合よりも簡単です。Rで使用する関数についてアドバイスできる人もいます。

この種のデータは、定期的な時系列と循環統計の中間にあります。

提示されたデータには99の観測があります。そのため、ヒストグラムは非常にうまく機能しますが、少し滑らかにした方がよいかもしれません。

ここに画像の説明を入力してください

(更新)それは好みと判断の問題ですが、私はあなたの滑らかな曲線が大幅に過度に平滑化されていると思います。

ここにサンプルとして、バイウェイト密度推定があります。私はアドホック変換15 *(時間+ 0.5)で度単位の循環データに自分のStataプログラムを使用しましたが、密度は1時間あたりで表されます。対照的に、これは少しスムーズではありませんが、選択を調整できます。

ここに画像の説明を入力してください


1
それはスムーズすぎることに同意しますが、それは私が得ている原則です。有用な語彙(循環的、定期的)をググリングすると、この種の問題に対する意外な関心はほとんどなくなりますが、Rのアドバイスを聞いてくれる人がいるのをもう少し待ちます。
nacnudus 2013


5

Tukeyの4253Hを3回連結して2回生カウントをコピーし、中間値の平滑化された値のセットを取得すると、カウントの平方根でのwhuberのロウワーとほぼ同じ画像が得られます。
ここに画像の説明を入力してください


2
+1私はTukeyのスムーザーを好み、ここに表示される例を見てうれしいです。
whuber

1
この正確なレシピは、Paul F. Vellemanによって考案されましたが、間違いなくTukeyの指導の下にありました。「42」は階段のアーチファクトを削減します。
Nick Cox

2

さらに、より複雑な代替案として、提案されているものの代わりに、周期的スプラインを検討することもできます。あなたは、Rパッケージでそれらを合わせてツールを見つけることができますsplinesA及びmgcv。すでに提案されているアプローチよりも優れている点は、「3コピー」法では明らかではない、フィットの自由度を計算できることです。


1
(+1)いくつかのコメント:まず、「3つのコピー」は特定のアプリケーションであり、一般的な規則ではありません。第2に、DFの計算は同じくらい簡単だと思います。データの量は同じで、1つはスプラインの近似に使用されるパラメーターの数を差し引きます。
whuber

@whuber:最後のビットの実行方法(スプラインを「3つのコピー」に適合させる場合に、スプラインの適合に使用されるパラメーターを計算する方法)は私には明確ではありません。
F.チューセル2013

1
コピー部分はデータ量を変更しないので、DFを推定する上で重要なことは、スプラインで使用されるパラメーターをカウントすることだけです。
whuber

1

さらに別のアプローチとして、周期的スプライン(F.Tusellの回答で提案)がありますが、ここではRでの実装も示します。ポアソンglmを使用してヒストグラムカウントに適合させ、次の滑らかなヒストグラムを作成します。

ここに画像の説明を入力してください

使用されるコード(x問題のデータオブジェクトから開始):

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")} )
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.