假设我有一个非常大的稀疏数据矩阵,但我只对它的一个样本感兴趣,使它变得更加稀疏。假设我还有一个三元组的数据帧,包括数据的行/列/值的列(从csv文件导入)。我知道我可以使用库( matrix )的sparseMatrix()函数来创建一个稀疏矩阵
sparseMatrix(i=df$row,j=df$column,x=df$value)然而,由于我的值,我最终得到了一个数百万行乘以数万列的稀疏矩阵(其中大多数是空的,因为我的子集排除了大多数行和列)。所有这些零行和零列最终会扭曲我的一些函数(以集群为例--我最终得到了一个包含原点的集群,而这个原点甚至不是一个有效的点)。我想执行相同的操作,但使用i和j作为行名和列名称。我尝试创建一个密集向量,采样到最大大小,然后使用
denseMatrix <- matrix(0,nrows,ncols,dimnames=c(df$row,df$column))
denseMatrix[as.character(df$row),as.character(df$column)]=df$value(实际上我一直将它设置为1,因为我对本例中的值不感兴趣),但我发现它填充了整个矩阵,因为它需要所有行和列的交叉,而不仅仅是row1*col1,row2*col2……有谁知道如何完成我想要做的事吗?或者,我也可以填充一个稀疏矩阵,然后让它以某种方式丢弃所有的零行和零列,以将自己压缩成更密集的形式(但我希望保留一些对原始行和列数字的引用),感谢您的建议!
下面是一个例子:
> rows<-c(3,1,3,5)
> cols<-c(2,4,6,6)
> mtx<-sparseMatrix(i=rows,j=cols,x=1)
> mtx
5 x 6 sparse Matrix of class "dgCMatrix"
[1,] . . . 1 . .
[2,] . . . . . .
[3,] . 1 . . . 1
[4,] . . . . . .
[5,] . . . . . 1我想去掉第1,3和5列以及第2和4行。这是一个非常简单的例子,但想象一下,如果不是第1,3和5行,它们是1000,3000和5000。那么它们之间就会有更多的空行。下面是使用具有命名行/列的密集矩阵时会发生的情况
> dmtx<-matrix(0,3,3,dimnames=list(c(1,3,5),c(2,4,6)))
> dmtx
2 4 6
1 0 0 0
3 0 0 0
5 0 0 0
> dmtx[as.character(rows),as.character(cols)]=1
> dmtx
2 4 6
1 1 1 1
3 1 1 1
5 1 1 1发布于 2011-08-24 01:49:46
当您说“摆脱”某些列/行时,您的意思是:
> mtx[-c(2,4), -c(1,3,5)]
3 x 3 sparse Matrix of class "dgCMatrix"
[1,] . 1 .
[2,] 1 . 1
[3,] . . 1子集是有效的,所以你只需要找出哪些行和列是空的?如果这是正确的,那么您可以使用colSums()和rowSums(),因为矩阵包已经对它们进行了增强,从而为稀疏矩阵提供了适当的方法。这应该会在操作期间保留稀疏性。
> dimnames(mtx) <- list(letters[1:5], LETTERS[1:6])
> mtx[which(rowSums(mtx) != 0), which(colSums(mtx) != 0)]
3 x 3 sparse Matrix of class "dgCMatrix"
B D F
a . 1 .
c 1 . 1
e . . 1或者,也许更安全
> mtx[rowSums(mtx) != 0, colSums(mtx) != 0]
3 x 3 sparse Matrix of class "dgCMatrix"
B D F
a . 1 .
c 1 . 1
e . . 1发布于 2011-08-24 02:04:47
您的代码几乎可以工作,您只需将行名和列名cbind在一起即可。然后,结果矩阵的每一行都被视为一对,而不是单独处理行和列。
> dmtx <- matrix(0,3,3,dimnames=list(c(1,3,5),c(2,4,6)))
> dmtx[cbind(as.character(rows),as.character(cols))] <- 1
> dmtx
2 4 6
1 0 1 0
3 1 0 1
5 0 0 1如果使用因子,这可能会更快。
> rowF <- factor(rows)
> colF <- factor(cols)
> dmtx <- matrix(0, nlevels(rowF), nlevels(colF),
dimnames=list(levels(rowF), levels(colF)))
> dmtx[cbind(rowF,colF)] <- 1
> dmtx
2 4 6
1 0 1 0
3 1 0 1
5 0 0 1您还可以在调用sparseMatrix时使用这些因素。
> sparseMatrix(i=as.integer(rowF), j=as.integer(colF), x=1,
+ dimnames = list(levels(rowF), levels(colF)))
3 x 3 sparse Matrix of class "dgCMatrix"
2 4 6
1 . 1 .
3 1 . 1
5 . . 1请注意,其他解决方案之一可能会更快;如果有大量数据,转换为因子可能会很慢。
发布于 2011-08-24 03:55:52
您的第一个问题源于这样一个事实,即coordinate list (COO)的行和列索引值不连续。当遇到这种情况时,甚至在处理大多数稀疏矩阵时,我倾向于根据行和列的支持重新排序。
您可以通过两种方式完成此操作:
logical(yourMatrix)的do colSums和rowSums以获得支持值,或者table或bigtabulate (来自bigmemory套件)之类的函数来计算每个值在坐标列表中出现的唯一次数。(我的首选是bigtabulate.)一旦获得支持,就可以使用rank函数(实际上是rank(-1 * support, ties = "first"))根据它们的排名将原始索引映射到新的索引。
此时,如果您使用sparseMatrix创建矩阵,它将只生成一个维度为所有行和列都受支持的矩阵。它不会映射到任何更大的对象。
这类似于@GavinSimpson的方法,尽管他的方法只删除缺少的行和列,而我的方法重新排序,将最大密度放在矩阵的左上角,当您移动到行和列的更大索引时,密度会降低。在我的方法中,为了映射回原始索引,只需创建一对映射:“原始到排名”和“排名到原始”,如果您愿意,您可以完美地重新创建原始数据。
https://stackoverflow.com/questions/7164430
复制相似问题