2013-02-08 17 views
5

Ho un frame di dati con tre colonne: ref, target, distance. Ogni ref ha una distanza misurata dallo stesso set di bersagli e vorrei ottenere un vettore di distanze minime per ogni ref. In questo momento sto facendo questo con un ciclo for, ma sembra che ci dovrebbe essere un modo per vettorializzare questo.Vectorize per il frame di dati loop su R

Ecco il mio codice:

refs <- levels(data$ref) 

result <- c() 
for (ref in refs) { 
    # Find the minimum distance for observations with the current ref 
    # but be sure to protect against ref == target! 
    best_dist <- min(data[data$ref == ref & data$target != ref,]$distance) 
    result <- c(result, best_dist) 
} 

Am I condannato per avere il mio frame di dati impostato in questo modo o c'è un buon modo per vettorizzare questo? Grazie per l'aiuto!

risposta

6

Non far crescere mai un oggetto all'interno di un loop utilizzando c, cbind, rbind. L'oggetto verrà copiato ogni volta. Invece preallocare alla dimensione corretta (o sopravvalutare se il risultato è fluido).

Detto questo, un loop non è necessaria qui

Mi piace data.table s per l'efficienza della memoria e codifica eleganza.

library(data.table) 
DT <- data.table(data) 


DT[ref != target, list(bestdist = min(distance)), by = ref] 

se ref e di destinazione sono le colonne del fattore con diversi livelli (come suggerito nel commento), allora o farli avere livelli identici, o convertire a carattere

DT[as.character(ref) != as.character(target), list(bestdist = min(distance)), by = ref] 
+0

Penso che tu abbia a ')' mancante qui ... – adibender

+0

ta. Risolto ora .. – mnel

+0

Questo sembra non funzionare abbastanza bene come è. Ho riscontrato il seguente errore quando ho provato questo: ** Errore in Ops.factor (ref, target): set di fattori di livello sono diversi ** Tuttavia, ** DT [, lista (bestdist = min (distanza)), da = ref] ** Produce l'output, ma senza il riferimento ref! = target. – weitzner