Question:
Similitude de Jaccard dans R
Torvon
2015-10-12 22:23:22 UTC
view on stackexchange narkive permalink

Je veux comparer 2 vecteurs de longueur 43; ils ont des valeurs de 0 (non présent) et 1 (présent). Je ferai référence à $ M_ {1,1} $ comme des situations dans lesquelles les deux 1 sont présents, et $ M_ {1,0} $ et $ M_ {0,1} $ à des situations dans lesquelles un seul 1 est présent alors que le l'autre valeur est 0.

  data3 $ IDS 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 données3 $ CESD 1 1 1 0 1 1 0 0 0 0 0 1 0 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 

Je veux comprendre comment ces 2 vecteurs sont liés. En lisant sur le sujet, l'index Jaccard semble être la voie à suivre. Dans ce cas précis, l'index Jaccard serait (notez que j'utilise la formule donnée à côté du deuxième chiffre sur Wikipedia): $$ \ frac {M_ {1,1}} {(M_ {1,0} + M_ {0,1} - M_ {1,1})} $$ Dans mon cas: $ 8 / (23 + 12 - 8) = 0.2962963 $

En utilisant:

  bibliothèque ('clusteval') cluster_similarity (data3 $ IDS, data3 $ CESD, similarity = "jaccard", method = "indépendance")  

Renvoie:

  0.553429  

Je ne comprends pas vraiment pourquoi et où est l'erreur que je fais.

Une autre chose que je ne comprends pas est les cas de chevauchement élevé. Imaginez $ M_ {1,1} = 30 $, avec seulement des valeurs de $ 2 $ chacune dans les cellules $ M_ {1,0} $ et $ M_ {0,1} $. Cela conduirait à un indice Jaccard de 30 $ / (2 + 2-30) = -1,153846 $.

Mais l'indice J n'est défini qu'entre 0 et 1. Où est mon malentendu?

Cinq réponses:
gung - Reinstate Monica
2015-10-13 07:23:30 UTC
view on stackexchange narkive permalink

En regardant l ' historique des modifications de la page Wikipédia, il semble que le problème soit dû à une confusion concernant les deux types de notation mathématique utilisés pour représenter l'index. En utilisant la notation de la théorie des ensembles, nous avons:
$$ J (A, B) = \ frac {| A \ cap B |} {| A \ cup B |} = \ frac {| A \ cap B |} {| A | + | B | - | A \ cap B |} $$ où $ \ cap $ désigne l ' intersection, $ \ cup $ désigne l' union, et $ \ lvert \ \ rvert $ désigne la cardinalité.

Plus bas, la formule a été présentée algébriquement en utilisant les décomptes d'une matrice / table de contingence $ M $:
$$ J = \ frac {M_ {11}} {M_ {10} + M_ { 01} + M_ {11}} $$ Cela a semblé contradictoire à un éditeur qui a commenté qu'il y avait un "Erro dans la formule [sic]. Devrait être moins l'intersection".

Les deux formules sont en fait cohérentes car bien que $ | A \ cap B | = M_ {11} $, $ | A | \ ne M_ {10} $ et $ | B | \ ne M_ { 01} $. La formule algébrique aurait pu être présentée (d'une manière plus lourde, mais plus clairement parallèle à la formule du haut) comme ceci:
$$ J = \ frac {M_ {11}} {\ sum_j M_ {1j} + \ sum_i M_ {i1} - M_ {11}} $$

Peter Smit
2015-10-13 01:39:32 UTC
view on stackexchange narkive permalink

Cette formule est en effet fausse.

Il devrait être m11 / (m01 + m10 + m11), car l'indice de Jaccard est la taille de l'intersection entre deux ensembles, divisée par la taille de l'union entre ces ensembles.

La valeur correcte est 8 / (12 + 23 + 8) = 0,186. Je trouve cependant bizarre que ce ne soit pas la même valeur que celle que vous obtenez du package R.

Vous avez bien compris que l'index Jaccard est une valeur comprise entre 0 et 1. Pour l'exemple, vous avez donné l'index correct est 30 / (2 + 2 + 30) = 0,882.

Le package a des problèmes avec 0 et 1 et estime le mauvais tableau de contingence.Je n'ai pas encore pu en trouver la raison, alors j'ai écrit ma propre fonction J avec la formule corrigée.La fonction dist.binary du package 'ade4' fonctionne également comme un charme (dans ce cas, utilisez 1-J).
Le package clusteval est destiné à comparer deux regroupements (partitions) plutôt que deux ensembles.L'indice Jaccard pour comparer des ensembles suppose 0 = absence de l'ensemble et 1 = présence dans l'ensemble.Si vous interprétez à la place le 0/1 comme indiquant les deux étiquettes de cluster possibles, avec `data3 $ IDS` et` data3 $ CESD` comme regroupements séparés, alors clusteval donne la bonne réponse.Un moyen rapide de vérifier est que les étiquettes de cluster sont invariantes à la permutation, alors que la présence / absence ne l'est pas.Ainsi, inverser le 0/1 dans l'une des variables modifie le Jaccard basé sur l'ensemble mais pas le Jaccard de clustering / clusteval.
jsb
2017-09-14 06:41:11 UTC
view on stackexchange narkive permalink

J'ai écrit une fonction simple pour calculer l'indice Jaccard (coefficient de similarité) et la distance Jaccard complémentaire pour les attributs binaires:

  # Votre ensemble de données
df2 <- data.frame (
  IDS = c (1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
  CESD = c (1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1))

# La fonction renvoie l'index Jaccard et la distance Jaccard
jaccard <- fonction (df, marge) {
  si (marge == 1 | marge == 2) {
    M_00 <- appliquer (df, marge, somme) == 0
    M_11 <- appliquer (df, marge, somme) == 2
    si (marge == 1) {
      df <- df [! M_00,]
      JSim <- somme (M_11) / nrow (df)
    } autre {
      df <- df [,! M_00]
      JSim <- somme (M_11) / longueur (df)
    }
    JDist <- 1 - JSim
    retour (c (JSim = JSim, JDist = JDist))
  } sinon pause
}
 

La fonction prend deux arguments: x un dataframe ou un objet matrice, et m l'argument MARGIN utilisé dans apply fonction. Si vos données sont au format large, définissez m = 2 pour appliquer somme sur les colonnes. Si vos données sont au format long, définissez m = 1 pour appliquer somme sur les lignes.

  Jaccard > (df2, 1)
     JSim JDist
0,1860465 0,8139535
 
Torvon
2015-10-13 01:15:26 UTC
view on stackexchange narkive permalink

Résolu. Le problème était que Wikipédia se trompait, en particulier la formule:

m11 / (m10 + m01-m11)

bmc
2018-05-23 00:47:20 UTC
view on stackexchange narkive permalink

Augmentation du code de @ jsb pour permettre une mesure de similarité entre toutes les observations.

  # Index Jaccar
bibliothèque (dplyr)

# Votre ensemble de données
df <- data.frame (t (data.frame (c1 = rnorm (100),
                              c2 = rnorm (100),
                              c3 = rnorm (100),
                              c4 = rnorm (100),
                              c5 = rnorm (100),
                              c6 = rnorm (100))))

df [df > 0] <- 1
df [df < = 0] <- 0
df

# La fonction renvoie l'index Jaccard et la distance Jaccard
# Paramètres:
# 1. df, dataframe d'intérêt
# 2. marge, axe dans lequel la fonction Apply est censée se déplacer
jaccard <- fonction (df, margin = 1) {
  si (marge == 1 | marge == 2) {
    M_00 <- appliquer (df, marge, somme) == 0
    M_11 <- appliquer (df, marge, somme) == 2
    si (marge == 1) {
      df <- df [! M_00,]
      JSim <- somme (M_11) / nrow (df)
    } autre {
      df <- df [,! M_00]
      JSim <- somme (M_11) / longueur (df)
    }
    JDist <- 1 - JSim
    retour (c (JSim = JSim, JDist = JDist))
  } sinon pause
}

jaccard (df [1: 2,], marge = 2)


jaccard_per_row <- fonction (df, margin = 1) {
   exiger (magrittr)
   exiger (dplyr)
   key_pairs <- expand.grid (row.names (df), row.names (df))
   résultats <- t (apply (key_pairs, 1, function (row) jaccard (df [c (row [1], row [2]),], margin = margin)))
   key_pair <- key_pairs% >% mutate (pair = paste (Var1, "_", Var2, sep = ""))
   résultats <- data.frame (résultats)
   row.names (résultats) <- key_pair $ pair
   résultats
}

jaccard_per_row (df, marge = 2)
 

Sortie:

  JSim JDist
c1_c1 1,0000000 0,0000000
c2_c1 0,3974359 0,6025641
c3_c1 0,3513514 0,6486486
c4_c1 0,3466667 0,6533333
c5_c1 0,33333333 0,66666667
c6_c1 0,3888889 0,6111111
c1_c2 0,3974359 0,6025641
c2_c2 1.0000000 0.0000000
c3_c2 0,3289474 0,6710526
c4_c2 0,4166667 0,5833333
c5_c2 0,3466667 0,6533333
c6_c2 0,3289474 0,6710526
c1_c3 0,3513514 0,6486486
c2_c3 0,3289474 0,6710526
c3_c3 1,0000000 0,0000000
c4_c3 0,2236842 0,7763158
c5_c3 0.3333333 0.6666667
c6_c3 0,3529412 0,6470588
c1_c4 0,3466667 0,6533333
c2_c4 0,4166667 0,5833333
c3_c4 0,2236842 0,7763158
c4_c4 1.0000000 0.0000000
c5_c4 0,3676471 0,6323529
c6_c4 0,2236842 0,7763158
c1_c5 0,33333333 0,66666667
c2_c5 0,3466667 0,6533333
c3_c5 0.3333333 0.6666667
c4_c5 0,3676471 0,6323529
c5_c5 1.0000000 0.0000000
c6_c5 0,2957746 0,7042254
c1_c6 0,3888889 0,6111111
c2_c6 0,3289474 0,6710526
c3_c6 0,3529412 0,6470588
c4_c6 0,2236842 0,7763158
c5_c6 0,2957746 0,7042254
c6_c6 1.0000000 0.0000000
 

Vous pouvez désormais déterminer quelles lignes ont un seuil supérieur au pourcentage souhaité et ne conserver que des observations très similaires pour votre analyse.

Profitez-en!



Ce Q&R a été automatiquement traduit de la langue anglaise.Le contenu original est disponible sur stackexchange, que nous remercions pour la licence cc by-sa 3.0 sous laquelle il est distribué.
Loading...