2015-08-18 11 views
6

ho una matrice delle distanze:efficiente di accesso a distanza a due a due

> mat 
      hydrogen helium lithium beryllium boron 
hydrogen 0.000000 2.065564 3.940308 2.647510 2.671674 
helium 2.065564 0.000000 2.365661 1.697749 1.319400 
lithium 3.940308 2.365661 0.000000 3.188148 2.411567 
beryllium 2.647510 1.697749 3.188148 0.000000 2.499369 
boron  2.671674 1.319400 2.411567 2.499369 0.000000 

E un frame di dati:

> results 

El1  El2 Score 
Helium Hydrogen 92 
Boron Helium 61 
Boron Lithium 88 

voglio calcolare tutte le distanze a coppie tra le parole results$El1 e results$El2 per ottenere il seguente:

> results 

El1  El2 Score Dist 
Helium Hydrogen 92 2.065564 
Boron Helium 61 1.319400 
Boron Lithium 88 2.411567 

Ho fatto questo con un ciclo for ma sembra davvero goffo. C'è un modo più elegante per cercare ed estrarre distanze con meno righe di codice?

Ecco il mio codice corrente:

names = row.names(mat) 
num.results <- dim(results)[1] 
El1 = match(results$El1, names) 
El2 = match(results$El2, names)  
el.dist <- matrix(0, num.results, 1)   
for (i1 in c(1:num.results)) {    
el.dist[i1, 1] <- mat[El1[i1], El2[i1]] 
} 
results$Dist = el.dist[,1] 

risposta

4
cols <- match(tolower(results$El1), colnames(mat)) 
rows <- match(tolower(results$El2), colnames(mat)) 
results$Dist <- mat[cbind(rows, cols)] 
results 
    El1  El2 Score  Dist 
1 Helium Hydrogen 92 2.065564 
2 Boron Helium 61 1.319400 
3 Boron Lithium 88 2.411567 

Si ritrova la maggior parte del codice. Quello su cui concentrarsi è mat[cbind(rows, cols)]. Con le matrici, siamo autorizzati a subsetare da un'altra matrice con lo stesso numero di colonne delle dimensioni. Dalla ?`[` aiuto:

Quando array indicizzazione di [un singolo argomento posso essere una matrice con tante colonne quante sono le dimensioni di x; il risultato è quindi un vettore con elementi corrispondenti all'insieme di indici in ciascuna riga di i.

+0

ho cancellato il commento precedente dopo aver trovato il problema: una lettera maiuscola canaglia! – Dex

3

altro approccio

results$Dist <- mapply(function(x, y) mat[tolower(x), tolower(y)], 
         results$El1, results$El2) 

Ciò presuppone results uso character non factor per El1 e El2.

Il risultato

> results 
    El1  El2 Score  Dist 
1 Helium Hydrogen 92 2.065564 
2 Boron Helium 61 1.319400 
3 Boron Lithium 88 2.411567 
+0

Grazie! Ho appena provato questo e ha funzionato bene anche se 'El1' e' El2' sono fattori. Non è consigliabile usare 'mapply' con fattori? – Dex

+1

@ user20672 - la differenza fattore/carattere cambierà i risultati restituiti quando è possibile indicizzare con un numero intero ** o ** un carattere. Un fattore è un intero internamente ... quindi 'x <- c (b = 1, a = 2)' e quindi 'x [factor (c (" a "," b "))]' e 'x [c ("a", "b")] 'restituirà risposte diverse. – thelatemail

+0

@thelatemail grazie per aver chiarito – Dex