Search code examples
rdataframelngeometric-mean

Divide value in each cell by the geometric mean of a specific row across columns and log-transform it


I would like to devide value in each cell by the geometric mean of a specific row across columns and log-transforme it (natural logarithm).

df1
      col1  col2  col3
row1  1     777   6
row2  136   1     665
row3  0     100   97

result

df_new
      col1    col2      col3
row1  -2.81   3.83     
row2           
row3              

example of the calculation for the row1 enter image description here


Solution

  • library(tidyverse)
    
    geometric_mean <- function(x){
        exp(sum(log(x), na.rm = TRUE) / length(x))
    }
    
    yourCalculation <- function(x){
        log(x / geometric_mean(x))
    }
    
    myMatrix <- tribble(
        ~col1  ,~col2  ,~col3
        , 1     , 777   , 6
        , 136   , 1     , 665
        , 0     , 100   , 97) %>%
        as.matrix()
    
    
    t(apply(myMatrix, 1, yourCalculation))
    
              col1      col2      col3
    [1,] -2.815733  3.839707 -1.023974
    [2,]  1.108508 -3.804147  2.695640
    [3,]       NaN       Inf       Inf
    

    Important about geometric means: Don't calculate them like this: prod(x)^(1/length(x)). The problem with this is, that with already medium sized vectors x you are likely to run across your type boundaries when you multiply them all and so it won't compute. The log()-and-exp() way is better.