【问题标题】:Multiply a data frame row-by-row逐行乘以数据框
【发布时间】:2011-09-04 05:05:13
【问题描述】:

输入文件:

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))

  A B C D
w 0 0 1 1
x 0 1 0 1
y 0 0 1 1
z 0 0 0 1

我想应用一个等式,即将行 w 乘以行 x 以获得 w-x 对的成对值,如下所示:

      A B C D
    w 0 0 1 1
X   x 0 1 0 1
--------------
   wx 0 0 0 1

获取 w-x、w-y、w-y、w-z、x-y、x-z、y-z 的逐行分析。并生成一个包含 6 列的新数据框(两个行名后跟相乘的值)。

那是

w x 0 0 0 1
w y 0 0 1 1
w z 0 0 0 1
x y 0 0 0 1
x z 0 0 0 1
y z 0 0 0 1

谢谢。

【问题讨论】:

    标签: r multiplication


    【解决方案1】:

    如果您不希望结果对象中的组合名称,那么我们可以结合@DWin 和@Owen 的答案的元素来提供一个真正矢量化的方法来解决这个问题。 (您可以将组合名称添加为行名称,并在最后添加一个额外的步骤。)

    一、数据:

    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)
    

    从@DWin 的答案中获取combn() 的想法,但在dat行索引 上使用它:

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

    combs 的行现在索引我们想要相乘的dat 的行:

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

    现在我们采用@Owen 展示的想法,即dat[i, ] * dat[j, ]ij 分别是combs 的第一行和第二行。我们使用data.matrix() 转换为矩阵,因为这对于大型对象更有效,但代码也可以使用dat 作为数据框。

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

    产生:

    > 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
    

    要了解其工作原理,请注意mat[combs[k,], ] 会生成一个矩阵,其中包含按组合指定的顺序重复的各行:

    > 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
    

    要准确获取 OP 发布的内容,我们可以使用第二个 combn() 调用来修改行名:

    > 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
    

    【讨论】:

      【解决方案2】:
      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" 
      

      所以最终的解决方案:

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

      如果您将组合转换为数据框,您还可以将 cbindmatrix 设置为“数字”类型:

       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
      

      【讨论】:

        【解决方案3】:

        如果你想将行相乘,我建议转换为矩阵:

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

        您可以通过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,])
                )
            })
        )
        

        抱歉,这看起来有点神奇——data.frames 并不是真的要“像行一样”。线条

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

        传入 6 列:a 和 b 作为名称,连接(与 c)到相乘的行。

        【讨论】:

          【解决方案4】:

          使用神奇的 plyr 包的更短的方法(我认为)

          你的数据框架

          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)
          

          你的结果:)

          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],])
           })
          

          【讨论】:

            猜你喜欢
            • 2022-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-07-26
            • 2018-12-14
            • 1970-01-01
            • 1970-01-01
            • 2019-03-05
            相关资源
            最近更新 更多