2017-03-26 1 views
2

J'utilise la méthode suivante de Daniel Weidele pour calculer une similarité Brainerd-Robinson pour un ensemble de données (code ci-dessous). Mes rangées représentent des lieux et mes colonnes représentent l'âge des personnes trouvées à chaque endroit. J'utilise la similarité pour mesurer les endroits qui ont des compositions démographiques similaires les uns aux autres, puis j'utilise la sortie dans une analyse de réseau. Mon problème est que beaucoup de mes places ont des '0' personnes dans certaines catégories d'âge, et donc l'index de similarité montre des liens forts entre ces endroits. Je voudrais exécuter deux itérations du modèle, à la fois i) où les '0 sont pris en compte et ii) où' 0 'sont ignorés, c'est-à-dire si je retourne juste les indices générés sur les données positives.Excluant 0 de similarité Brainerd-Robinson

J'ai essayé différentes méthodes d'exclusion de '0' de l'analyse et rien n'a fonctionné jusqu'ici. Des suggestions pour cela? Merci.

# function to load the observations 
 
load = function() { 
 
    p <- read.csv("observations.csv") 
 
    rownames(p) <- p[,1] 
 
    p <- p[,c(2:6)] 
 
    return(p) 
 
} 
 

 
# function to compute the normalized Brainerd-Robinson similarity for observations x 
 
BR <- function(x) 
 
{ 
 
    rd <- dim(x)[1] 
 
    results <- matrix(0,rd,rd) 
 
    for (s1 in 1:rd) { 
 
    for (s2 in 1:rd) { 
 
     results[s1,s2] <- 1 - (sum(abs(x[s1, ]/sum(x[s1,]) - x[s2, ]/sum(x[s2,]))))/2 
 
    } 
 
    } 
 
    rownames(results) <- rownames(x) 
 
    colnames(results) <- rownames(x) 
 
    return(results) 
 
} 
 

 
# load observations, compute Brainerd-Robinson similarity and write results to file 
 
write.csv(BR(load()), "br.csv")

+0

Serait-il logique de vos données, à l'entrée d'une moyenne pour tous les âges dans les lieux de 0? –

+0

J'aurais alors le même problème, n'est-ce pas? Si tous les 0 sont remplacés par le même n, alors ces valeurs seront toujours marquées comme 100% 'similaires'? – michael

+0

Si je devais remplacer tous mes '0' par NA, y aurait-il une bonne façon de les exclure de l'analyse? – michael

Répondre

0

Pourquoi ne pas demander à l'auteur directement? :)

Quand vous regardez la ligne

results[s1,s2] <- 1 - (sum(abs(x[s1, ]/sum(x[s1,]) - x[s2, ]/sum(x[s2,]))))/2 

c'est la plupart du temps où la magie se produit. Permettez-moi de décrire ce qui se passe ici, juste regarder le côté droit de l'opération d'affectation <-:

1 - (sum(abs(x[s1, ]/sum(x[s1,]) - x[s2, ]/sum(x[s2,]))))/2 

Appelons

  • le vecteur x[s1,] les Obvserations du site 1 (OOS1),
  • le numéro (ou scalaire) sum(x[s1,]), qui est alors sum(OOS1) le Somme du site 1 (SOS1),
  • et le vecteur x[s1,]/sum(x[s1,]) les Normalisé Observations du site 1 (NOS1)

On peut alors réécrire notre partie droite de l'affectation à:

1 - (sum(abs(OOS1/SOS1 - OOS2/SOS2)))/2 

ou

1 - (sum(abs(NOS1 - NOS2)))/2 

La partie importante est que NOS1 et NOS2 sont toujours des vecteurs contenant les nombres de valeurs observées par catégorie, juste normalisées à la proportion dans le site.

Maintenant la partie cruciale pour votre question: abs(NOS1 - NOS2).

NOS1 - NOS2 

soustrait simplement un vecteur de l'autre.C'est là que vous voulez faire de votre modification, afin de ne pas tenir compte des valeurs 0:

differenceIgnoreZeroes <- function(u, v) 
{ 
    # input vectors u and v should have equal length for this to work 
    result <- vector() 
    for (i in 1:length(u)) { 
    if(u[i] == 0 || v[i] == 0) next # SKIP IF EITHER VALUE IS 0 
    result[i] <- u[i] - v[i]  
    } 
    return(result) 
} 

Ayant cette fonction définie, nous écrivons donc differenceIgnoreZeroes(NOS1, NOS2) plutôt que NOS1-NOS2.

Nous continuons à côté de prendre la valeur absolue comme avant:

abs(differenceIgnoreZeroes(NOS1, NOS2)) 

Comme le vecteur résultant contient désormais des valeurs « NA », lorsque la somme sur le vecteur, nous devons faire attention à ne pas tenir compte de ces NA s, sinon, toute la somme deviendrait également NA. Par conséquent définir un paramètre na.rm à T (rue):

sum(abs(differenceIgnoreZeroes(NOS1,NOS2)), na.rm = T) 

Ainsi, notre mission totale à la main droite se présente comme suit:

1 - (sum(abs(differenceIgnoreZeroes(OOS1/SOS1, OOS2/SOS2)), na.rm = T))/2 

qui élargit encore à

1 - (sum(abs(differenceIgnoreZeroes(x[s1, ]/sum(x[s1,]), 
x[s2, ]/sum(x[s2,]))), na.rm = T))/2 

J'espère que cela aide!

Cheers,

Daniel Weidele