Как получить область эллипса из двумерных нормальных распределенных данных?


12

У меня есть данные, которые выглядят так:

фигура

Я попытался применить нормальное распределение (оценка плотности ядра работает лучше, но мне не нужна такая большая точность), и это работает довольно хорошо. Плотность графика составляет эллипс.

Мне нужно получить эту функцию эллипса, чтобы решить, находится ли точка в области эллипса или нет. Как это сделать?

R или Mathematica код приветствуются.

Ответы:


18

Corsario предлагает хорошее решение в комментарии: используйте функцию плотности ядра для проверки на включение в набор уровней.

Другая интерпретация этого вопроса заключается в том, что он запрашивает процедуру проверки на включение в эллипсы, создаваемые двумерным нормальным приближением к данным. Для начала давайте сгенерируем некоторые данные, которые выглядят как иллюстрации в вопросе:

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

Эллипсы определяются первым и вторым моментами данных:

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

Формула требует инверсии дисперсионно-ковариационной матрицы:

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

Функция «высота» эллипса является отрицательной величиной логарифма двумерной нормальной плотности :

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

журнал⁡(2πйе(Σ))

Чтобы проверить это , давайте нарисуем некоторые его контуры. Это требует создания сетки точек в направлениях 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)с

ellipse(s,t) <= c

Mathematica выполняет свою работу аналогичным образом: вычисляет матрицу дисперсии-ковариации данных, инвертирует ее, создает ellipseфункцию, и все готово.


Спасибо всем, особенно @whuber. Это именно то, что мне нужно.
— matejuh

Btw. Есть ли простое решение для контуров оценки плотности ядра? Потому что, если я хочу быть более строгим, мои данные выглядят так: github.com/matejuh/doschecker_wiki_images/raw/master/… соответственно. github.com/matejuh/doschecker_wiki_images/raw/master/...
— matejuh

Я не могу найти простое решение в R. Рассмотрим использование функции SmoothKernelDistribution в Mathematica 8.
— whuber

2
Соответствует ли уровни уровню доверия? Я так не думаю. Как я могу это сделать, пожалуйста?
— matejuh

Это требует нового вопроса, потому что вам нужно указать, на что вы надеетесь, и, судя по вашим графикам, есть сомнения относительно того, являются ли такие эллипсы адекватными описаниями данных.
— whuber

9

Сюжет прост с ellipse()функцией mixtoolsпакета для R:

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

Точки зеленого цвета - это точки выше порога, а точки красного цвета - точки ниже порога.

введите описание изображения здесь


Спасибо, ваш второй подход очень помогает мне с распределением ядра. Я программист, а не статистик, и я новичок в Mathmatica и R, поэтому я очень ценю вашу помощь. В вашем втором подходе для меня ясно, как проверить одну точку, где она лежит. Но как это сделать при первом подходе? Я полагаю, что мне нужно сравнить мою точку зрения с определением эллипсоида. Можете ли вы предоставить, пожалуйста, как? Теперь я должен надеяться, что в R есть такие же определения, потому что мне нужно использовать его в RinRuby ...
— matejuh

@matejuh Я только добавил еще несколько строк о первом подходе, который может направить вас к решению.
— VLC

2

ellipseФункция в ellipseпакете для R будет генерировать эти эллипсы ( на самом деле многоугольник приближая эллипс). Вы могли бы использовать этот эллипс.

ellipseχ2


1

Я нашел ответ по адресу: /programming/2397097/how-can-a-data-ellipse-be-superimpposed-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)

введите описание изображения здесь

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.