【问题标题】:Combining (pasting) columns组合(粘贴)列
【发布时间】:2015-04-20 15:23:31
【问题描述】:

我有以下data.frame

Tipo Start  End Strand Accesion1 Accesion2
1 gene   197 1558      +      <NA>   SP_0001
2  CDS   197 1558      + NP_344554      <NA>
3 gene  1717 2853      +      <NA>   SP_0002
4  CDS  1717 2853      + NP_344555      <NA>
5 gene  2864 3112      +      <NA>   SP_0003
6  CDS  2864 3112      + NP_344556      <NA>

还有更多的“Tipo”值,例如 tRNA、region、exon 或 rRNA,但我只对结合这两个感兴趣,gene 和 CDS

我想得到以下内容

Start End Accesion1 Accesion2
1 197 1558 NP_344554 SP_0001

但仅当基因和 CDS 的 start 和 End 值一致时。我尝试使用 dplyr 使用 select、arrange 和 mutate,但摆脱 NA 对我来说有点复杂

【问题讨论】:

  • 您可能需要提供更多详细信息,关于gene/CDS 是否成对出现。目前尚不清楚,因为您提到还有其他值 tRNA, region, exon 等。假设,如果 df1$Start[6] &lt;- 2964 示例数据集的预期结果是什么
  • 是的,它们成对出现您提供的解决方案似乎效果很好。因为存在一些额外的 Tipo,所以会出现一些 NA,但我可以使用 complete.cases 轻松丢弃它们。我正在寻找 dplyr 的解决方案,只是因为我喜欢它。但是解决方案(你删除了?)效果很好
  • 你能检查一下这是否有效library(data.table);setDT(df1)[, id:=cumsum(Tipo == 'gene')][,list(Accesion1=na.omit(Accesion1), Accesion2=na.omit(Accesion2)) , list(id, Start, End)]
  • 是的,它工作得很好。我得到了同样的结果

标签: r dplyr


【解决方案1】:

带有summarize_eachdplyr 版本:

DF %>% 
  group_by(Start, End) %>% 
  summarise_each(funs(max), Accesion1, Accesion2)

生产:

Source: local data frame [3 x 4]
Groups: Start

  Start  End Accesion1 Accesion2
1   197 1558 NP_344554   SP_0001
2  1717 2853 NP_344555   SP_0002
3  2864 3112 NP_344556   SP_0003

假设 AccessionX 变量是 character(不适用于因子),以及 Start End 对仅包含两个值(Tipo 和 Gene 各一个)的条件,如您的数据设置。

【讨论】:

  • 我不知道为什么,但我不明白。一个 sapply(df, class) 告诉我 Accesion1 和 3 是字符。但是我得到这个 Start End Accesion1 Accesion2 1 197 1558 NA NA 2 1717 2853 NA NA 3 2864 3112 NA NA 4 3196 4311 NA NA 5 4382 4951 NA NA 6 4952 8461 NA NA 7 8519 8785 NA NA 8 9273 NA NA 10 9266 10534 NA NA
  • 我认为可能需要summarise_each(funs(max=max(., na.rm=TRUE)), Accesion1, Accesion2)
  • @akrun,谢谢,我的数据实际上有 "&lt;NA&gt;" 的字符版本,所以它工作得很好。
【解决方案2】:

你可以试试

library(data.table)
setDT(df1)[, id:=cumsum(Tipo == 'gene')][,
   list(Accesion1=na.omit(Accesion1), Accesion2=na.omit(Accesion2)) ,
                              list(id, Start, End)]

