2012-01-12 5 views
3

У меня есть список разреженных векторов (в R). Мне нужно преобразовать этот список в разреженную матрицу. Выполнение этого задания через цикл занимает много времени.Создание разреженной матрицы из списка разреженных векторов

sm<-spMatrix(length(tc2),n.col) 
for(i in 1:length(tc2)){ 
    sm[i,]<-(tc2[i])[[1]]; 
} 

Есть ли лучший способ?

+0

я могу ответить, но некоторые более необходимо руководство. Сохраняются ли эти векторы в любом разреженном формате? Например. вы сохраняете 'tc2 [[1]]' как числовой вектор с большим количеством 0s или используете разреженную матрицу для представления каждого вектора? Можете ли вы привести пример данных для работы? – Iterator

+0

@DAF - Был ли мой ответ на вопрос, что вы спрашивали? Если это так, вы можете принять его, нажав галочку слева. Если нет, можете ли вы добавить пример типа разреженных векторов, который вы хотите объединить в разреженной матрице? Приветствия. –

+0

@iterator - я могу сделать шаг назад и начать со списка «набора предметов», то есть каждая запись представляет собой список чисел, обозначающих элементы/слова, встречающиеся в строке. Я хотел бы иметь разреженное матричное представление этих данных. Решение Josh работает для небольших примеров, но на образце с 10K строк и 10k элементов у меня заканчивается память (16 G) – DAF

ответ

5

Вот два шага решение:

  • Использование lapply() и as(..., "sparseMatrix"), чтобы преобразовать список sparseVectors в список одного столбца sparseMatrices.

  • Использование do.call() и cBind() совместить sparseMatrices в одном разреженной матрицы.


require(Matrix) 

# Create a list of sparseVectors 
ss <- as(c(0,0,3, 3.2, 0,0,0,-3), "sparseVector") 
l <- replicate(3, ss) 

# Combine the sparseVectors into a single sparseMatrix 
l <- lapply(l, as, "sparseMatrix") 
do.call(cBind, l) 

# 8 x 3 sparse Matrix of class "dgCMatrix" 
#      
# [1,] . . . 
# [2,] . . . 
# [3,] 3.0 3.0 3.0 
# [4,] 3.2 3.2 3.2 
# [5,] . . . 
# [6,] . . . 
# [7,] . . . 
# [8,] -3.0 -3.0 -3.0 
+1

Спасибо! Это работает на примере и делает то, что я хочу (кроме того, что я использую rBind в do.call, так как у меня есть строки в списке).Тем не менее, по текстовым данным (10K строк и до 10K функций, хотя и очень редких) do.call очень долго висит R, поэтому я в конечном итоге убил его. Какие-либо предложения? – DAF

+0

Не знаете, почему это работает медленно. Похоже, что 'rBind' может фактически рекурсивно называть' rbind2' (который связывает вместе по две строки за раз). Это ** будет очень медленным с большим количеством векторов, чтобы объединиться. Но поскольку я предложил альтернативный подход к построению матрицы, которую вы действительно хотите, я буду продолжать изучать это дальше. Приветствия. –

2

Благодаря Джош О'Брайена для предлагая решение: создать 3 список, а затем создать разреженную матрицу. я включать код для этого здесь:

vectorList2Matrix<-function(vectorList){ 
nzCount<-lapply(vectorList, function(x) length([email protected])); 
nz<-sum(do.call(rbind,nzCount)); 
r<-vector(mode="integer",length=nz); 
c<-vector(mode="integer",length=nz); 
v<-vector(mode="integer",length=nz); 
ind<-1; 
for(i in 1:length(vectorList)){ 
    ln<-length(vectorList[[i]]@i); 
    if(ln>0){ 
    r[ind:(ind+ln-1)]<-i; 
    c[ind:(ind+ln-1)]<-vectorList[[i]]@j+1 
    v[ind:(ind+ln-1)]<-vectorList[[i]]@x 
    ind<-ind+ln; 
    } 
} 
return (sparseMatrix(i=r,j=c,x=v)); 
} 
+0

мне очень помог! Однако я совмещаю векторы одинакового размера, поэтому мое решение содержит немного меньше кода: http://stackoverflow.com/a/32525837/1075993 –

2

Этот сценарий, cbind ИНГ кучу векторов, устанавливается идеально для сброса информации прямо в sparse, column-oriented матрицы (dgCMatrix класса).

Вот функция, которая будет делать это:

sv.cbind <- function (...) { 
    input <- lapply(list(...), as, "dsparseVector") 
    thelength <- unique(sapply(input,length)) 
    stopifnot(length(thelength)==1) 
    return(sparseMatrix( 
      x=unlist(lapply(input,slot,"x")), 
      i=unlist(lapply(input,slot,"i")), 
      p=c(0,cumsum(sapply(input,function(x){length([email protected])}))), 
      dims=c(thelength,length(input)) 
     )) 
} 

С быстрой проверки, это выглядит примерно в 10 раз быстрее, чем принуждение + cBind:

require(microbenchmark) 
xx <- lapply(1:10, function (k) { 
      sparseVector(x=rep(1,100), i=sample.int(1e4,100), length=1e4) 
     }) 
microbenchmark(do.call(sv.cbind, xx), do.call(cBind, lapply(xx,as,"sparseMatrix"))) 
# Unit: milliseconds 
#           expr  min  lq  mean median  uq  max neval cld 
#       do.call(sv.cbind, xx) 1.398565 1.464517 1.540172 1.49487 1.55911 3.455421 100 a 
# do.call(cBind, lapply(xx, as, "sparseMatrix")) 16.037890 16.356268 16.956326 16.59854 17.49956 20.256253 100 b