有效地将矩阵分割为中心

时间:2017-03-07 06:09:55

标签: r

给出以下矩阵:

set.seed(1)
x <- matrix(rnorm(15),5,3)


           [,1]       [,2]       [,3]
[1,] -0.6264538 -0.8204684  1.5117812
[2,]  0.1836433  0.4874291  0.3898432
[3,] -0.8356286  0.7383247 -0.6212406
[4,]  1.5952808  0.5757814 -2.2146999
[5,]  0.3295078 -0.3053884  1.1249309

我想提供一个行数与x相同的行,其中整数值介于1和x的列数之间,例如

split_vector = c(1, 2, 3, 1, 2)

并应用将矩阵x拆分为三个矩阵的操作,每个矩阵的大小与x相同。第一个包含split_vector中相应索引左侧每行中的所有列,第二个包含split_vector中索引给出的条目,第三个包含所有其他条目。例如,分别将这些矩阵表示为M1, M2, M3,然后:

M2 <- matrix(rep(F, prod(dim(x))), ncol = ncol(x))
M2[cbind(seq_len(nrow(x)), split_vector)] <- T
M2[M2] <- x[M2] # very naughty coercion here
> M2
           [,1]       [,2]       [,3]
[1,] -0.6264538  0.0000000  0.0000000
[2,]  0.0000000  0.4874291  0.0000000
[3,]  0.0000000  0.0000000 -0.6212406
[4,]  1.5952808  0.0000000  0.0000000
[5,]  0.0000000 -0.3053884  0.0000000

3 个答案:

答案 0 :(得分:2)

创建输出矩阵

out1 <- out2 <- out3 <- matrix(0, nrow(x), ncol(x))

创建满足每个条件的指标,并用于添加x

中的相关值
id1 <- col(x) < v
out1[id1] <- x[id1]

id2 <- col(x) == v
out2[id2] <- x[id2]

id3 <- !(id2 + id1)
out3[id3] <- x[id3]

输出

> out1
           [,1]      [,2] [,3]
[1,]  0.0000000 0.0000000    0
[2,]  0.1836433 0.0000000    0
[3,] -0.8356286 0.7383247    0
[4,]  0.0000000 0.0000000    0
[5,]  0.3295078 0.0000000    0
> out2
           [,1]       [,2]       [,3]
[1,] -0.6264538  0.0000000  0.0000000
[2,]  0.0000000  0.4874291  0.0000000
[3,]  0.0000000  0.0000000 -0.6212406
[4,]  1.5952808  0.0000000  0.0000000
[5,]  0.0000000 -0.3053884  0.0000000
> out3
     [,1]       [,2]       [,3]
[1,]    0 -0.8204684  1.5117812
[2,]    0  0.0000000  0.3898432
[3,]    0  0.0000000  0.0000000
[4,]    0  0.5757814 -2.2146999
[5,]    0  0.0000000  1.1249309

答案 1 :(得分:1)

我能够使用来自here的想法。

set.seed(1)
x <- matrix(rnorm(15),5,3)
split_vector = c(1, 2, 3, 1, 2)

x = data.frame(cbind(x,split_vector)) #cbind x and split_vector so that 'apply' can be used on rows

M1 = function(v, n){
    extract = v[seq_along(v) < n]
    l = length(v) - length(extract)
    return(c(extract, rep(0, l)))
}

M2 = function(v, n){
    extract = v[seq_along(v) == n]
    l1 = n-1
    l2 = length(v) - n
    return(c(rep(0, l1), extract, rep(0, l2)))
}

M3 = function(v, n){
    extract = v[seq_along(v) > n]
    l = length(v) - length(extract)
    return(c(rep(0, l), extract))
}

t(apply(x, 1, function(a) M1(v = a[-length(a)], n = a[length(a)])))
#           [,1]      [,2] [,3]
#[1,]  0.0000000 0.0000000    0
#[2,]  0.1836433 0.0000000    0
#[3,] -0.8356286 0.7383247    0
#[4,]  0.0000000 0.0000000    0
#[5,]  0.3295078 0.0000000    0

t(apply(x, 1, function(a) M2(v = a[-length(a)], n = a[length(a)])))
#          [,1]       [,2]       [,3]
#[1,] -0.6264538  0.0000000  0.0000000
#[2,]  0.0000000  0.4874291  0.0000000
#[3,]  0.0000000  0.0000000 -0.6212406
#[4,]  1.5952808  0.0000000  0.0000000
#[5,]  0.0000000 -0.3053884  0.0000000

t(apply(x, 1, function(a) M3(v = a[-length(a)], n = a[length(a)])))
#     [,1]       [,2]       [,3]
#[1,]    0 -0.8204684  1.5117812
#[2,]    0  0.0000000  0.3898432
#[3,]    0  0.0000000  0.0000000
#[4,]    0  0.5757814 -2.2146999
#[5,]    0  0.0000000  1.1249309

答案 2 :(得分:1)

您可能不会为此找到现成功能,但您可以尝试以下内容。在这里,我使用了来自&#34; reshape2&#34;的melt。用于将list转换为data.frame的包(然后我将其转换为matrix以进行矩阵索引)。

myFun <- function(inmat, splitvec) {
  require(reshape2)
  M1 <- M2 <- M3 <- `dim<-`(rep(0, prod(dim(inmat))), dim(inmat))
  M1Val <- as.matrix(rev(melt(lapply(splitvec, function(x) (1:x)[-x]))))
  M2Val <- cbind(seq_len(nrow(inmat)), splitvec)
  M3Val <- as.matrix(rev(melt(lapply(splitvec, function(x) (x:ncol(inmat))[-1]))))
  list(M1 = {M1[M1Val] <- inmat[M1Val]; M1},
       M2 = {M2[M2Val] <- inmat[M2Val]; M2},
       M3 = {M3[M3Val] <- inmat[M3Val]; M3})
}

使用样本数据,您将获得3个矩阵的列表,如下所示:

myFun(x, split_vector)
## $M1
##            [,1]      [,2] [,3]
## [1,]  0.0000000 0.0000000    0
## [2,]  0.1836433 0.0000000    0
## [3,] -0.8356286 0.7383247    0
## [4,]  0.0000000 0.0000000    0
## [5,]  0.3295078 0.0000000    0
## 
## $M2
##            [,1]       [,2]       [,3]
## [1,] -0.6264538  0.0000000  0.0000000
## [2,]  0.0000000  0.4874291  0.0000000
## [3,]  0.0000000  0.0000000 -0.6212406
## [4,]  1.5952808  0.0000000  0.0000000
## [5,]  0.0000000 -0.3053884  0.0000000
## 
## $M3
##      [,1]       [,2]       [,3]
## [1,]    0 -0.8204684  1.5117812
## [2,]    0  0.0000000  0.3898432
## [3,]    0  0.0000000  0.0000000
## [4,]    0  0.5757814 -2.2146999
## [5,]    0  0.0000000  1.1249309
##