2013-04-29 4 views
5

Questa domanda è simile alle domande che sono state poste riguardo all'errore in virgola mobile in altre lingue (ad esempio here), tuttavia non ho trovato una soluzione soddisfacente.Come rimuovere le matrici da un elenco duplicato con errore a virgola mobile?

Sto lavorando a un progetto che prevede lo studio di matrici che condividono determinate caratteristiche. Come parte di questo, ho bisogno di sapere quante matrici in una lista sono uniche.

D <- as.matrix(read.table("datasource",...)) 
mat_list <- vector('list',length=length(samples_list)) 
mat_list <- lapply(1:length(samples_list),function(i) matrix(data=0,nrow(D),ncol(D))) 

Questa lista è poi popolato da calcoli dai dati sulla base degli elementi di samples_list. Dopo che mat_list è stato popolato, ho bisogno di rimuovere i duplicati. Correre

mat_list <- unique(mat_list) 

riduce un po 'le cose; tuttavia, molti di questi elementi si trovano davvero all'interno dell'errore della macchina l'uno dell'altro. La funzione unique non consente di specificare la precisione e non sono stato in grado di trovare il codice sorgente per la modifica.

Un'idea che avevo era questa:

ErrorReduction<-function(mat_list, tol=2){ 
    len <- length(mat_list) 
    diff <- mat_list[[i]]-mat_list[[i+1]] 
    for(i in 1:len-1){ 
    if(norm(diff,"i")<tol){ 
    mat_list[[i+1]] <- mat_list[i] 
    } 
    } 
    mat_list<-unique(mat_list) 
    return(mat_list) 
} 

ma questo guarda solo le differenze a coppie. Sarebbe semplice ma molto probabilmente inefficiente per farlo con i cicli nidificati for.

Quali metodi conosci o quali idee hai, di gestione del problema di identificazione e rimozione di matrici che si trovano nell'errore della macchina di essere duplicati?

+0

potete inserire un paio di esempi in cui si pensa che la risposta è "uguale" e "non uguale" e specificare perché? Al momento hai "datasource" ma nessun altro lo fa. Incoraggiamo l'uso dell'uso di 'dput (mat)'. –

risposta

6

Ecco una funzione che si applica all.equal per ogni coppia utilizzando outer e rimuove tutti i duplicati:

approx.unique <- function(l) { 
    is.equal.fun <- function(i, j)isTRUE(all.equal(norm(l[[i]] - l[[j]], "M"), 0)) 
    is.equal.mat <- outer(seq_along(l), seq_along(l), Vectorize(is.equal.fun)) 
    is.duplicate <- colSums(is.equal.mat * upper.tri(is.equal.mat)) > 0 
    l[!is.duplicate] 
} 

Un esempio:

a <- matrix(runif(12), 4, 3) 
b <- matrix(runif(12), 4, 3) 
c <- matrix(runif(12), 4, 3) 

all <- list(a1 = a, b1 = b, a2 = a, a3 = a, b2 = b, c1 = c) 

names(approx.unique(all)) 
# [1] "a1" "b1" "c1" 
+0

Questa è una bella codifica! –

+0

Questo è un approccio interessante, non ero a conoscenza della funzione 'all.equal'. Sembra che usi molta memoria: prova ad usarlo su una serie di matrici della dimensione 360x300 e vedrai cosa intendo. Ad esempio: 'M1 <- matrice (dati = 0, nrow = 360, ncol = 300); M2 <- M1 + rep (1e-17,300); all <- list (M1, M2); all <- rep (all, 30) 'Questo dovrebbe riconoscere che sono tutti una matrice zero, ma il mio computer (con 12 Gb RAM) non può gestirlo. –

+0

@D_Watkins, ho leggermente modificato la mia risposta. Il cambiamento dovrebbe fare un uso migliore della memoria. – flodel

1

Credo che stiate cercando all.equal che confronta gli oggetti "all'interno dell'errore della macchina". Controlla ?all.equal.

Problemi correlati