Domanda:
Somiglianza di Jaccard in R
Torvon
2015-10-12 22:23:22 UTC
view on stackexchange narkive permalink

Voglio confrontare 2 vettori di lunghezza 43; hanno valori di 0 (non presente) e 1 (presente). Mi riferirò a $ M_ {1,1} $ come situazioni in cui entrambi 1 sono presenti, e $ M_ {1,0} $ e $ M_ {0,1} $ a situazioni in cui è presente un solo 1 mentre il l'altro valore è 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 0data3 $ 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 0 1 1 1 1 1 1 1 1 1 1 1 1 

Voglio capire quanto sono correlati questi 2 vettori. Leggendo l'argomento, l'indice Jaccard sembra la strada da percorrere. In questo caso specifico, l'indice di Jaccard sarebbe (nota che sto usando la formula data accanto alla seconda cifra su Wikipedia): $$ \ frac {M_ {1,1}} {(M_ {1,0} + M_ {0,1} - M_ {1,1})} $$ Nel mio caso: $ 8 / (23 + 12 - 8) = 0,2962963 $

Utilizzando:

  library ('clusteval') cluster_similarity (data3 $ IDS, data3 $ CESD, similarity = "jaccard", method = "indipendenza")  

Restituisce:

  0.553429  

Non riesco a capire bene perché e dov'è l'errore che faccio.

Un'altra cosa che non capisco è nei casi di sovrapposizione elevata. Immagina $ M_ {1,1} = 30 $, con solo $ 2 $ valori ciascuno nelle celle $ M_ {1,0} $ e $ M_ {0,1} $. Ciò porterebbe a un indice Jaccard di $ 30 / (2 + 2-30) = -1.153846 $.

Ma l'indice J è definito solo tra 0 e 1. Dov'è il mio malinteso?

Cinque risposte:
gung - Reinstate Monica
2015-10-13 07:23:30 UTC
view on stackexchange narkive permalink

Guardando la cronologia delle modifiche della pagina di Wikipedia, sembra che il problema fosse dovuto a una confusione sui due tipi di notazione matematica utilizzati per rappresentare l'indice. Usando la notazione dalla teoria degli insiemi, abbiamo:
$$ J (A, B) = \ frac {| A \ cap B |} {| A \ cup B |} = \ frac {| A \ cap B |} {| A | + | B | - | A \ cap B |} $$ dove $ \ cap $ denota l ' intersezione, $ \ cup $ denota l' unione e $ \ lvert \ \ rvert $ denota la cardinalità.

Più in basso, la formula è stata presentata algebricamente utilizzando i conteggi da una tabella di matrice / contingenza $ M $:
$$ J = \ frac {M_ {11}} {M_ {10} + M_ { 01} + M_ {11}} $$ Questo sembrava contraddittorio per un editore che ha commentato che c'era un "Erro nella formula [sic]. Dovrebbe essere meno l'intersezione".

Le due formule sono infatti coerenti perché sebbene $ | A \ cap B | = M_ {11} $, $ | A | \ ne M_ {10} $ e $ | B | \ ne M_ { 01} $. La formula algebrica avrebbe potuto essere presentata (in un modo più ingombrante, ma più chiaramente parallelo alla formula in alto) in questo modo:
$$ 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

Quella formula è davvero sbagliata.

Dovrebbe essere m11 / (m01 + m10 + m11), poiché l'indice Jaccard è la dimensione dell'intersezione tra due insiemi, divisa per la dimensione dell'unione tra questi insiemi.

Il valore corretto è 8 / (12 + 23 + 8) = 0,186. Trovo strano, però, che questo non sia lo stesso valore che ottieni dal pacchetto R.

Hai capito correttamente che l'indice Jaccard è un valore compreso tra 0 e 1. Per l'esempio hai fornito l'indice corretto è 30 / (2 + 2 + 30) = 0,882.

