Как удалить матрицы из списка, которые являются дубликатами в пределах ошибки с плавающей запятой?


Этот вопрос аналогичен вопросам, которые были заданы относительно ошибки с плавающей запятой в других языках (например, здесь), однако я не нашел удовлетворительного решения.

Я работаю над проектом, который включает в себя исследование матриц, которые разделяют определенные характеристики. Кроме того, мне нужно знать, сколько матриц в списке уникальны.
 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)))
Этот список затем заполняется вычислениями из данных, основанных на элементах samples_list. После mat_list был заполнен, мне нужно удалить дубликаты. Работает
mat_list <- unique(mat_list)

Сужает круг вопросов довольно сильно; однако многие из этих элементов действительно находятся в пределах погрешности машины друг от друга. Функция unique не позволяет задавать точность, и я не смог найти исходный код для модификации.

Одна идея у меня была такая:

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)
}
Но это касается только попарных различий. Было бы просто, но, скорее всего, неэффективно делать это с вложенными циклами for.

Какие методы вы знаете, или какие идеи у вас есть, чтобы решить проблему идентификации и удаления матриц, которые находятся в пределах машинной ошибки быть дубликатами?

2 5

2 ответа:

Вот функция, которая применяет all.equal к каждой паре с помощью outer и удаляет все дубликаты:

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

Пример:

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"

Я полагаю, что вы ищете all.equal, который сравнивает объекты "в пределах ошибки машины". Проверьте ?all.equal.