Recherche de valeurs aberrantes sur un nuage de points

9

J'ai un ensemble de points de données qui sont censés s'asseoir sur un locus et suivre un modèle, mais il y a quelques points de dispersion du locus principal qui causent de l'incertitude dans mon analyse finale. Je voudrais obtenir un locus soigné pour l'appliquer plus tard pour mon analyse. Les points bleus sont plus ou moins les points de dispersion que je veux trouver et les exclure de manière sophistiquée sans le faire manuellement.entrez la description de l'image ici

Je pensais utiliser quelque chose comme la régression des voisins les plus proches, mais je ne sais pas si c'est la meilleure approche ou je ne sais pas très bien comment la mettre en œuvre pour me donner un résultat approprié. Au fait, je veux le faire sans aucune procédure de montage.

La version transposée des données est la suivante:

X=array([[ 0.87 , -0.01 ,  0.575,  1.212,  0.382,  0.418, -0.01 ,  0.474,
         0.432,  0.702,  0.574,  0.45 ,  0.334,  0.565,  0.414,  0.873,
         0.381,  1.103,  0.848,  0.503,  0.27 ,  0.416,  0.939,  1.211,
         1.106,  0.321,  0.709,  0.744,  0.309,  0.247,  0.47 , -0.107,
         0.925,  1.127,  0.833,  0.963,  0.385,  0.572,  0.437,  0.577,
         0.461,  0.474,  1.046,  0.892,  0.313,  1.009,  1.048,  0.349,
         1.189,  0.302,  0.278,  0.629,  0.36 ,  1.188,  0.273,  0.191,
        -0.068,  0.95 ,  1.044,  0.776,  0.726,  1.035,  0.817,  0.55 ,
         0.387,  0.476,  0.473,  0.863,  0.252,  0.664,  0.365,  0.244,
         0.238,  1.203,  0.339,  0.528,  0.326,  0.347,  0.385,  1.139,
         0.748,  0.879,  0.324,  0.265,  0.328,  0.815,  0.38 ,  0.884,
         0.571,  0.416,  0.485,  0.683,  0.496,  0.488,  1.204,  1.18 ,
         0.465,  0.34 ,  0.335,  0.447,  0.28 ,  1.02 ,  0.519,  0.335,
         1.037,  1.126,  0.323,  0.452,  0.201,  0.321,  0.285,  0.587,
         0.292,  0.228,  0.303,  0.844,  0.229,  1.077,  0.864,  0.515,
         0.071,  0.346,  0.255,  0.88 ,  0.24 ,  0.533,  0.725,  0.339,
         0.546,  0.841,  0.43 ,  0.568,  0.311,  0.401,  0.212,  0.691,
         0.565,  0.292,  0.295,  0.587,  0.545,  0.817,  0.324,  0.456,
         0.267,  0.226,  0.262,  0.338,  1.124,  0.373,  0.814,  1.241,
         0.661,  0.229,  0.416,  1.103,  0.226,  1.168,  0.616,  0.593,
         0.803,  1.124,  0.06 ,  0.573,  0.664,  0.882,  0.286,  0.139,
         1.095,  1.112,  1.167,  0.589,  0.3  ,  0.578,  0.727,  0.252,
         0.174,  0.317,  0.427,  1.184,  0.397,  0.43 ,  0.229,  0.261,
         0.632,  0.938,  0.576,  0.37 ,  0.497,  0.54 ,  0.306,  0.315,
         0.335,  0.24 ,  0.344,  0.93 ,  0.134,  0.4  ,  0.223,  1.224,
         1.187,  1.031,  0.25 ,  0.53 , -0.147,  0.087,  0.374,  0.496,
         0.441,  0.884,  0.971,  0.749,  0.432,  0.582,  0.198,  0.615,
         1.146,  0.475,  0.595,  0.304,  0.416,  0.645,  0.281,  0.576,
         1.139,  0.316,  0.892,  0.648,  0.826,  0.299,  0.381,  0.926,
         0.606],
       [-0.154, -0.392, -0.262,  0.214, -0.403, -0.363, -0.461, -0.326,
        -0.349, -0.21 , -0.286, -0.358, -0.436, -0.297, -0.394, -0.166,
        -0.389,  0.029, -0.124, -0.335, -0.419, -0.373, -0.121,  0.358,
         0.042, -0.408, -0.189, -0.213, -0.418, -0.479, -0.303, -0.645,
        -0.153,  0.098, -0.171, -0.066, -0.368, -0.273, -0.329, -0.295,
        -0.362, -0.305, -0.052, -0.171, -0.406, -0.102,  0.011, -0.375,
         0.126, -0.411, -0.42 , -0.27 , -0.407,  0.144, -0.419, -0.465,
        -0.036, -0.099,  0.007, -0.167, -0.205, -0.011, -0.151, -0.267,
        -0.368, -0.342, -0.299, -0.143, -0.42 , -0.232, -0.368, -0.417,
        -0.432,  0.171, -0.388, -0.319, -0.407, -0.379, -0.353,  0.043,
        -0.211, -0.14 , -0.373, -0.431, -0.383, -0.142, -0.345, -0.144,
        -0.302, -0.38 , -0.337, -0.2  , -0.321, -0.269,  0.406,  0.223,
        -0.322, -0.395, -0.379, -0.324, -0.424,  0.01 , -0.298, -0.386,
         0.018,  0.157, -0.384, -0.327, -0.442, -0.388, -0.387, -0.272,
        -0.397, -0.415, -0.388, -0.106, -0.504,  0.034, -0.153, -0.32 ,
        -0.271, -0.417, -0.417, -0.136, -0.447, -0.279, -0.225, -0.372,
        -0.316, -0.161, -0.331, -0.261, -0.409, -0.338, -0.437, -0.242,
        -0.328, -0.403, -0.433, -0.274, -0.331, -0.163, -0.361, -0.298,
        -0.392, -0.447, -0.429, -0.388,  0.11 , -0.348, -0.174,  0.244,
        -0.182, -0.424, -0.319,  0.088, -0.547,  0.189, -0.216, -0.228,
        -0.17 ,  0.125, -0.073, -0.266, -0.234, -0.108, -0.395, -0.395,
         0.131,  0.074,  0.514, -0.235, -0.389, -0.288, -0.22 , -0.416,
        -0.777, -0.358, -0.31 ,  0.817, -0.363, -0.328, -0.424, -0.416,
        -0.248, -0.093, -0.28 , -0.357, -0.348, -0.298, -0.384, -0.394,
        -0.362, -0.415, -0.349, -0.08 , -0.572, -0.07 , -0.423,  0.359,
         0.4  ,  0.099, -0.426, -0.252, -0.697, -0.508, -0.348, -0.254,
        -0.307, -0.116, -0.029, -0.201, -0.302, -0.25 , -0.44 , -0.233,
         0.274, -0.295, -0.223, -0.398, -0.298, -0.209, -0.389, -0.247,
         0.225, -0.395, -0.124, -0.237, -0.104, -0.361, -0.335, -0.083,
        -0.254]])
