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)
创建一个指示行组的向量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)
这是另一种方法:
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)