How to calculate average difference between one value and all others in a group in r

Viewed 59

I have a dataset of genes in groups and each gene has a score:

 Group Gene      Score     
    1   AQP11    0.55     
    1   CLNS1A   0.2      
    1   RSF1     0.54       
    2   CFDP1    0.41      
    2   CHST6    0.42     
    3   ACE      0.63        
    3   NOS2     0.63         

I'm looking to examine the top scored gene per group, and see the average difference in score between that gene and all others in its group.

Outputting for example (just to note calculated by hand):

 Group Gene      Score     Avg_TopGene_Difference_Per_Locus
    1   AQP11    0.55              0.18    # difference of AQP11 score with the other genes: (0.35+0.01)/2
    1   CLNS1A   0.2               0.18
    1   RSF1     0.54              0.18
    2   CFDP1    0.41              ...
    2   CHST6    0.42      
    3   ACE      0.63          
    3   NOS2     0.63          

I am trying to use a combination of group_by() and top_n but I'm not getting far with doing the actual difference calculation as diff() is sequential and not going back to only use my top score gene.

Input data:

structure(list(Group = c(1L, 1L, 1L, 2L, 2L, 3L, 3L), Gene = c("AQP11", 
"CLNS1A", "RSF1", "CFDP1", "CHST6", "ACE", "NOS2"), Score = c(0.5566507, 
0.2811747, 0.5269924, 0.4186066, 0.4295135, 0.634, 0.6345), direct_count = c(4L, 
0L, 3L, 1L, 1L, 1L, 1L), secondary_count = c(5L, 2L, 6L, 2L, 
3L, 1L, 1L)), row.names = c(NA, -7L), class = c("data.table", 
"data.frame"))
2 Answers

Would this give you what you need? It sounds like for each group, you want to get the differences between the max score and each score. Then, the Avg_TopGene_Difference_Per_Locus would be the sum of these differences, divided by the number of differences (minus 1). Note you could add a filter after group_by to ensure n() > 1 to avoid dividing by zero if that's a possibility.

library(tidyverse)

df %>%
  group_by(Group) %>%
  mutate(diff = max(Score) - Score,
         Avg_TopGene_Difference_Per_Locus = sum(diff) / (n() - 1))

Output

  Group Gene   Score direct_count secondary_count     diff Avg_TopGene_Difference_Per_Locus
  <int> <chr>  <dbl>        <int>           <int>    <dbl>                            <dbl>
1     1 AQP11  0.557            4               5 0                                0.153   
2     1 CLNS1A 0.281            0               2 0.275                            0.153   
3     1 RSF1   0.527            3               6 0.0297                           0.153   
4     2 CFDP1  0.419            1               2 0.0109                           0.0109  
5     2 CHST6  0.430            1               3 0                                0.0109  
6     3 ACE    0.634            1               1 0.000500                         0.000500
7     3 NOS2   0.634            1               1 0                                0.000500

We can use data.table methods

library(data.table)
df[,  diff := max(Score) - Score, .(Group)][, 
      Avg_TopGene_Difference_Per_Locus = sum(Diff)/(.N - 1), Group]
Related