Dalek
la source
Comment identifiez-vous ces points bleus?
Dan
Il suffit de mettre quelques @ Dan limites xet yet les déterminer. Mais j'ai beaucoup de ce type de tracés avec différentes fonctionnalités et différents points de dispersion et je veux trouver un moyen fiable de les exclure sans les définir en regardant les diagrammes.
Dalek
1
comment définissez-vous un "modèle soigné". Je ne vois aucune raison pour laquelle ces points bleus seraient exclus en plus de l'inspection visuelle. Si vous aviez un critère d'exclusion, cela aurait plus de sens.
Dan
@Dan basé sur l'application que je recherche, les points bleus pour moi sont considérés comme des valeurs aberrantes et des dispersions de la fonctionnalité principale.
Dalek
ok alors qu'est-ce qui a défini la "caractéristique principale"?
Dan

Réponses:

10

Pour commencer à identifier les points «dispersés», pensez à vous concentrer sur les emplacements où une estimation de la densité du noyau est relativement faible.

Cette suggestion suppose que peu ou rien n'est connu ou même soupçonné initialement au sujet du "locus" des points - la ou les courbes le long desquelles la plupart tomberont - et elle est faite dans un esprit d'exploration semi-automatisée des données (plutôt que de tester des hypothèses).

Vous devrez peut-être jouer avec la largeur du noyau et le seuil de "relativement bas". Il existe de bons moyens automatiques d'estimer les premiers tandis que les seconds pourraient être identifiés via une analyse des densités aux points de données (pour identifier un groupe de valeurs faibles).


