具有多个条件的for循环的矢量化

时间:2017-01-12 00:57:18

标签: r for-loop conditional-statements vectorization

dummies  = matrix(c(0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0), nrow=6, ncol=6) 
colnames(dummies)  <- c("a","b", "c", "d", "e", "f")

我有一个带假人的矩阵

> dummies
     a b c d e f
[1,] 0 0 0 0 1 0
[2,] 0 0 1 0 0 0
[3,] 1 0 0 0 0 0
[4,] 0 0 0 0 0 1
[5,] 0 1 0 0 0 0
[6,] 0 0 0 1 0 0

我知道我的假人是相关的,因为第1行被分为2,3和4,以及5和6.我想在同一行中的每个虚拟代码(1)之间拆分同一行:

> dummies
        a    b    c    d    e    f
[1,]  0.0  0.0 -0.5  0.0  0.5  0.0
[2,]  0.0  0.0  0.5  0.0 -0.5  0.0
[3,]  0.5  0.0  0.0  0.0  0.0 -0.5
[4,] -0.5  0.0  0.0  0.0  0.0  0.5
[5,]  0.0  0.5  0.0 -0.5  0.0  0.0
[6,]  0.0 -0.5  0.0  0.5  0.0  0.0 

为实现这一目标,我将执行以下操作:

dummies <- ifelse(dummies==1, 0.5, 0)
for (i in 1:nrow(dummies)){
    column = which(dummies[i,] %in% 0.5)
    if (i %% 2 != 0) {      
      dummies[i+1, column] <- -0.5
    } else {            
      dummies[i-1, column] <- -0.5
   }
 }

我的问题是我是否可以用矢量化代码实现这一点。在这种情况下,我无法弄清楚如何使用ifelse因为我无法将它与行索引结合起来在每一行上找到0.5

4 个答案:

答案 0 :(得分:12)

以下是基地R的一次尝试

which

此解决方案使用矩阵只是具有维度属性的向量这一事实。 c(1, -1)[(ones %% 2 == 0L) + 1L]在基础向量中找到1的位置。

第二行中的第二项,# get locations of ones ones <- which(dummies == 1) # get adjacent locations news <- ones + c(1L, -1L)[(ones %% 2 == 0L) + 1L] 允许选择&#34;对#34;根据原始位置是偶数还是奇数,将用于分割1值的向量元素。这可以在这里工作,因为存在偶数行,这在配对元素的问题中是必需的。

下一行根据元素最初是一(0.5)还是相邻的对元素(-0.5)填充矩阵。请注意,第二个命令利用基础向量位置概念。

第二种方法借鉴了hubertl,thelatemail和martin-morgan的帖子和评论的概念,首先在正确的位置从原始矩阵中减去0.5以获得与上述相同的索引

[<-

然后将dummies[c(ones, news)] <- dummies[c(ones, news)] - .5 dummies a b c d e f [1,] 0.0 0.0 -0.5 0.0 0.5 0.0 [2,] 0.0 0.0 0.5 0.0 -0.5 0.0 [3,] 0.5 0.0 0.0 0.0 0.0 -0.5 [4,] -0.5 0.0 0.0 0.0 0.0 0.5 [5,] 0.0 0.5 0.0 -0.5 0.0 0.0 [6,] 0.0 -0.5 0.0 0.5 0.0 0.0 与减法结合起来

{{1}}

答案 1 :(得分:6)

创建一个指示行组grp的向量,并从该组的每个成员中减去该组意味着rowsum(dummies, grp) / 2

grp = rep(seq_len(nrow(dummies) / 2), each=2)
dummies - rowsum(dummies, grp)[grp,] / 2

更一般地说,允许不同大小和无序的组

dummies - (rowsum(dummies, grp) / tabulate(grp))[grp,]

答案 2 :(得分:5)

这是另一种方法:

dummies[] <- sapply(split(dummies, gl(length(dummies)/2,2)), function(v) if(any(!!v))v-.5 else v)
        a    b    c    d    e    f
[1,]  0.0  0.0 -0.5  0.0  0.5  0.0
[2,]  0.0  0.0  0.5  0.0 -0.5  0.0
[3,]  0.5  0.0  0.0  0.0  0.0 -0.5
[4,] -0.5  0.0  0.0  0.0  0.0  0.5
[5,]  0.0  0.5  0.0 -0.5  0.0  0.0
[6,]  0.0 -0.5  0.0  0.5  0.0  0.0

答案 3 :(得分:4)

另一种方法:

dummies - ((dummies[c(1,3,5),]+dummies[c(2,4,6),])/2)[c(1,1,2,2,3,3),]

        a    b    c    d    e    f
[1,]  0.0  0.0 -0.5  0.0  0.5  0.0
[2,]  0.0  0.0  0.5  0.0 -0.5  0.0
[3,]  0.5  0.0  0.0  0.0  0.0 -0.5
[4,] -0.5  0.0  0.0  0.0  0.0  0.5
[5,]  0.0  0.5  0.0 -0.5  0.0  0.0
[6,]  0.0 -0.5  0.0  0.5  0.0  0.0