2016-03-21 1 views
1

У меня проблема с большой проблемой, и более конкретная проблема, которую я надеюсь, когда-нибудь решит - решить большую проблему. Я бы очень признателен, если у кого-нибудь есть идеи для меня попробовать.Преобразовать огромную разреженную матрицу в data.table для более быстрого подмножества в R

В основном у меня огромная разреженная матрица (около 300k x 150k, первоначально матрица Term-Document, созданная с пакетом R {tm}), который сохраняется как простая триплетная матрица, используя пакет {slam}, и я запускаю функция, которая пересекает множество терминов, а затем подмножает ее на основе этих терминов. К сожалению, процесс подмножества является чрезмерно медленным.

При попытке выяснить, как подмножество быстрее, я наткнулся на пакет data.table, который очень хорошо выполнялся в некоторых тестах, которые я запускал с ним. Однако, когда я пытаюсь преобразовать свою разреженную матрицу в data.table, я получаю

Error in vector(typeof(x$v), nr * nc) : vector size cannot be NA 
In addition: Warning message: 
In nr * nc : NAs produced by integer overflow 

Я понимаю, что это потому, что он пытается преобразовать его в стандартную матрицу первой, которая является технически вектором R, и 300k * 150k значительно выше .Machine$integer.max.

Итак, мой вопрос: кто-нибудь знает, как преобразовать простую матрицу триплетов в data.frame или data.table, не преобразовывая ее сначала в матрицу, тем самым избегая целочисленного переполнения?

Если нет, то у кого-нибудь есть другое обходное решение или b) есть ли какие-либо советы по быстрому подмножеству огромных разреженных матриц и/или простых тройных матриц?

Ниже приведен воспроизводимый пример, с которым можно столкнуться. На моей машине цикл, который подмножает каждый из первых 10 строк, занимает около 3 секунд. Как только мы перейдем к сотням тысяч строк, которые быстро становятся непомерно высокими. Заранее спасибо за помощь:

require(slam) 
STM <- simple_triplet_matrix(i = as.integer(runif(10000000,1,300000)), 
        j = as.integer(runif(10000000,1,150000)), 
        v = rep(rnorm(10), 1000000), 
        nrow = 300000, 
        ncol = 150000) 

start <- Sys.time() 
for (i in 1:10) { 
    vec <- as.matrix(STM[,i]) 
} 
Sys.time() - start 

Sidenote: обратите внимание, что если вы пытаетесь STMm <- as.matrix(STM) вы получите ту же ошибку переполнения я показал выше.

+1

матрица триплет в основном 3 векторы, содержащие координаты ненулевых элементов в 1-м столбцах 2 и значение в 3-м. Возможный подход (я его не тестировал) заключался бы в использовании RCpp-пакета для написания вашего подмножества в C++, передающего триплет на C++ в виде списка из 3 векторов. Должно быть так же быстро, как все, что вы можете сделать в R. – dww

ответ

4

Объект STM на самом деле просто список, вы можете Подмножество нормально:

STM_DT <- data.table(i = STM$i, j = STM$j, v = STM$v)

Это дает:

> STM_DT 
       i  j   v 
     1: 186598 756 0.34271080 
     2: 278329 72334 2.03924976 
     3: 178388 32708 1.03925605 
     4: 260635 101424 0.05780086 
     5: 169321 126202 1.00027529 
     ---       
9999996: 96209 90019 -1.09341023 
9999997: 54467 16612 -2.08070273 
9999998: 179029 96906 -0.86197333 
9999999: 153017 148731 0.47765003 
10000000: 104145 123291 0.24258613 

скорость почти мгновенно

+0

Спасибо. Замечательно. – seth127