【讨论】:

    【解决方案3】:

    这是使用aggregate()的解决方案:

    df <- data.frame(Tipo=c('gene','CDS','gene','CDS','gene','CDS'), Start=c(197,197,1717,1717,2864,2864), End=c(1558,1558,2853,2853,3112,3112), Strand=c('+','+','+','+','+','+'), Accesion1=c(NA,'NP_344554',NA,'NP_344555',NA,'NP_344556'), Accesion2=c('SP_0001',NA,'SP_0002',NA,'SP_0003',NA) );
    df2 <- df[df$Tipo%in%c('gene','CDS'),c('Start','End','Accesion1','Accesion2')];
    aggregate(df2[,c('Accesion1','Accesion2')], df2[,c('Start','End')], function(x) x[!is.na(x)] );
    ##   Start  End Accesion1 Accesion2
    ## 1   197 1558 NP_344554   SP_0001
    ## 2  1717 2853 NP_344555   SP_0002
    ## 3  2864 3112 NP_344556   SP_0003
    

    如果原始data.frame中有非基因非CDS行,则必须预先计算df2;为了正确聚合基因和 CDS 行,非基因非 CDS 行必须从xby 中排除。 (当然,您的示例数据只有基因和 CDS 行,因此示例数据在技术上不是必需的。)

    此解决方案假设只要两行具有相同的StartEnd 值,那么它们必须是基因/CDS 对(而不是基因/基因或CDS/CDS)。

    【讨论】:

    • 感谢您的评论。我没有检查所有情况下的解决方案,因为 OP 提到它有效(基于 cmets)。
    • 我也非常喜欢这个答案。谢谢
    【解决方案4】:

    这是一种可能的方法。您选择带有基因和 CDS 的行。然后,按 Start 和 END 对数据进行分组。可能有 1 或 3 行以上的 START/END 组。因此,您要确保选择具有两行的 START/END 组。此外,您要确保同时拥有基因和 CDS (length(unique(Tipo)) == 2)。最后,在 Accesion1 和 Accesion 2 中取非 NA 元素。

    filter(df, Tipo %in% c("gene", "CDS")) %>%
    group_by(Start, End) %>%
    filter(n() == 2 & length(unique(Tipo)) == 2) %>%
    summarise(Accesion1 = Accesion1[!is.na(Accesion1)],
              Accesion2 = Accesion2[!is.na(Accesion2)])
    

    这是一个伪示例。

    mydf <- structure(list(Tipo = structure(c(2L, 1L, 2L, 1L, 2L, 2L), .Label = c("CDS", 
    "gene"), class = "factor"), Start = c(197, 197, 1717, 1717, 2864, 
    2864), End = c(1558, 1558, 2853, 2853, 3112, 3112), Strand = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L), .Label = "+", class = "factor"), Accesion1 = structure(c(NA, 
    1L, NA, 2L, NA, 3L), .Label = c("NP_344554", "NP_344555", "NP_344556"
    ), class = "factor"), Accesion2 = structure(c(1L, NA, 2L, NA, 
    3L, NA), .Label = c("SP_0001", "SP_0002", "SP_0003"), class = "factor")), .Names = c("Tipo", 
    "Start", "End", "Strand", "Accesion1", "Accesion2"), row.names = c(NA, 
    -6L), class = "data.frame")
    
    
      Tipo Start  End Strand Accesion1 Accesion2
    1 gene   197 1558      +      <NA>   SP_0001
    2  CDS   197 1558      + NP_344554      <NA>
    3 gene  1717 2853      +      <NA>   SP_0002
    4  CDS  1717 2853      + NP_344555      <NA>
    5 gene  2864 3112      +      <NA>   SP_0003
    6 gene  2864 3112      + NP_344556      <NA>
    
    
    filter(mydf, Tipo %in% c("gene", "CDS")) %>%
    group_by(Start, End) %>%
    filter(n() == 2 & length(unique(Tipo)) == 2) %>%
    summarise(Accesion1 = Accesion1[!is.na(Accesion1)],
              Accesion2 = Accesion2[!is.na(Accesion2)])
    
    #  Start  End Accesion1 Accesion2
    #1   197 1558 NP_344554   SP_0001
    #2  1717 2853 NP_344555   SP_0002
    

    【讨论】:

    • @akrun 我有点生疏了。我想知道上面的例子澄清了你的观点。如果我错过了您的观点,请告诉我。
    • 这是否意味着我的 data.frame 必须包含因子?我的实际上不包含因素。这是一个普通的 data.frame,你的代码不起作用。
    • @AntonioRodriguezFranco 当我看到你的问题时,不清楚你是否有性格或因素。让我修改一下我的建议。
    • @AntonioRodriguezFranco 我尝试使用包含 Tipo、Accesion1 和 2 作为字符的 data.frame。我的代码返回了预期的结果。我想知道是否发生了其他事情。
    猜你喜欢
    • 2021-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-27
    • 1970-01-01
    • 2017-09-21
    • 1970-01-01
    相关资源
    最近更新 更多