Exemple

La figure est générée une combinaison de deux types de données: une, représentées par des points rouges, sont des données de haute précision, tandis que l'autre, comme représenté sur les points bleus, des données sont relativement faible précision obtenues près de l'extrémité basse valeur de . À l'arrière-plan se trouvent (a) les contours d'une estimation de la densité du noyau (en niveaux de gris) et (b) la courbe autour de laquelle les points ont été générés (en noir).X

Figure

Les points avec des densités relativement faibles ont été encerclés automatiquement . (Les densités à ces points sont inférieures à un huitième de la densité moyenne de tous les points.) Elles incluent la plupart - mais pas tous! - des points de faible précision et certains des points de haute précision (en haut droite). Les points de faible précision situés près de la courbe (tels qu'extrapolés par les points de haute précision) n'ont pas été encerclés. L'encerclement des points de haute précision met en évidence le fait que partout où les points sont clairsemés, la trace de la courbe sous-jacente sera incertaine. C'est une caractéristique de l'approche suggérée, pas une limitation!


Code

RLe code pour produire cet exemple suit. Il utilise la ksbibliothèque, qui évalue l'anisotropie dans le motif de points pour développer une forme de noyau orientée. Cette approche fonctionne bien dans les exemples de données, dont le nuage de points a tendance à être long et maigre.

#
# Simulate some data.
#
f <- function(x) -0.55 + 0.45*x + 0.01/(1.2-x)^2 # The underlying curve

set.seed(17)
n1 <- 280; n2 <- 15
x <- c(1.2 - rbeta(n1,.9, .6), rep(0.1, n2))
y <- f(x)
d <- data.frame(x=x + c(rnorm(n1, 0, 0.025), rnorm(n2, 0, 0.1)),
                   y=y + c(rnorm(n1, 0, 0.025), rnorm(n2, 0, 0.33)),
                   group=c(rep(1, n1), rep(2, n2)))
d <- subset(d, subset=(y <= 1.0)) # Omit any high-y points
#
# Plot the density estimate.
#
require(ks)
p <- cbind(d$x, d$y)
dens <- kde(p)
n.levels <- 13
colors <- gray(seq(1, 0, length.out=n.levels))
plot(dens, display="filled.contour2", cont=seq(0, 100, length.out=n.levels),
     col=colors, xlab="X", ylab="Y")
#
# Evaluate densities at the data points.
#
dens <- kde(p, eval.points=p)
d$Density <- dens$estimate
#
# Plot the (correct) curve and the points.
#
curve(f(x), add=TRUE, to=1.2, col="Black")
points(d$x, d$y, ylim=c(-1,1), pch=19, cex=sqrt(d$Density/8),
     col=ifelse(d$group==1, "Red", "Blue"))
#
# Highlight some low-density points.
#
m <- mean(d$Density)
e <- subset(d, subset=(Density < m/10))
points(e$x, e$y, col="#00000080")
whuber
la source
La raison pour laquelle les données simulées sont fournies est que j'ai fait cette analyse avant que les données ne soient publiées dans la question. Le code de simulation peut être utile pour tester cette procédure - ou toute autre -, et peut donc être utile en soi.
whuber
afin d'obtenir la courbe sous-jacente, vous avez donc estimé le coefficient de l'ajustement en utilisant une procédure d'ajustement, non? avez-vous assumé une fonction de montage?
Dalek
Rien du tout: voir le code, qui utilise uniquement l'estimation de densité du noyau (telle que renvoyée par kde) pour identifier les points à encercler. Si je n'avais pas simulé les données d'une forme fonctionnelle connue (telle que donnée par f), je n'aurais pas pu dessiner de courbe de référence du tout, car aucun ajustement n'a été fait.
whuber
Je voulais dire la fonctionnalité de f(x).
Dalek
@whuber, super cool plot!
Dan