Primera aproximación
Puedes probar este enfoque en Mathematica.
Vamos a generar algunos datos bivariados:
data = Table[RandomVariate[BinormalDistribution[{50, 50}, {5, 10}, .8]], {1000}];
Entonces tenemos que cargar este paquete:
Needs["MultivariateStatistics`"]
Y, ahora:
ellPar=EllipsoidQuantile[data, {0.9}]
da una salida que define una elipse de confianza del 90%. Los valores que se obtienen de esta salida tienen el siguiente formato:
{Ellipsoid[{x1, x2}, {r1, r2}, {{d1, d2}, {d3, d4}}]}
x1 y x2 especifican el punto en el que se centra la elipse, r1 y r2 especifican los radios del semieje, y d1, d2, d3 y d4 especifican la dirección de alineación.
También puedes trazar esto:
Show[{ListPlot[data, PlotRange -> {{0, 100}, {0, 100}}, AspectRatio -> 1], Graphics[EllipsoidQuantile[data, 0.9]]}]
La forma paramétrica general de la elipse es:
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]}
Y se puede trazar de esta manera:
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}}]
Podría realizar una comprobación basada en información puramente geométrica: si la distancia euclidiana entre el centro de la elipse (ellPar[[1,1]]) y su punto de datos es mayor que la distancia entre el centro de la elipse y el borde de la misma (obviamente, en la misma dirección en la que se encuentra su punto), entonces ese punto de datos está fuera de la elipse.
Segundo enfoque
Este enfoque se basa en la distribución kernel suave.
Estos son algunos datos distribuidos de forma similar a los suyos:
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];
Obtenemos una distribución kernel suave sobre estos valores de datos:
skd = SmoothKernelDistribution[data];
Obtenemos un resultado numérico para cada punto de datos:
eval = Table[{data[[i]], PDF[skd, data[[i]]]}, {i, Length[data]}];
Fijamos un umbral y seleccionamos todos los datos que sean superiores a este umbral:
threshold = 1.2;
dataIn = Select[eval, #1[[2]] > threshold &][[All, 1]];
Aquí obtenemos los datos que caen fuera de la región:
dataOut = Complement[data, dataIn];
Y ahora podemos trazar todos los datos:
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]]
Los puntos de color verde son los que están por encima del umbral y los puntos de color rojo son los que están por debajo del umbral.