【问题标题】:Dividing rows by their sum in R在R中将行除以它们的总和
【发布时间】:2015-09-21 19:07:38
【问题描述】:

我有以下示例数据集:

Example<-data.frame(A=10*1:9,B=10*10:18)

rownames(Example)<-paste("Sample",1:9)
> Example
          A   B
Sample 1 10 100
Sample 2 20 110
Sample 3 30 120
Sample 4 40 130
Sample 5 50 140
Sample 6 60 150
Sample 7 70 160
Sample 8 80 170
Sample 9 90 180

我试图将两列中的每个元素除以其列的总数。我尝试了多种方法,但我觉得我缺少一段基本的代码,这会使这更容易。我已经走到这一步了:

ExampleSum1 <- sum(Example[,1])
ExampleSum2 <- sum(Example[,2])

但我不知道如何将 10、20、30 等除以 ExampleSum1 等。

【问题讨论】:

    标签: r arithmetic-expressions


    【解决方案1】:

    这就是你所追求的吗?

    id <- paste("sample", c(1:9))
    
    A <- seq(10, 90, 10)
    B <- seq(100, 180, 10)
    
    Example <- data.frame(id, A, B)
    
    Example$A2 <- with(Example, A/sum(A))
    Example$B2 <- with(Example, B/sum(B))
    

    注意:新列 A2 和 B2。

        id    A   B         A2         B2
     sample 1 10 100 0.02222222 0.07936508
     sample 2 20 110 0.04444444 0.08730159  
     sample 3 30 120 0.06666667 0.09523810
     sample 4 40 130 0.08888889 0.10317460
     sample 5 50 140 0.11111111 0.11111111
     sample 6 60 150 0.13333333 0.11904762
     sample 7 70 160 0.15555556 0.12698413
     sample 8 80 170 0.17777778 0.13492063
     sample 9 90 180 0.20000000 0.14285714
    

    【讨论】:

      【解决方案2】:

      您可以使用colSumspaste 获取列总和,以使新的列名派生自之前的列名。 colSums 返回列和的向量,但要进行列除法,您需要使用一些技巧。最好的方法似乎是提到的@user20650。

      ## Make new columns: proportions of column sums
      dat[,paste(names(dat),"prop", sep="_")] <- t( t(dat) / colSums(dat) )
      
      dat
      #          A   B     A_prop     B_prop
      # Sample1 10 100 0.02222222 0.07936508
      # Sample2 20 110 0.04444444 0.08730159
      # Sample3 30 120 0.06666667 0.09523810
      # Sample4 40 130 0.08888889 0.10317460
      # Sample5 50 140 0.11111111 0.11111111
      # Sample6 60 150 0.13333333 0.11904762
      # Sample7 70 160 0.15555556 0.12698413
      # Sample8 80 170 0.17777778 0.13492063
      # Sample9 90 180 0.20000000 0.14285714
      

      数据

      dat <- read.table(text="A      B
      Sample1    10     100
      Sample2    20     110
      Sample3    30     120
      Sample4    40     130
      Sample5    50     140
      Sample6    60     150
      Sample7    70     160
      Sample8    80     170
      Sample9    90     180", header=T)
      

      【讨论】:

      • 另一个基本 R 替代品prop.table(as.matrix(dat), 2)
      • @Legalizelt,很好的答案!
      【解决方案3】:

      如果只是一个apply

       apply(dat, 2, function(x) x / sum(x))
                       A          B
      Sample1 0.02222222 0.07936508
      Sample2 0.04444444 0.08730159
      Sample3 0.06666667 0.09523810
      Sample4 0.08888889 0.10317460
      Sample5 0.11111111 0.11111111
      Sample6 0.13333333 0.11904762
      Sample7 0.15555556 0.12698413
      Sample8 0.17777778 0.13492063
      Sample9 0.20000000 0.14285714
      

      【讨论】:

        【解决方案4】:

        data.table解决方案:

        sum.cols = c("A", "B")
        library(data.table)
        setDT(Example, keep.rownames = TRUE)
        Example[ , (sum.cols) := lapply(.SD, function(x) x/sum(x)), .SDcols = sum.cols]
        

        或者在你的情况下可能更直接:

        Example[ , c("A", "B") := .(A/sum(A), B/sum(B))]
        

        哪个给:

        Example
        #          rn          A          B
        # 1: Sample 1 0.02222222 0.07936508
        # 2: Sample 2 0.04444444 0.08730159
        # 3: Sample 3 0.06666667 0.09523810
        # 4: Sample 4 0.08888889 0.10317460
        # 5: Sample 5 0.11111111 0.11111111
        # 6: Sample 6 0.13333333 0.11904762
        # 7: Sample 7 0.15555556 0.12698413
        # 8: Sample 8 0.17777778 0.13492063
        # 9: Sample 9 0.20000000 0.14285714
        

        与使用colSumssweep 的方法相比,这种方法的主要吸引力在于,这两种方法都需要将您的数据转换为矩阵然后再返回,这可能会很昂贵。这取决于您的用例;如果您的表很小,这些其他方法都可以,这取决于您认为最易读的内容。

        我还注意到没有其他答案提到mapply 方法,它几乎适用于任何范例;这是data.table 方法:

        Example[ , (sum.cols) := mapply(`/`, .SD, lapply(.SD, sum), SIMPLIFY = FALSE), 
                .SDcols = sum.cols]
        

        【讨论】:

          【解决方案5】:

          你可以这样做:

          library(dplyr)
          dat %>% mutate_each(funs(. / sum(.)))
          

          这给出了:

          #           A          B
          #1 0.02222222 0.07936508
          #2 0.04444444 0.08730159
          #3 0.06666667 0.09523810
          #4 0.08888889 0.10317460
          #5 0.11111111 0.11111111
          #6 0.13333333 0.11904762
          #7 0.15555556 0.12698413
          #8 0.17777778 0.13492063
          #9 0.20000000 0.14285714
          

          如果您想保留行名,请执行以下操作:

          dat %>% add_rownames("rn") %>% mutate_each(funs(. / sum(.)), -rn) 
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-05-13
            • 2019-07-21
            • 1970-01-01
            • 1970-01-01
            • 2023-03-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多