Multiply a data frame row-by-row

后端 未结 4 1326
花落未央
花落未央 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:05

    If you want to multiply rows, I recommend converting to a matrix:

    > m = as.matrix(df1)
    
    > m["x", ] * m["y", ]
    A B C D 
    0 0 0 1 
    

    The specific result you want you could get with plyr,

    library(plyr)
    
    ldply(1:(nrow(m)-1), function(i)
        ldply((i+1):nrow(m), function(j) {
            a = row.names(m)[[i]]
            b = row.names(m)[[j]]
    
            do.call(data.frame,
                c(list(a=a, b=b), m[i,] * m[j,])
            )
        })
    )
    

    Sorry part of that looks a little magical -- data.frames aren't really meant to be "row like". The lines

    do.call(data.frame,
        c(list(a=a, b=b), m[i,] * m[j,])
    )
    

    pass in the 6 columns: a and b for the names, concatenated (with c) to the multiplied row.

    0 讨论(0)
  • 2021-01-21 06:18
    dat <- read.table(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)
    > combos <- combn(rn,2)
    > combos
         [,1] [,2] [,3] [,4] [,5] [,6]
    [1,] "w"  "w"  "w"  "x"  "x"  "y" 
    [2,] "x"  "y"  "z"  "y"  "z"  "z" 
    
    apply(combos,2, function(x) c(x[1], x[2], unlist(dat[x[1],]*dat[x[2],])))
      [,1] [,2] [,3] [,4] [,5] [,6]
      "w"  "w"  "w"  "x"  "x"  "y" 
      "x"  "y"  "z"  "y"  "z"  "z" 
    A "0"  "0"  "0"  "0"  "0"  "0" 
    B "0"  "0"  "0"  "0"  "0"  "0" 
    C "0"  "1"  "0"  "0"  "0"  "0" 
    D "1"  "1"  "1"  "1"  "1"  "1" 
    

    So the final solution:

    t( apply(combos,2, function(x) c(x[1], x[2], unlist(dat[x[1],]*dat[x[2],]))) )
    

    If you convert the combos to a dataframe you would also be able to cbindmatrix as type "numeric":

     cbind( as.data.frame(t(combos)), 
            t( apply(combos,2, function(x)  
                        unlist(dat[x[1],]*dat[x[2],]))) )
    
      V1 V2 A B C D
    1  w  x 0 0 0 1
    2  w  y 0 0 1 1
    3  w  z 0 0 0 1
    4  x  y 0 0 0 1
    5  x  z 0 0 0 1
    6  y  z 0 0 0 1
    
    0 讨论(0)
  • 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
    
    0 讨论(0)
  • A shorter way (I think) using the amazing plyr package

    Your data.frame

    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,0,1,0), D=c(1,1,1,1))
    
    YOUR_COMBS<-combn(rownames(df1),2)
    

    And your result :)

    require(plyr) #(version 1.81...in version 1.82 you can take the annoying 'X1' index out... )
    
    
         YOUR_RESULTS<-adply(YOUR_COMBS,2,function(x) {
          tmp_row<-data.frame(Comb=paste0(x,collapse = ''),df1[x[1],]*df1[x[2],])
     })
    
    0 讨论(0)
提交回复
热议问题