【问题标题】:Apply function to each cell of matrix in R将函数应用于 R 中矩阵的每个单元格
【发布时间】:2017-04-02 07:01:21
【问题描述】:

我正在尝试对 R 中数据表的每个单元格执行一个函数,根据此循环的结果创建第二个单元格。例如,假设我有矩阵 A

    Ad1    Ad2    Ad3    Ad4
    AA      6       0     10
    AB      7      10     12
    AC      0       0     15

我正在尝试创建矩阵 B

    Ad1    Ad2    Ad3    Ad4
    AA      1       0      1
    AB      1       0      1
    AC      0       0      1

如果每个单元格的值 > 0,则每个单元格都假定值为 1 并且该列减去该单元格的总和也大于 0。

例如,AA~Ad2 为 6,列的和为 7 (6 + 7 + 0 - 6);则矩阵 B 中的 AA~Ad2 取值为 1。

有没有办法在不执行循环的情况下执行此操作?我已经设法通过一个循环来做到这一点,但它花费的时间太长了:

A = read.table(text="Ad1    Ad2    Ad3    Ad4
AA     6      0     10
AA     7     10     12
AA     0     0     15", header=TRUE)

B = read.table(text="Ad1    Ad2    Ad3    Ad4
AA     0      0     0
AA     0     0     0
AA     0     0     0", header=TRUE)

for (i in 1:nrow(B)) {
    for (j in 2:ncol(B)) {
        if ((sum(A[,j], na.rm = T) - ifelse(is.na(A[i,j]), 0, A[i,j]))> 0 &
        ifelse(is.na(A[i,j]), 0, A[i,j]) > 0 ) 
        {B[i,j] <- 1}
    }
}

【问题讨论】:

    标签: r loops apply


    【解决方案1】:

    我们可以通过创建两个逻辑矩阵来做到这一点而无需循环 -1)检查数字列值是否大于 0(A[-1] &gt; 0),2)检查列和与列值的差是否也大于 0。如果两者都是 TRUE(&amp; 条件),则将逻辑矩阵转换为二进制(+)并将其分配给数据集的子集(A[-1]

    A[-1] <-  +(colSums(A[-1])[col(A[-1])]-A[-1]>0 & A[-1] > 0)
    A
    #  Ad1 Ad2 Ad3 Ad4
    #1  AA   1   0   1
    #2  AB   1   1   1
    #3  AC   0   0   1
    

    【讨论】:

      【解决方案2】:

      这里是 2 行中的另一种基本 R 方法。第一个拉出可能减少复制的矩阵。第二行计算结果,首先检查值是否大于 0,然后检查总 colSum 是否大于每个元素。这部分是通过 rep 和 each 参数部分完成的。

      # extract matrix from data.frame
      myMat <- as.matrix(A[-1])
      # calculate result and store in data.frame
      A[-1] <- (myMat > 0) * ((rep(colSums(myMat), each=nrow(myMat))- myMat) > 0)
      A
        Ad1 Ad2 Ad3 Ad4
      1  AA   1   0   1
      2  AA   1   0   1
      3  AA   0   0   1
      

      【讨论】:

        【解决方案3】:

        这是一个使用两个逻辑表达式对原始矩阵求值的解决方案:

        (A &gt; 0 &amp; (colSums(A) - A &gt; 0)) * 1.0

        &amp; 的左侧检查值是否大于零,而右侧检查与列总和相关的要求。

        它们各自产生一个与A 相同维度的逻辑矩阵。然后,&amp; 允许您组合逻辑矩阵以生成一个新矩阵,其中仅当两个输入矩阵中的单元格均为 TRUE 时,单元格才为 TRUE。

        最后,* 1.0 将逻辑矩阵转换为数字。

        【讨论】:

        • 您也可以尝试purrr::keep(A, is.numeric)先选择数字列。
        • 好建议——对于data.frames,我倾向于使用x[,sapply(x, is.numeric)]之类的东西。我一直想看看purrr。好像有一些有用的功能!
        【解决方案4】:

        你也可以这样做:

        m <- as.matrix(A[,-1])
        colsm <- matrix(colSums(m), ncol = ncol(m), nrow = nrow(m), byrow = T)
        (colsm-m)>0 & m>0)*1
        
        #    Ad2 Ad3 Ad4
        #[1,]   1   0   1
        #[2,]   1   0   1
        #[3,]   0   0   1
        

        【讨论】:

          猜你喜欢
          • 2020-04-10
          • 1970-01-01
          • 2018-05-25
          • 1970-01-01
          • 2018-09-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多