Удаление столбцов из big.matrix, которые имеют только одно значение

У меня есть очень большая двоичная матрица, хранящаяся как big.matrix для экономии памяти (в противном случае она составляет более 2 ГБ - 5 миллионов столбцов и 100 строк).

r <- 100
c <- 10000
m4 <- matrix(sample(0:1,r*c, replace=TRUE),r,c)
m4 <- cbind(m4, 1)
m4 <- as.big.matrix(m4)

Мне нужно удалить каждый столбец, который имеет только одно уникальное значение (в данном случае только 0 или только 1). Из-за количества столбцов я хочу иметь возможность делать это параллельно.

Как я могу это сделать, сохраняя при этом данные сжатыми как big.matrix? Я могу преобразовать его в df и перебирать столбцы в поисках количества уникальных значений, но это занимает слишком много оперативной памяти.

Спасибо!


person Keshav M    schedule 21.04.2018    source источник
comment
Что-то вроде этого, хорошо? m5 <- m4[, !(colSums(m4) %in% c(0, nrow(m4)))]   -  person    schedule 21.04.2018
comment
К сожалению нет. Прежде всего, это работает только тогда, когда m4 относится к классу matrix, а не big.matrix, как указано в задаче. Кроме того, выходные данные также относятся к классу matrix, занимая слишком много памяти.   -  person Keshav M    schedule 21.04.2018
comment
А, ладно, извиняюсь. Как насчет того, чтобы обернуть подмножество в as.big.matrix или применить операцию подмножества к подмножествам большой матрицы, используя `sub.big.matrix? Я думаю, вы, возможно, уже рассматривали эти варианты?   -  person    schedule 21.04.2018
comment
Используйте Rcpp для создания алгоритма, который возвращает индексы столбцов, которые вы хотите сохранить, на основе вашего критерия. Это должно быть легко, потому что вы уже знаете, как получить доступ к элементам big.matrix в Rcpp. Затем используйте deepcopy.   -  person F. Privé    schedule 22.04.2018


Ответы (1)


Поместите это в файл .cpp и добавьте его с помощью Rcpp::sourceCpp:

// [[Rcpp::depends(BH, bigmemory)]]
#include <bigmemory/MatrixAccessor.hpp>
#include <Rcpp.h>
using namespace Rcpp;

// [[Rcpp::export]]
LogicalVector to_keep(SEXP bm_addr) {

  XPtr<BigMatrix> xptr(bm_addr);
  MatrixAccessor<double> macc(*xptr);

  size_t n = macc.nrow();
  size_t m = macc.ncol();

  double first_val;

  LogicalVector keep(m, false);

  for (size_t j = 0; j < m; j++) {
    first_val = macc[j][0];
    for (size_t i = 1; i < n; i++) {
      if (macc[j][i] != first_val) {
        keep[j] = true;
        break;
      }
    }
  }

  return keep;
}

/*** R
library(bigmemory)
r <- 100
c <- 10000
m4 <- matrix(sample(0:1,r*c, replace=TRUE),r,c)
m4 <- cbind(m4, 1)
m4 <- as.big.matrix(m4)
m4[, 1] <- 1
m4[, 2] <- 0

keep <- to_keep(m4@address)
m4.keep <- deepcopy(m4, cols = which(keep))
*/
person F. Privé    schedule 21.04.2018