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

Ton*_*ony 11 for-loop r vectorization conditional-statements

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")
Run Code Online (Sandbox Code Playgroud)

我有一个假人矩阵

> 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
Run Code Online (Sandbox Code Playgroud)

我知道我的假人是相关的,因为第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 
Run Code Online (Sandbox Code Playgroud)

为此,我执行以下操作:

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
   }
 }
Run Code Online (Sandbox Code Playgroud)

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

lmo*_*lmo 12

这是基地R的一次尝试

# get locations of ones
ones <- which(dummies == 1)
# get adjacent locations
news <- ones + c(1L, -1L)[(ones %% 2 == 0L) + 1L]

# fill out matrix
dummiesDone <- dummies * 0.5
dummiesDone[news] <- -0.5

dummiesDone
        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
Run Code Online (Sandbox Code Playgroud)

该解决方案使用矩阵仅仅是具有维度属性的向量的事实.which在底层矢量中找到1的位置.

第二行中的第二项c(1, -1)[(ones %% 2 == 0L) + 1L]允许基于原始位置是偶数还是奇数来选择将用于分割1值的矢量的"对"元素.这可以在这里工作,因为存在偶数行,这在配对元素的这个问题中是必需的.

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


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

# get locations of ones
ones <- which(dummies == 1)
# get adjacent locations
news <- ones + c(1L, -1L)[(ones %% 2 == 0L) + 1L]
Run Code Online (Sandbox Code Playgroud)

然后结合[<-减法

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
Run Code Online (Sandbox Code Playgroud)


Mar*_*gan 6

创建一个指示行组的向量grp,并从组的rowsum(dummies, grp) / 2每个成员中减去组均值,如

grp = rep(seq_len(nrow(dummies) / 2), each=2)
dummies - rowsum(dummies, grp)[grp,] / 2
Run Code Online (Sandbox Code Playgroud)

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

dummies - (rowsum(dummies, grp) / tabulate(grp))[grp,]
Run Code Online (Sandbox Code Playgroud)


Pie*_*une 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
Run Code Online (Sandbox Code Playgroud)