2012-10-03 13 views
0

J'ai une matrice de similarité entre tous les cas et, dans une trame de données séparée, des classes de ces cas. Je veux calculer la similarité moyenne entre les cas de la même classe, voici l'équation pour un exemple n de la classe j:Calcul rapide de la proximité moyenne dans une matrice de proximité

Average proximity between cases

Nous devons calculer une somme de tous au carré proximités entre n et tous les cas k qui viennent de la même classe que n. Lien: http://www.stat.berkeley.edu/~breiman/RandomForests/cc_home.htm#outliers

J'ai implémenté cela avec 2 pour les boucles, mais c'est vraiment lent. Y a-t-il un moyen plus rapide de faire une telle chose dans R?

Merci.

// DATA (dput)

de trame de données avec des classes:

structure(list(class = structure(c(1L, 2L, 2L, 1L, 3L, 3L, 1L, 
          1L, 2L, 3L), .Label = c("1", "2", "3", "5", "6", "7"), class = "factor")), .Names = "class", row.names = c(NA, 
      -10L), class = "data.frame") 

matrice de proximité (rangée m et de la colonne m correspondent à la classe dans la ligne m de la trame de données ci-dessus):

structure(c(1, 0.60996875, 0.51775, 0.70571875, 0.581375, 0.42578125, 
0.6595, 0.7134375, 0.645375, 0.468875, 0.60996875, 1, 0.77021875, 
0.55171875, 0.540375, 0.53084375, 0.4943125, 0.462625, 0.7910625, 
0.56321875, 0.51775, 0.77021875, 1, 0.451375, 0.60353125, 0.62353125, 
0.5203125, 0.43934375, 0.6909375, 0.57159375, 0.70571875, 0.55171875, 
0.451375, 1, 0.69196875, 0.59390625, 0.660375, 0.76834375, 0.606875, 
0.65834375, 0.581375, 0.540375, 0.60353125, 0.69196875, 1, 0.7194375, 
0.684, 0.68090625, 0.50553125, 0.60234375, 0.42578125, 0.53084375, 
0.62353125, 0.59390625, 0.7194375, 1, 0.53665625, 0.553125, 0.513, 
0.801625, 0.6595, 0.4943125, 0.5203125, 0.660375, 0.684, 0.53665625, 
1, 0.8456875, 0.52878125, 0.65303125, 0.7134375, 0.462625, 0.43934375, 
0.76834375, 0.68090625, 0.553125, 0.8456875, 1, 0.503, 0.6215, 
0.645375, 0.7910625, 0.6909375, 0.606875, 0.50553125, 0.513, 
0.52878125, 0.503, 1, 0.60653125, 0.468875, 0.56321875, 0.57159375, 
0.65834375, 0.60234375, 0.801625, 0.65303125, 0.6215, 0.60653125, 
1), .Dim = c(10L, 10L)) 

résultat correct:

c(2.44197227050781, 2.21901680175781, 2.07063155175781, 2.52448621289062, 
1.88040830957031, 2.16019295703125, 2.58622273828125, 2.81453253222656, 
2.1031745078125, 2.00542063378906) 

Répondre

1

Devrait être possible. Votre notation ne précise pas si nous trouverons des membres de classes similaires dans les lignes ou les colonnes, donc cette réponse est présumée dans les colonnes mais les modifications évidentes fonctionneraient aussi bien si elles étaient dans les lignes. Comme les deux opérations sont vectorisées, on peut s'attendre à ce qu'elles soient beaucoup plus rapides que les boucles for-loops.

Avec la modification et en supposant que la matrice est appelée 'tapis' et la classe-dataframe nommé 'CLDF':

sapply(1:nrow(mat) , 
      function(r) sum(mat[r, cldf[['class']][r] == cldf[['class']] ]^2) ) 
[1] 2.441972 2.219017 2.070632 2.524486 1.880408 2.160193 2.586223 2.814533 2.103175 2.005421 

+0

Le problème est que nous ne pouvons pas dire quels exemples proviennent de la même classe seulement de la matrice. Nous devons chercher dans le cadre de données. –

+0

Dans ce cas, votre affichage d'un exemple représentatif et une "bonne réponse" sont en retard. –

+0

Je pense que je peux modifier la matrice (ou pour chaque classe utiliser un sous-ensemble de la matrice) et utiliser votre réponse. Je vais essayer de voir à quelle vitesse c'est. Merci à quatre votre aide. –