【问题标题】:Tidy way to summarize several columns of data in R?总结R中几列数据的整洁方法?
【发布时间】:2021-08-24 05:10:15
【问题描述】:

我有一个包含转录 ID 及其相关基因名称的大型数据框,以及一个指示某个模型是否报告该基因/转录本具有重要意义的列。尽管每个基因都与多个转录本相关联,但每个转录本总是与一个基因相关联。这是一个可重现的示例:

transcript <- c('t1', 't2', 't3', 't4', 't5', 't6', 't7','t8', 't9', 't10')
gene <- c('g1', 'g1', 'g1', 'g2', 'g2', 'g2', 'g3','g3', 'g3', 'g3')
model1 <- c('TRUE', 'TRUE', 'TRUE', 'FALSE', 'FALSE', 'FALSE', 'TRUE', 'TRUE', 'TRUE', 'TRUE')
model2 <-c('FALSE', 'FALSE', 'FALSE', 'TRUE', 'TRUE', 'TRUE', 'TRUE', 'TRUE', 'TRUE', 'TRUE')
shared <- data.frame(transcript, gene, model1, model2)
shared

transcript gene model1 model2
<chr> <chr> <chr> <chr>
t1  g1  TRUE    FALSE   
t2  g1  TRUE    FALSE   
t3  g1  TRUE    FALSE   
t4  g2  FALSE   TRUE    
t5  g2  FALSE   TRUE    
t6  g2  FALSE   TRUE    
t7  g3  TRUE    TRUE    
t8  g3  TRUE    TRUE    
t9  g3  TRUE    TRUE    
t10 g3  TRUE    TRUE

我想通过 TRUE 值的数量和标识来浓缩和总结这个 df,如下所示:

n_transcripts n_genes transcripts genes
<dbl> <dbl> <chr> <chr>
model1  7   2   t1;t2;t3;t7;t8;t9;t10   g1;g3
model2  7   2   t4;t5;t6;t7;t8;t9;t10   g2;g3

我尝试过创建一个空白 df 并从初始 df 中进行总结,但在区分模型 1 和模型 2 时一直被搁置。实际上,我有几十个模型,并希望避免手动遍历每个模型。有没有人知道从哪里开始?

【问题讨论】:

    标签: r dplyr summary


    【解决方案1】:

    在模型列上转为更长的格式并仅过滤那些值为 TRUE 的行。按模型分组并总结想要的值。

    shared %>%
      pivot_longer(
        cols = matches("^model[0-9]+$"),
        names_to = "model"
      ) %>%
      filter(value == TRUE) %>%
      group_by(model) %>%
      summarise(
        n_transcripts = n(),
        n_genes = length(unique(gene)),
        transcripts = str_c(unique(transcript), collapse = ";"),
        genes = str_c(unique(gene), collapse = ";"),
      )
    

    【讨论】:

      【解决方案2】:

      这是我的做法。

      我的方法是使用包dplyr,它擅长总结这样的数据。但是,当您的数据呈整齐的形式时效果最好,这意味着它是完美的正方形并且每一列都是一个变量。这意味着“model1”和“model2”两列必须合二为一,如下所示:

      require(dplyr)
      
      shared <- shared %>% 
        gather(., key = "model", value = "expr", -c(1:2))
      

      这会将模型 1 和模型 2 行放在彼此的顶部,并将它们生成的 TRUE/FALSE 放入它们自己的变量中,我在这里称之为 expr

      您的数据现在确实有更多行,但现在总结起来要容易得多,因为我们可以在“模型”列上使用dplyr::group_by() 并将其余部分相加。首先,我们必须解决一些其他问题。

      在您的数据中,您的 TRUE/FALSE 值是“字符”值,而不是逻辑值。这意味着 R 像名称一样理解这些值,而不是像是/否、0/1 或其他任何东西。当我们要计算这些时,我将它们更改为如下值:

      shared[shared == "TRUE"] <- 1
      shared[shared == "FALSE"] <- 0
      
      shared$expr <- as.numeric(shared$expr)
      

      需要像我在这里所做的那样将expr 类型强制为as.numeric(),因为它再次更改为“字符”。这可能是我的侥幸。

      不管怎样,我们现在准备总结一下。如果您对dplyr 不熟悉,那么下一部分可能会让人感到困惑:

      shared <- shared %>% 
        .[.$expr == 1, ] %>%  #Remove the rows with FALSE (0)
        group_by(model) %>% 
        summarize(n_transcripts = sum(expr), #Sum all the TRUE (1)
                  n_genes = length(unique(gene)), #Count unique genes
                  transcripts = paste(unique(transcript), collapse = ";"), 
                  genes = paste(unique(gene), collapse = ";"))
      

      这里发生了很多事情,dplyr 让我们可以一口气完成所有这些事情。我正在使用%&gt;%(管道)运算符将每个函数的结果传递给下一个函数。此函数/调用的真正内容是函数summarize(),它将计算/粘贴/统计“模型”列中每个唯一值的数据,在本例中为“模型1”和“模型2”

      【讨论】:

      • 感谢您对每个步骤的非常详细的解释!
      猜你喜欢
      • 2017-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-07
      • 1970-01-01
      • 2023-03-07
      相关资源
      最近更新 更多