2013-04-29 7 views
5

To pytanie jest podobne do pytań zadawanych w związku z błędem zmiennoprzecinkowym w innych językach (na przykład here), jednak nie znalazłem satysfakcjonującego rozwiązania.Jak usunąć macierze z listy, które są duplikatami w błędach zmiennoprzecinkowych?

Pracuję nad projektem, który obejmuje badanie matryc, które mają pewne cechy. W związku z tym muszę wiedzieć, ile macierzy na liście jest unikalnych.

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))) 

Lista ta jest następnie wypełniana przez obliczeń z danych opartych na elementach samples_list. Po zapełnieniu mat_list muszę usunąć duplikaty. Uruchamianie

mat_list <- unique(mat_list) 

zawęża to wszystko; jednak wiele z tych elementów naprawdę znajduje się w granicach błędu maszyny. Funkcja unique nie pozwala na określenie precyzji i nie udało mi się znaleźć kodu źródłowego do modyfikacji.

Jeden pomysł miałem było to:

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) 
} 

ale to wygląda tylko na różnice parami. Byłoby to proste, ale najprawdopodobniej nieskuteczne, aby to zrobić z zagnieżdżonymi pętlami for.

Jakie metody znasz lub jakie masz pomysły na rozwiązywanie problemu identyfikacji i usuwania macierzy, które są w obrębie błędu maszynowego polegającego na duplikowaniu?

+0

można umieścić kilka przykładów, gdzie uważasz, że odpowiedź jest "równy" i "nie równy" i określić, dlaczego? W tej chwili masz "źródło danych", ale nikt inny tego nie robi. Zachęcamy do używania 'dput (mat)'. –

Odpowiedz

6

Oto funkcja, która dotyczy all.equal do każdej pary z wykorzystaniem outer i usuwa wszystkie duplikaty:

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] 
} 

Przykład:

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

To dobre kodowanie! –

+0

To ciekawe podejście, nie wiedziałem o funkcji 'all.equal'. Wydaje się, że zużywa dużo pamięci: spróbuj użyć go na zestawie macierzy wymiaru 360x300, a zobaczysz, co mam na myśli. Na przykład: 'M1 <- matrix (dane = 0, nrow = 360, ncol = 300); M2 <- M1 + rep (1e-17,300); wszystkie <- lista (M1, M2); all <- rep (all, 30) 'Powinno to rozpoznać, że wszystkie są macierzą zero, ale mój komputer (z 12 Gb RAM) nie może sobie z tym poradzić. –

+0

@D_Watkins, nieznacznie zredagowałem swoją odpowiedź. Zmiana powinna lepiej wykorzystywać pamięć. – flodel

1

Wierzę, że szukasz all.equal, która porównuje obiekty "w obrębie błędu maszyny". Sprawdź ?all.equal.

Powiązane problemy