二変量正規分布データから楕円領域を取得する方法は?


11

私は次のようなデータを持っています:

図

私は正規分布を適用しようとしました(カーネル密度の推定はうまく機能しますが、それほど高い精度は必要ありません)。これは非常にうまく機能します。密度プロットは楕円を作成します。

その楕円関数を取得して、点が楕円の領域内にあるかどうかを判断する必要があります。どうやってするか?

RまたはMathematicaコードを歓迎します。

回答:


18

Corsarioはコメントで優れたソリューションを提供します。カーネル密度関数を使用して、レベルセットに含まれるかどうかをテストします。

質問の別の解釈は、データへの2変量正規近似によって作成された楕円内に含まれるかどうかをテストする手順を要求するというものです。はじめに、質問の図のようなデータを生成してみましょう。

library(mvtnorm) # References rmvnorm()
set.seed(17)
p <- rmvnorm(1000, c(250000, 20000), matrix(c(100000^2, 22000^2, 22000^2, 6000^2),2,2))

楕円は、データの1次モーメントと2次モーメントによって決まります。

center <- apply(p, 2, mean)
sigma <- cov(p)

この式では、分散共分散行列の反転が必要です。

sigma.inv = solve(sigma, matrix(c(1,0,0,1),2,2))

楕円の「高さ」関数は、2変量正規密度の対数の負です。

ellipse <- function(s,t) {u<-c(s,t)-center; u %*% sigma.inv %*% u / 2}

(私は等しい追加の定数を無視しました。)log(2πdet(Σ))

これをテストするために、いくつかの輪郭を描きましょう。そのためには、x方向とy方向に点のグリッドを生成する必要があります。

n <- 50
x <- (0:(n-1)) * (500000/(n-1))
y <- (0:(n-1)) * (50000/(n-1))

このグリッドで高さ関数を計算してプロットします。

z <- mapply(ellipse, as.vector(rep(x,n)), as.vector(outer(rep(0,n), y, `+`)))
plot(p, pch=20, xlim=c(0,500000), ylim=c(0,50000), xlab="Packets", ylab="Flows")
contour(x,y,matrix(z,n,n), levels=(0:10), col = terrain.colors(11), add=TRUE)

等高線図

明らかに機能します。したがって、点レベル楕円形の輪郭の内側にあるかどうかを判断するテストは、(s,t)c

ellipse(s,t) <= c

Mathematicaは同じ方法で仕事をします:データの分散共分散行列を計算し、それを逆にし、ellipse関数を構築すれば、あなたはすべて準備が整いました。


皆さん、特に@whuberに感謝します。これはまさに私が必要とするものです。
matejuh 2012年

ところで カーネル密度推定コンターの簡単な解決策はありますか?より厳密にしたい場合、私のデータは次のようになります。github.com / matejuh / doschecker_wiki_images / raw / master / resp。github.com/matejuh/doschecker_wiki_images/raw/master/...
matejuh

私はR.でシンプルなソリューションを使用することを検討してください見つけることができないのMathematica 8の「SmoothKernelDistribution」機能を。
whuber

2
レベルは信頼レベルに対応していますか?私はそうは思いません。どうすればいいですか?
matejuh

信頼性を求めるものを指定する必要があり、プロットから判断すると、最初にそのような楕円がデータの適切な説明であるかどうかについて懸念があるため、これには新しい質問が必要です。
whuber

9

プロットは、R ellipse()mixtoolsパッケージの関数で簡単です。

library(mixtools)
library(mvtnorm) 
set.seed(17)
p <- rmvnorm(1000, c(250000, 20000), matrix(c(100000^2, 22000^2, 22000^2, 6000^2),2,2))
plot(p, pch=20, xlim=c(0,500000), ylim=c(0,50000), xlab="Packets", ylab="Flows")
ellipse(mu=colMeans(p), sigma=cov(p), alpha = .05, npoints = 250, col="red") 

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


5

最初のアプローチ

Mathematicaでこのアプローチを試すかもしれません。

いくつかの二変量データを生成しましょう:

data = Table[RandomVariate[BinormalDistribution[{50, 50}, {5, 10}, .8]], {1000}];

次に、このパッケージをロードする必要があります。

Needs["MultivariateStatistics`"]

そしていま:

ellPar=EllipsoidQuantile[data, {0.9}]

90%の信頼楕円を定義する出力を提供します。この出力から取得する値は、次の形式です。

{Ellipsoid[{x1, x2}, {r1, r2}, {{d1, d2}, {d3, d4}}]}

x1とx2は楕円が中心に置かれる点を指定し、r1とr2は半軸半径を指定し、d1、d2、d3とd4は整列方向を指定します。

これをプロットすることもできます:

Show[{ListPlot[data, PlotRange -> {{0, 100}, {0, 100}}, AspectRatio -> 1],  Graphics[EllipsoidQuantile[data, 0.9]]}]