Il pacchetto presenta problemi con 0 e 1 e stima la tabella di contingenza errata.Non sono ancora riuscito a trovarne la ragione, quindi ho scritto la mia funzione J con la formula corretta.Anche la funzione dist.binary dal pacchetto 'ade4' funziona come un fascino (in questo caso, usa 1-J).
Il pacchetto clusteval è pensato per confrontare due cluster (partizioni) anziché due set.L'indice Jaccard per il confronto degli insiemi assume 0 = assenza dall'insieme e 1 = presenza nell'insieme.Se invece si interpreta 0/1 come indicante le due possibili etichette di cluster, con `data3 $ IDS` e` data3 $ CESD` come raggruppamenti separati, allora clusteval fornisce la risposta corretta.Un modo rapido per verificare è che le etichette dei cluster siano invarianti alla permutazione, mentre la presenza / assenza non lo è.Quindi, invertendo lo 0/1 in una delle variabili cambia la Jaccard basata su set ma non la Jaccard di clustering / clusteval.
jsb
2017-09-14 06:41:11 UTC
view on stackexchange narkive permalink

Ho scritto una semplice funzione per calcolare l'indice Jaccard (coefficiente di similarità) e la distanza Jaccard complementare per attributi binari:

  # Il tuo set di dati
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, 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 funzione restituisce l'indice Jaccard e la distanza Jaccard
jaccard <- funzione (df, margin) {
  if (margin == 1 | margin == 2) {
    M_00 <- applica (df, margin, sum) == 0
    M_11 <- applica (df, margin, sum) == 2
    if (margin == 1) {
      df <- df [! M_00,]
      JSim <- sum (M_11) / nrow (df)
    } altro {
      df <- df [,! M_00]
      JSim <- somma (M_11) / lunghezza (df)
    }
    JDist <- 1 - JSim
    ritorno (c (JSim = JSim, JDist = JDist))
  } altrimenti si rompono
}
 

La funzione accetta due argomenti: x un dataframe o un oggetto matrice e m l'argomento MARGIN utilizzato in apply funzione. Se i tuoi dati sono in formato ampio, imposta m = 2 per applicare sum sulle colonne. Se i dati sono in formato lungo, imposta m = 1 per applicare sum sulle righe.

  > jaccard (df2, 1)
     JSim JDist
0.1860465 0.8139535
 
Torvon
2015-10-13 01:15:26 UTC
view on stackexchange narkive permalink

Risolto. Il problema era che Wikipedia in realtà era sbagliata, in particolare la formula:

m11 / (m10 + m01-m11)

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

Aumento del codice @ jsb per abilitare una misura di somiglianza tra tutte le osservazioni.

  # Indice Jaccar
libreria (dplyr)

# Il tuo set di dati
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 funzione restituisce l'indice Jaccard e la distanza Jaccard
# Parametri:
# 1. df, dataframe di interesse
# 2. margine, asse in cui la funzione di applicazione deve muoversi
jaccard <- funzione (df, margin = 1) {
  if (margin == 1 | margin == 2) {
    M_00 <- applica (df, margin, sum) == 0
    M_11 <- applica (df, margin, sum) == 2
    if (margin == 1) {
      df <- df [! M_00,]
      JSim <- sum (M_11) / nrow (df)
    } altro {
      df <- df [,! M_00]
      JSim <- somma (M_11) / lunghezza (df)
    }
    JDist <- 1 - JSim
    ritorno (c (JSim = JSim, JDist = JDist))
  } altrimenti si rompono
}

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


jaccard_per_row <- funzione (df, margin = 1) {
   richiedono (magrittr)
   richiedono (dplyr)
   key_pairs <- expand.grid (row.names (df), row.names (df))
   risultati <- 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 = ""))
   risultati <- data.frame (risultati)
   row.names (risultati) <- key_pair $ coppia
   risultati
}

jaccard_per_row (df, margin = 2)
 

Risultato:

  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.3333333 0.6666667
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.3333333 0.6666667
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
 

Ora puoi determinare quali righe hanno una soglia superiore a una percentuale desiderata e conservare solo osservazioni molto simili per la tua analisi.

Buon divertimento!



Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 3.0 con cui è distribuito.
Loading...