J'ai un ensemble de données avec trois colonnes X, Y et Z. Il y a plusieurs lignes dans le tableau. Les coordonnées X et Y dans chaque ligne correspondent à un emplacement dans l'espace XY et Z est la hauteur à cet emplacement XY. Je souhaite créer un cluster 3x3 à chaque emplacement XY et calculer la moyenne des 8 points voisins les plus proches (à l'exclusion du point central). Ensuite, soustrayez la hauteur Z de l'emplacement XY au centre de la moyenne calculée et si la différence est supérieure au seuil (décidé par l'utilisateur), cet emplacement XY sera appelé une valeur aberrante. Cela continuera jusqu'à ce que tous les emplacements XY aient été vérifiés. aberrant. Existe-t-il des fonctions intégrées dans JMP que je peux utiliser ? Comment puis-je le scripter en JSL? De plus, comment les coordonnées des bords sont-elles gérées ? Un exemple d'image est présenté ci-dessous. Toute orientation sera très appréciée.

une idée similaire, une mise en œuvre différente
// make sample data
dt = New Table( "sample",
New Column( "x", Numeric, "Continuous", Format( "Best", 12 ) ),
New Column( "y", Numeric, "Continuous", Format( "Best", 12 ) ),
New Column( "z", Numeric, "Continuous", Format( "Best", 12 ) )
);
For( ix = 0, ix < 200, ix += 1,
For( iy = 0, iy < 250, iy += 1,
dt << addrows( 1 );
dt:x = ix;
dt:y = iy;
dt:z = Random Normal( 30, .25 );
)
);
// load into a matrix that is 1 row/col bigger all around
// this assumes the x/y data is gridded, integers, no holes
// but no particular order
xmin = Col Min( dt:x );
xmax = Col Max( dt:x );
ymin = Col Min( dt:y );
ymax = Col Max( dt:y );
m = J( ymax - ymin + 3, xmax - xmin + 3, . );// +3 makes a border of missing values on all sides
For( i = 1, i <= N Rows( dt ), i += 1,
// subtract minimum makes it zero based. add 1 to get one-based, but add 2 to leave the border
m[dt:y[i] - ymin + 2, dt:x[i] - xmin + 2] = dt:z[i]; // copy each z to its x,y (col,row) element
);
meanmat = J( ymax - ymin + 1, xmax - xmin + 1, . ); // +1 is original size
// the x and y loops do not include the border
For( ix = 2, ix <= N Cols( m ) - 1, ix += 1,
For( iy = 2, iy <= N Rows( m ) - 1, iy += 1,
// smallmat is 3x3 and may include missing values from border
smallmat = m[(iy - 1) :: (iy + 1), (ix - 1) :: (ix + 1)];
smallmat[2, 2] = .;// remove center point from consideration
meanmat[iy - 1, ix - 1] = Mean( smallmat ); // mean ignores missing values: mean([8 2 .])==5
)
);
threshold = .5; // detection threshold
// the error matrix has 0 for ok, 1 for beyond threshold. the subscripts on m[]
// remove the border to make it line up with the meanmat.
error = Abs( m[2 :: (ymax - ymin + 2), 2 :: (xmax - xmin + 2)] - meanmat ) > threshold;
// add the outlier indicator back to the table
dt << New Column( "outliers" );
For( i = 1, i <= N Rows( dt ), i += 1,
dt:outliers[i] = error[dt:y[i] - ymin + 1, dt:x[i] - xmin + 1]
);
// fiddle with the tabl's row states to make the graph
dt << colorOrMarkByColumn( outliers );
dt << selectwhere( outliers == 1 );
// a graph
dt << Surface Plot(
Columns( :x, :y, :z ),
Datapoints Choice( "Points" ),
Response( :z ),
Surface Color Method( "Solid", "Solid", "Solid", "Solid" ),
SetVariableAxis( :x, Axis Data( {} ) ),
SetVariableAxis( :y, Axis Data( {} ) ),
SetZAxis( :z, Current Value( 30.5 ) ),
SetXVariable( :x ),
SetYVariable( :y ),
Frame3D(
Set Graph Size( 900, 900 ),
Set Rotation( -89, 1, -35 )
)
);
Red outliers above and below blue cloudRed outliers above and below blue cloudValeurs aberrantes rouges au-dessus et au-dessous du nuage bleu
Cela suppose que les coordonnées x et y des données sont des entiers consécutifs. Assurez-vous que le comportement des bords correspond à ce que vous attendez et assurez-vous que le centre est laissé comme prévu. Testez attentivement ! Par exemple, un cas 2x2 comme celui-ci :
Tiny test case making use of the missing value border, a lot!Tiny test case making use of the missing value border, a lot!Petit cas de test utilisant la bordure de valeur manquante, beaucoup !
Aucune fonction ne peut être appelée pour ce traitement de données très spécialisé. Voici un court script qui effectue la tâche essentielle.
Names Default to Here( 1 );
dt1 = Current Data Table();
// dimensions of results
nr = Col Maximum( dt1:Y ) - 1; // assumes first level is 0
nc = Col Maximum( dt1:X ) - 1; // assumes first level is 0
net height = [];
// iterate over 3x3 cells
For( c = 1, c < nc, c++,
For( r = 1, r < nr, r++,
cell = dt1 << Get Rows Where(
Or(
:X == r-1 & :Y == c-1,
:X == r-1 & :Y == c,
:X == r-1 & :Y == c+1,
:X == r & :Y == c-1,
:X == r & :Y == c,
:X == r & :Y == c+1,
:X == r+1 & :Y == c-1,
:X == r+1 & :Y == c,
:X == r+1 & :Y == c+1,
)
);
target = dt1 << Get Rows Where( :X == r & :Y == c );
net height |/= Matrix( { c, r, (((Sum( dt1:Z[cell] ) - dt1:Z[target]) / 8)</img> - dt1:z[target])[1] } )`;
);
);
dt2 = As Table( net height, << Column Names( { "X", "Y", "Net Z" } ) );
// assume user threshold is 1.5
threshold = 1.5;
dt2 << New Table Variable( "Threshold", "1.5" );
dt2 << New Column( "Outlier", "Numeric", "Nominal",
Values( net height[0,3] > threshold ),
Value Labels( {0 = "No", 1 = "Yes"} ),
Use Value Labels( 1 )
);
dt2 << New Script( "Plot Outliers",
Current Data Table() << Graph Builder(
Size( 522, 454 ),
Show Control Panel( 0 ),
Variables( X( :X ), Y( :Y ), Color( :Outlier ) ),
Elements( Points( X, Y, Legend( 3 ) ) )
);
);