Multiply a data frame row-by-row

后端 未结 4 1327
花落未央
花落未央 2021-01-21 05:25

Input file:

df1 <- data.frame(row.names=c(\"w\",\"x\",\"y\",\"z\"), 
                  A=c(0,0,0,0),
                  B=c(0,1,0,0), 
                  C=c(1,         


        
4条回答
  •  一向
    一向 (楼主)
    2021-01-21 06:19

    If you don't want the combo names in the resulting object, then we can combine elements of @DWin's and @Owen's Answers to provide a truly vectorised approach to the problem. (You can add the combination names as row names with one extra step at the end.)

    First, the data:

    dat <- read.table(con <- textConnection("  A B C D
    w 0 0 1 1
    x 0 1 0 1
    y 0 0 1 1
    z 0 0 0 1
    "), header=TRUE)
    close(con)
    

    Take the combn() idea from @DWin's Answer but use it on the row indices of dat:

    combs <- combn(seq_len(nrow(dat)), 2)
    

    The rows of combs now index the rows of dat that we want to multiply together:

    > combs
         [,1] [,2] [,3] [,4] [,5] [,6]
    [1,]    1    1    1    2    2    3
    [2,]    2    3    4    3    4    4
    

    Now we take the idea @Owen showed, namely dat[i, ] * dat[j, ] with i and j being the first and second rows of combs respectively. We convert to a matrix with data.matrix() as this will be more efficient for large objects, but the code will work with dat as a data frame too.

    mat <- data.matrix(dat)
    mat[combs[1,], ] * mat[combs[2,], ]
    

    which produces:

    > mat[combs[1,], ] * mat[combs[2,], ]
      A B C D
    w 0 0 0 1
    w 0 0 1 1
    w 0 0 0 1
    x 0 0 0 1
    x 0 0 0 1
    y 0 0 0 1
    

    To see how this works, note that mat[combs[k,], ] produces a matrix with various rows repeated in the order specified by the combinations:

    > mat[combs[1,], ]
      A B C D
    w 0 0 1 1
    w 0 0 1 1
    w 0 0 1 1
    x 0 1 0 1
    x 0 1 0 1
    y 0 0 1 1
    > mat[combs[2,], ]
      A B C D
    x 0 1 0 1
    y 0 0 1 1
    z 0 0 0 1
    y 0 0 1 1
    z 0 0 0 1
    z 0 0 0 1
    

    To get exactly what the OP posted, we can modify the rownames using a second combn() call:

    > out <- mat[combs[1,], ] * mat[combs[2,], ]
    > rownames(out) <- apply(combn(rownames(dat), 2), 2, paste, collapse = "")
    > out
       A B C D
    wx 0 0 0 1
    wy 0 0 1 1
    wz 0 0 0 1
    xy 0 0 0 1
    xz 0 0 0 1
    yz 0 0 0 1
    

提交回复
热议问题