2016-09-02 4 views
3

У меня есть очень большой (~ 500 000 х ~ 500000) разреженные матрицы в R, и я пытаюсь разделить каждую колонку по ее сумме:Колонка масштабирования для очень больших разреженных матриц в R

sm = t(t(sm)/colSums(sm)) 

Однако , когда я это сделаю, я получаю следующее сообщение об ошибке:

# Error in evaluating the argument 'x' in selecting a method for function 't': 
# Error: cannot allocate vector of size 721.1 Gb 

Есть ли лучший способ сделать это в R? Я могу хранить штраф colSums, а также вычислить и сохранить транспонирование разреженной матрицы, но проблема, похоже, при попытке выполнить "/". Похоже, что разреженная матрица преобразуется в полную плотную матрицу.

Любая помощь будет принята с благодарностью. Спасибо!

+0

Как насчет 'sweep (см, 2, colSums (см), \'/\ ')'? – thelatemail

+0

Та же ошибка, что и удаленное предложение:> sm = sweep (sm, 2, colSums (sm), '/') Ошибка: не может выделять вектор размером 1442.2 Gb – user3745472

ответ

4

Это то, что мы можем сделать, если предположить A является dgCMatrix:

[email protected] <- [email protected]/rep.int(colSums(A), diff([email protected])) 

Это требует некоторого понимания dgCMatrix класса.

  1. @x хранит значения нулевой матрицы в упакованном массиве 1D;
  2. @p хранит кумулятивное число ненулевых элементов по столбцу, поэтому diff([email protected]) дает количество ненулевых элементов для каждого столбца.

Повторим каждый элемент colSums(A) по количеству доли не равно нулю элементов в этом столбце, а затем разделить [email protected] этим вектором. В этой связи мы обновляем [email protected] с помощью масштабированных значений. Таким образом, масштабирование столбцов выполняется разреженным образом.


Пример:

library(Matrix) 
set.seed(2); A <- Matrix(rbinom(100,10,0.05), nrow = 10) 

#10 x 10 sparse Matrix of class "dgCMatrix" 

# [1,] . . 1 . 2 . 1 . . 2 
# [2,] 1 . . . . . 1 . 1 . 
# [3,] . 1 1 1 . 1 1 . . . 
# [4,] . . . 1 . 2 . . . . 
# [5,] 2 . . . 2 . 1 . . . 
# [6,] 2 1 . 1 1 1 . 1 1 . 
# [7,] . 2 . 1 2 1 . . 2 . 
# [8,] 1 . . . . 3 . 1 . . 
# [9,] . . 2 1 . 1 . . 1 . 
#[10,] . . . . 1 1 . . . . 

diff([email protected]) ## number of non-zeros per column 
# [1] 4 3 3 5 5 7 4 2 4 1 

colSums(A) ## column sums 
# [1] 6 4 4 5 8 10 4 2 5 2 

[email protected] <- [email protected]/rep.int(colSums(A), diff([email protected])) ## sparse column rescaling 

#10 x 10 sparse Matrix of class "dgCMatrix" 

# [1,] .   . 0.25 . 0.250 . 0.25 . . 1 
# [2,] 0.1666667 . . . .  . 0.25 . 0.2 . 
# [3,] .   0.25 0.25 0.2 .  0.1 0.25 . . . 
# [4,] .   . . 0.2 .  0.2 . . . . 
# [5,] 0.3333333 . . . 0.250 . 0.25 . . . 
# [6,] 0.3333333 0.25 . 0.2 0.125 0.1 . 0.5 0.2 . 
# [7,] .   0.50 . 0.2 0.250 0.1 . . 0.4 . 
# [8,] 0.1666667 . . . .  0.3 . 0.5 . . 
# [9,] .   . 0.50 0.2 .  0.1 . . 0.2 . 
#[10,] .   . . . 0.125 0.1 . . . . 

@thelatemail упоминается другой метод, сначала превращением dgCMatrix в dgTMatrix:

AA <- as(A, "dgTMatrix") 
[email protected] <- [email protected]/colSumns(A)[[email protected] + 1L] 

Для dgTMatrix класса нет @p, но @j, указав индекс столбца (на основе 0) для ни одного элемента матрицы.

+0

Если вы конвертируете в 'dgTMatrix' -' A <- as (A, "dgTMatrix") 'вы можете сделать' A @ x/colSums (A) [A @ j + 1] ', поскольку он имеет слот' A @ j' для индекса столбца. Хороший ответ, хотя, я узнал кое-что о разреженных матрицах :-) – thelatemail

+2

Обычно я использую 'B = A% *% Диагональ (x = 1/colSums (A))'. Но похоже ваше решение ('A @ x <- A @ x/rep.int (colSums (A), diff (A @ p))) немного (~ 2x-3x) быстрее. +1 –