【问题标题】:Vectorisation of for loop with multiple conditions具有多个条件的 for 循环向量化
【发布时间】:2017-05-26 23:39:53
【问题描述】:
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

【问题讨论】:

    标签: r for-loop conditional-statements vectorization


    【解决方案1】:

    这是对基础 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
    

    此解决方案使用矩阵只是具有维度属性的向量这一事实。 which 在底层向量中找到 1 的位置。

    第二行中的第二项c(1, -1)[(ones %% 2 == 0L) + 1L] 允许根据原始位置是偶数还是奇数来选择将用于拆分个值的向量的“对”元素。这在这里行得通,因为有偶数行,这在这个配对元素的问题中是必要的。

    接下来的行根据元素是否最初是一个 (0.5) 或者它是否是相邻的对元素 (-0.5) 来填充矩阵。请注意,第二个命令利用了底层矢量位置概念。


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

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

    然后将[&lt;-与减法相结合

    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
    

    【讨论】:

    • “接受”的答案是在清晰详细的解释的基础上选择的。谢谢。
    【解决方案2】:

    创建一个表示行组的向量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,]
    

    【讨论】:

      【解决方案3】:

      这是另一种方法:

      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
      

      【讨论】:

        【解决方案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
        

        【讨论】:

        • 变体 - (dummies - dummies[c(2:1,4:3,6:5),])/2
        猜你喜欢
        • 2021-07-19
        • 2023-01-29
        • 2020-08-21
        • 2020-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-06
        • 2014-03-15
        相关资源
        最近更新 更多