首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用包括行名和列名的索引向量向矩阵添加值

使用包括行名和列名的索引向量向矩阵添加值
EN

Stack Overflow用户
提问于 2011-08-24 00:37:01
回答 4查看 3.6K关注 0票数 6

假设我有一个非常大的稀疏数据矩阵,但我只对它的一个样本感兴趣,使它变得更加稀疏。假设我还有一个三元组的数据帧,包括数据的行/列/值的列(从csv文件导入)。我知道我可以使用库( matrix )的sparseMatrix()函数来创建一个稀疏矩阵

代码语言:javascript
复制
sparseMatrix(i=df$row,j=df$column,x=df$value)

然而,由于我的值,我最终得到了一个数百万行乘以数万列的稀疏矩阵(其中大多数是空的,因为我的子集排除了大多数行和列)。所有这些零行和零列最终会扭曲我的一些函数(以集群为例--我最终得到了一个包含原点的集群,而这个原点甚至不是一个有效的点)。我想执行相同的操作,但使用i和j作为行名和列名称。我尝试创建一个密集向量,采样到最大大小,然后使用

代码语言:javascript
复制
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……有谁知道如何完成我想要做的事吗?或者,我也可以填充一个稀疏矩阵,然后让它以某种方式丢弃所有的零行和零列,以将自己压缩成更密集的形式(但我希望保留一些对原始行和列数字的引用),感谢您的建议!

下面是一个例子:

代码语言:javascript
复制
> 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。那么它们之间就会有更多的空行。下面是使用具有命名行/列的密集矩阵时会发生的情况

代码语言:javascript
复制
> 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
EN

回答 4

Stack Overflow用户

发布于 2011-08-24 01:49:46

当您说“摆脱”某些列/行时,您的意思是:

代码语言:javascript
复制
> 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(),因为矩阵包已经对它们进行了增强,从而为稀疏矩阵提供了适当的方法。这应该会在操作期间保留稀疏性。

代码语言:javascript
复制
> 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

或者,也许更安全

代码语言:javascript
复制
> 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
票数 4
EN

Stack Overflow用户

发布于 2011-08-24 02:04:47

您的代码几乎可以工作,您只需将行名和列名cbind在一起即可。然后,结果矩阵的每一行都被视为一对,而不是单独处理行和列。

代码语言:javascript
复制
> 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

如果使用因子,这可能会更快。

代码语言:javascript
复制
> 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时使用这些因素。

代码语言:javascript
复制
> 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

请注意,其他解决方案之一可能会更快;如果有大量数据,转换为因子可能会很慢。

票数 4
EN

Stack Overflow用户

发布于 2011-08-24 03:55:52

您的第一个问题源于这样一个事实,即coordinate list (COO)的行和列索引值不连续。当遇到这种情况时,甚至在处理大多数稀疏矩阵时,我倾向于根据行和列的支持重新排序。

您可以通过两种方式完成此操作:

  1. 生成稀疏矩阵以及logical(yourMatrix)的do colSumsrowSums以获得支持值,或者
  2. 使用tablebigtabulate (来自bigmemory套件)之类的函数来计算每个值在坐标列表中出现的唯一次数。(我的首选是bigtabulate.)

一旦获得支持,就可以使用rank函数(实际上是rank(-1 * support, ties = "first"))根据它们的排名将原始索引映射到新的索引。

此时,如果您使用sparseMatrix创建矩阵,它将只生成一个维度为所有行和列都受支持的矩阵。它不会映射到任何更大的对象。

这类似于@GavinSimpson的方法,尽管他的方法只删除缺少的行和列,而我的方法重新排序,将最大密度放在矩阵的左上角,当您移动到行和列的更大索引时,密度会降低。在我的方法中,为了映射回原始索引,只需创建一对映射:“原始到排名”和“排名到原始”,如果您愿意,您可以完美地重新创建原始数据。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7164430

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档