Les voisins proches signifient le calculSalut tout le monde,
Je dois calculer la moyenne des matrices/composants voisins sur une plaquette microélectronique par exemple sur une boîte 3x3 comme celle-ci :

La composante de référence est au centre d'une boite et donc entourée de 8 composantes dont je veux calculer la moyenne, pour chaque ligne du tableau de données (puis calculer la même chose pour une boite 5x5 et 16 voisins...)
Il sera utilisé comme une nouvelle fonctionnalité pour l'apprentissage automatique.
Mon code est :
dt = current data table();
<BR />// building the KD table
matrice = (dt:row << getvalues) || (dt:col << getvalues);
table = KDTable(matrice);
for( i=1, i<=nrows(dt),i++,
// get the 3x3 neighbors
neighbors = table << Knearestrows(8,i);
neighbors_number = neighbors[1,1];
// Select the neighbors and get their metrics values and calculate the mean<BR /> dt << select rows (neighbors_number );
mean_selection = Col Mean( If( Selected(), :metric, . ) );
:mean_metric[i] = mean_selection;
dt << clear select
);Quelqu'un a-t-il un moyen intelligent de faire ce calcul plus efficacement?
merci!
ScriptRe : Calcul de la moyenne des voisins prochesMerci pour tout ça, je vais approfondir
Re : Calcul de la moyenne des voisins prochesSalut @Franck_R ,
Peut-être que cela peut aussi vous aider : Complément : Analyse des données spatiales
Si ce que vous recherchez est la corrélation spatiale, le I de Moran est peut-être le concept le plus fondamental.
Ron
Re : Calcul de la moyenne des voisins prochesVous pouvez remplir suffisamment de lignes et de colonnes de valeurs manquantes, à gauche, à droite, en haut, en bas.Selon jusqu'où vous allez avec l'extension du voisinage, vous pourriez avoir 8 tranches de valeurs manquantes complètes entourant la vraie tranche.
Il existe une autre façon de procéder, nécessitant également les lignes et les colonnes factices, ce qui sera très rapide :
Les matrices JMP 2D peuvent être indexées en tant que matrices linéaires 1D.
[ 1 2,
3 4,
5 6 ] (3 lignes, 2 colonnes)
ressemble aussi
[ 1,
2,
3,
4,
5,
6] (6 lignes, 1 colonne lors de l'utilisation d'un indice)
Si la plaquette est NRows x NCols, placez-la au milieu d'une matrice 3NRows x 3NCols (je l'appellerai M3).
Vous pouvez créer une matrice d'indices 1D pour indexer M3 en ajoutant 1 pour se déplacer horizontalement et en ajoutant 3NCols pour se déplacer verticalement. Pour extraire une sous-matrice 3x3 de M3, utilisez la matrice d'index et la fonction shape().
quelque chose comme ça:
M3 = [. . . . . . . . .,
. . . . . . . . .,
. . . . . . . . .,
. . . 1 2 3 . . .,
. . . 4 5 6 . . .,
. . . 7 8 9 . . .,
. . . . . . . . .,
. . . . . . . . .,
. . . . . . . . .];
indexer2x2 = [1 2 10 11]; // top left 2x2 sub-matrix
For( x = 2, x <= 5, x += 1,
For( y = 2, y <= 5, y += 1,
Write( "\!n ", x, " ", y, " ", Shape( M3[indexer2x2 + x + y * 9], 2 ) );
)
);
2 2 [. ., . 1]
2 3 [. 1, . 4]
2 4 [. 4, . 7]
2 5 [. 7, . .]
3 2 [. ., 1 2]
3 3 [1 2, 4 5]
3 4 [4 5, 7 8]
3 5 [7 8, . .]
4 2 [. ., 2 3]
4 3 [2 3, 5 6]
4 4 [5 6, 8 9]
4 5 [8 9, . .]
5 2 [. ., 3 .]
5 3 [3 ., 6 .]
5 4 [6., 9.]
5 5 [9 ., . .]
Vous pourriez aussi avoir besoin de ceci : Utilisation de Loc avec une matrice 2D
Vous pouvez créer un indexer3x3, etc. et simplement réutiliser le M3 pour chaque niveau. la boucle for x=3, x<=5 doit aller un peu plus loin à chaque fois.
edit : la fonction de forme peut être inutile si vous obtenez simplement la moyenne des éléments indexés, mais elle aide à montrer ce qui s'est passé ci-dessus. plus : les matrices JSL ont un comportement particulier lorsque l'index est inférieur à 1 et vous n'obtiendrez pas le message d'erreur que vous pourriez espérer ! si l'indexeur contient un zéro (ou -1, etc.), cela semblera très étrange.
Re : Calcul de la moyenne des voisins prochespar contre je me rends compte que la solution du rayon limite n'est pas parfaite car on prend quand même un élément supplémentaire dans le tableau
par exemple un rayon de 1,5 contient une valeur de 2 car c'est la valeur qui stoppe la recherche des voisins... Donc ça ne me donne pas exactement ce que je veux, il va falloir que je cherche un peu plus !
Re : Calcul de la moyenne des voisins prochesMerci beaucoup c'est très intéressant !
J'utilise parfois "commencer la mise à jour des données" mais je n'y ai pas pensé ici : bon point. Avec cela, la solution Loc() est en fait un peu plus lente que knearestrows() si vous ajoutez la mise à jour de début que je trouve pour 20 000 lignes :
ancien script sans commencer la mise à jour : 116s !
knarestrows() avec commencer la mise à jour : 5 s
Loc() avec début de mise à jour : 14s
mais pour les knearestrows, j'ai dû changer la façon dont je calcule la moyenne car nous ne pouvons plus utiliser de lignes sélectionnées avec la mise à jour début/fin.
Pour les bords tu as parfaitement raison, j'avais pensé à mettre :
neighbors = table << Knearestrows( {8, 1.5}, i );
Pour éviter ce problème en utilisant un rayon limité
Merci encore!
Re : Calcul de la moyenne des voisins prochesJe suis presque sûr que la taille du problème déterminera si l'approche kdtable() ou loc() est meilleure. Je suppose que loc() gagnera pour une matrice 10x10 ou plus petite, et kdtable pour 100x100 ou plus.
Le point de Xan sur les bords est important. Loc() pourrait être le moyen le plus simple d'obtenir la bonne réponse.
Re : Calcul de la moyenne des voisins prochesJe ne sais pas comment l'efficacité se compare, mais voici une alternative à essayer.
- L'utilisation de begin/end data update() aidera pour n'importe quelle méthode
- L'utilisation du voisin le plus proche est astucieuse (et peut-être même plus efficace) mais sachez qu'elle renverra toujours les 8 les plus proches, même sur les bords de la plaquette où les voisins seront tous d'un même côté.
- L'indice matriciel peut être plus efficace que Col Mean().
dt = current data table();
metrics = dt[0, "metric"];
rows = dt[0, "row"];
cols = dt[0, "col"];
d = 1; // 1 => 3x3, 2 => 5x5
dt << Begin Data Update();
For Each Row(
neighbors = Loc( :col - d <= cols <= :col + d & :row - d <= rows <= :row + d );
mean all = Mean( metrics[neighbors] );
nn = N Rows( neighbors );
mean without center = (mean all * nn - :metric) / (nn - 1);
:mm = mean without center;
);
dt << End Data Update();