矩阵改变乐趣

时间:2015-08-13 11:14:21

标签: r matrix dataframe

我正在使用的矩阵看起来像这样

m <- matrix(rep(c(0,1),10),ncol=2,nrow=5)
colnames(m)<-c(2,5)

所以矩阵在pos 2和5处有行。所有不在colnames中的pos都必须全为0

        2    5
[1,]    0    1
[2,]    1    0
[3,]    0    1
[4,]    1    0
[5,]    0    1

应该是

        1 2 3 4 5
[1,]    0 0 0 0 1
[2,]    0 1 0 0 0
[3,]    0 0 0 0 1
[4,]    0 1 0 0 0
[5,]    0 0 0 0 1

该函数需要接受一个结束参数(在这个例子中它是5)

是否存在一种在非常大的基质中快速的解决方案?我谈论了类似于此事的1400次10 Mil oder

2 个答案:

答案 0 :(得分:1)

我们根据初始矩阵('m1')中列名的最大值创建一个'{0'的正方形matrix。在示例中,它是'5'。因此,我们创建的'm2'是维度5X5

n <- max(as.numeric(colnames(m1)))
m2 <- matrix(0, n,n)

使用melt中的reshape2,我们将'm1'的'宽'格式转换为'long'格式,subset生成的'data.frame',删除行'value'为'0'。根据第一列和第二列创建行/列索引,将其转换为matrix并使用它将'm2'中的'0'值替换为1.

library(reshape2)
m2[as.matrix(subset(melt(m1), value!=0)[,-3])] <- 1
m2
#     [,1] [,2] [,3] [,4] [,5]
#[1,]    0    0    0    0    1
#[2,]    0    1    0    0    0
#[3,]    0    0    0    0    1
#[4,]    0    1    0    0    0
#[5,]    0    0    0    0    1

或者base R选项会创建没有meltcbind行/列索引的行/列索引,并将'm2'中的值替换为1。

 m2[cbind(seq(n), c(as.numeric(colnames(m1))[col(m1)]*m1))] <- 1

编辑:

如果'm1'中的值不是全1

 m2[cbind(seq(n), c(as.numeric(colnames(m1))[col(m1)]*m1))] <- m1[!!m1]

为了便于理解,上面的代码可以分成不同的部分。 col(m1)给出原始矩阵的列索引。

 col(m1)
 #     [,1] [,2]
 #[1,]    1    2
 #[2,]    1    2
 #[3,]    1    2
 #[4,]    1    2
 #[5,]    1    2

通过使用该数字索引,我们可以在转换为'numeric'后将该值更改为'm1'的列名。输出为vector

 as.numeric(colnames(m1))[col(m1)]
 #[1] 2 2 2 2 2 5 5 5 5 5

乘以'm1'将'1'值替换为我们在上一步中获得的值

as.numeric(colnames(m1))[col(m1)]*m1
#     2 5
#[1,] 0 5
#[2,] 2 0
#[3,] 0 5
#[4,] 2 0
#[5,] 0 5

我们可以将它(c)连接到vector以创建列索引

 c(as.numeric(colnames(m1))[col(m1)]*m1)
 #[1] 0 2 0 2 0 5 0 5 0 5

获取'row'索引的'{1}}'n'。

seq

当我们 seq(n) #[1] 1 2 3 4 5 带有列索引的行索引时,由于循环,行索引会重复自己到列索引的长度

cbind

这可用于从'm2'

获取相应的元素
  cbind(seq(n),  c(as.numeric(colnames(m1))[col(m1)]*m1))
  #     [,1] [,2]
  #[1,]    1    0
  #[2,]    2    2
  #[3,]    3    0
  #[4,]    4    2
  #[5,]    5    0
  #[6,]    1    5
  #[7,]    2    0
  #[8,]    3    5
  #[9,]    4    0
  #[10,]   5    5

我们分配给1

在编辑部分,我使用了 m2[cbind(seq(n), c(as.numeric(colnames(m1))[col(m1)]*m1))] #[1] 0 0 0 0 0 ,它为所有不为0的值返回逻辑矩阵!!m1。通过对TRUE/FALSE进行子集,我们得到m1[!!m1]的{​​{1}}这些值可用于替换。

或者更快的方法是使用vector创建sparseMatrix。如上所述,我们创建行('i')和列('j')索引,子集'i'和'j'仅包含非零值(因为它不适用于{{1 }),并指定library(Matrix)。在这里,我们不必创建初始矩阵'm2'。

sparseMatrix

使用x=1换行将其转换为常规矩阵

 library(Matrix)
 j <- c(as.numeric(colnames(m1))[col(m1)]*m1)
 i <- rep(seq(n), length.out=length(j))
 sparseMatrix(i[j!=0], j[j!=0], x=1)
 #   5 x 5 sparse Matrix of class "dgCMatrix"

 #[1,] . . . . 1
 #[2,] . 1 . . .
 #[3,] . . . . 1
 #[4,] . 1 . . .
 #[5,] . . . . 1

数据

as.matrix

答案 1 :(得分:1)

这是一种类似的解决方案,没有熔化基质。

首先,我们将从最后一列获取值并分配一个矩阵(类似于@akruns方法)

indx <- as.numeric(colnames(m)[ncol(m)])
m2 <- matrix(0, ncol = indx, nrow = nrow(m))

然后,我们将简单地将列名添加到新矩阵并根据匹配的列名插入旧矩阵

colnames(m2) <- seq_len(indx)
m2[, colnames(m)] <- m
m2
#      1 2 3 4 5
# [1,] 0 0 0 0 1
# [2,] 0 1 0 0 0
# [3,] 0 0 0 0 1
# [4,] 0 1 0 0 0
# [5,] 0 0 0 0 1