楕円の一般的なパラメトリック形式は次のとおりです。

ell[t_, xc_, yc_, a_, b_, angle_] := {xc + a Cos[t] Cos[angle] - b Sin[t] Sin[angle],
    yc + a Cos[t] Sin[angle] + b Sin[t] Cos[angle]}

そして、あなたはこのようにそれをプロットすることができます:

ParametricPlot[
    ell[t, ellPar[[1, 1, 1]], ellPar[[1, 1, 2]], ellPar[[1, 2, 1]], ellPar[[1, 2, 2]],
    ArcTan[ellPar[[1, 3, 1, 2]]/ellPar[[1, 3, 1, 1]]]], {t, 0, 2 \[Pi]},
    PlotRange -> {{0, 100}, {0, 100}}]

純粋な幾何学的情報に基づいてチェックを実行できます。楕円の中心(ellPar [[1,1]])とデータポイント間のユークリッド距離が、楕円の中心と境界の距離より大きい場合楕円(明らかに、ポイントが配置されているのと同じ方向)、そのデータポイントは楕円の外側にあります。

第二のアプローチ

このアプローチは、スムーズなカーネル配布に基づいています。

これらは、データと同様の方法で配布されるいくつかのデータです。

data1 = RandomVariate[BinormalDistribution[{.3, .7}, {.2, .3}, .8], 500];
data2 = RandomVariate[BinormalDistribution[{.6, .3}, {.4, .15}, .8], 500];
data = Partition[Flatten[Join[{data1, data2}]], 2];

これらのデータ値でスムーズなカーネル分布を取得します。

skd = SmoothKernelDistribution[data];

各データポイントの数値結果を取得します。

eval = Table[{data[[i]], PDF[skd, data[[i]]]}, {i, Length[data]}];

しきい値を修正し、このしきい値よりも高いすべてのデータを選択します。

threshold = 1.2;
dataIn = Select[eval, #1[[2]] > threshold &][[All, 1]];

ここでは、リージョン外のデータを取得します。

dataOut = Complement[data, dataIn];

これで、すべてのデータをプロットできます。

Show[ContourPlot[Evaluate@PDF[skd, {x, y}], {x, 0, 1}, {y, 0, 1}, PlotRange -> {{0, 1}, {0, 1}}, PlotPoints -> 50],
ListPlot[dataIn, PlotStyle -> Darker[Green]],
ListPlot[dataOut, PlotStyle -> Red]]

緑色の点はしきい値を超えている点であり、赤色の点はしきい値を下回っている点です。

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


ありがとう、あなたの2番目のアプローチは、カーネルの配布で私を大いに助けてくれます。私はプログラマーであり、統計学ではありません。私はMathmaticaとRの初心者なので、あなたの助けに感謝します。2番目のアプローチでは、それがある場所の1つのポイントをテストする方法は私には明らかです。しかし、それを最初のアプローチでどのように行うのですか?私の点を楕円体の定義と比較しなければならないと思います。どのように提供できますか?RinRubyで使用する必要があるため、Rにも同じ定義があることを期待する必要があります...
matejuh

@matejuh私はあなたを解決に導くかもしれない最初のアプローチについて数行追加しました。
VLC

2

R ellipseellipseパッケージ内の関数は、これらの楕円(実際には楕円を近似する多角形)を生成します。その楕円を使用できます。

実際に簡単なのは、ポイントでの密度の高さを計算して、楕円の輪郭値よりも高い(楕円の内側)か、低い(楕円の外側)かを確認することです。ellipse関数の内部で使用楕円を作成するための値を、使用する高さを見つけるためにそこに開始することができます。χ2


1

私は答えを見つけました:https : //stackoverflow.com/questions/2397097/how-can-a-data-ellipse-be-superimposed-on-a-ggplot2-scatterplot

#bootstrap
set.seed(101)
n <- 1000
x <- rnorm(n, mean=2)
y <- 1.5 + 0.4*x + rnorm(n)
df <- data.frame(x=x, y=y, group="A")
x <- rnorm(n, mean=2)
y <- 1.5*x + 0.4 + rnorm(n)
df <- rbind(df, data.frame(x=x, y=y, group="B"))

#calculating ellipses
library(ellipse)
df_ell <- data.frame()
for(g in levels(df$group)){
df_ell <- rbind(df_ell, cbind(as.data.frame(with(df[df$group==g,], ellipse(cor(x, y), 
                                         scale=c(sd(x),sd(y)), 
                                         centre=c(mean(x),mean(y))))),group=g))
}
#drawing
library(ggplot2)
p <- ggplot(data=df, aes(x=x, y=y,colour=group)) + geom_point(size=1.5, alpha=.6) +
  geom_path(data=df_ell, aes(x=x, y=y,colour=group), size=1, linetype=2)

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

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