【问题标题】:Replacing singular values with lists in a matrix用矩阵中的列表替换奇异值
【发布时间】:2012-06-03 05:37:23
【问题描述】:

给定矩阵

test <- structure(list(X1 = c(3L, 0L, 3L, 1L, 2L, 2L, 1L, 2L, 2L, 3L), 
X2 = c(2L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), X3 = c(0L, 
0L, 3L, 0L, 2L, 2L, 3L, 0L, 0L, 2L), X4 = c(1L, 1L, 1L, 0L, 
3L, 1L, 3L, 1L, 1L, 1L), X5 = c(3L, 3L, 1L, 3L, 1L, 3L, 2L, 
3L, 3L, 3L), X6 = c(3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L
), X7 = c(2L, 2L, 2L, 3L, 2L, 2L, 3L, 2L, 2L, 2L), X8 = c(3L, 
0L, 1L, 0L, 1L, 1L, 3L, 0L, 0L, 1L), X9 = c(3L, 3L, 3L, 3L, 
3L, 3L, 3L, 3L, 3L, 3L)), .Names = c("X1", "X2", "X3", "X4", 
"X5", "X6", "X7", "X8", "X9"), row.names = c("1", "2", "3", "4", 
"5", "6", "7", "8", "9", "10"), class = "data.frame")

我试图用数字序列 c(0,0,1) 替换“1”的每个实例,用 c(0,1,0) 替换 2,用 (1,0,1) 替换 3,和 0 乘 (0,0,0)。矩阵中的每个值都应替换为这些三个二进制值序列之一。结果矩阵的nrow 应该是nrow(test) * 3。显然我尝试使用索引test[test == 1] &lt;- c(0,0,1),但这会返回错误rhs is the wrong length for indexing by a logical matrix。替换功能在这里似乎也不起作用,返回相同的错误消息。有什么想法吗?

【问题讨论】:

    标签: r matrix replace


    【解决方案1】:

    由于结果的维度不同(3 维数组而不是 2 维矩阵),所以不能一一替换元素。

    您可以使用apply:if 经常用于对矩阵的每一列或每一行应用一个函数,但我们也可以使用它对每个元素应用一个函数。

    apply( 
      test, 
      1:2, 
      function(u) list(c(0,0,0), c(0,0,1), c(0,1,0), c(1,0,1))[[u+1]] 
    )
    

    【讨论】:

    • +1 表示apply 可以同时用于不同的边距。这对我来说是个新闻!
    • 我也是。认为这很优雅,但因为我确实知道apply 是 n 维的,所以我对矢量方面的巧妙选择印象最深。
    【解决方案2】:

    你可以这样做:

    Z <- matrix(c(0, 1, 0, 0,
                  0, 0, 1, 0,
                  0, 0, 0, 1), nrow = 3)
    
    sapply(test, function(i)Z[,i+1])
    #      X1 X2 X3 X4 X5 X6 X7 X8 X9
    # [1,]  0  1  0  0  0  0  1  0  0
    # [2,]  0  0  1  0  0  0  0  0  0
    # [3,]  1  0  0  0  1  1  0  1  1
    # ...
    # [28,]  0  1  1  0  0  0  1  0  0
    # [29,]  0  0  0  0  0  0  0  0  0
    # [30,]  1  0  0  0  1  1  0  0  1
    

    【讨论】:

      【解决方案3】:

      您可以使用 switch 扩展:

      matrix( sapply( c(1+data.matrix(test)), 
                          switch, c(0,0,0), c(0,0,1), c(0,1,0), c(1,0,1)) , 
              nrow=nrow(test)*3 ) 
            [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
       [1,]    1    0    0    0    1    1    0    1    1
       [2,]    0    1    0    0    0    0    1    0    0
       [3,]    1    0    0    1    1    1    0    1    1
       [4,]    0    0    0    0    1    1    0    0    1
       [5,]    0    0    0    0    0    0    1    0    0
       [6,]    0    1    0    1    1    1    0    0    1
       snipped remaining rows
      
      
      str( matrix( sapply( c(1+data.matrix(test)), 
                          switch, c(0,0,0), c(0,0,1), c(0,1,0), c(1,0,1)) , 
              nrow=nrow(test)*3 ) )
        num [1:30, 1:9] 1 0 1 0 0 0 1 0 1 0 ...
      

      【讨论】:

        【解决方案4】:

        您的输入是一个数据框,因此双应用方法也可以:

        f <- function(u) list(c(0,0,0), c(0,0,1), c(0,1,0), c(1,0,1))[[u+1]] 
        #  borrowed from Vincent Zoonekynd's answer
        sapply(test, sapply, f)
        

        请注意,输出完全符合 OP 中的要求(“结果矩阵的第 n 行应为 nrow(test) * 3”)——这可能优于也可能不优于 3 维数组(@ 的结果987654322@),这取决于您想要实现的目标。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多