组合(粘贴)列

Combining (pasting) columns

我有以下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的起始值和结束值一致时。我试过使用 select,用 dplyr 排列和变异,但是摆脱 NAs

对我来说有点复杂

这是一个使用 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

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

此解决方案假设只要两行具有相同的 StartEnd 值,则它们必须是 gene/CDS 对(相对于 gene/gene 或CDS/CDS).

这是一种可能的方法。您选择带有基因和 CDS 的行。然后,您按开始和结束对数据进行分组。可能有 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

dplyr 版本 summarize_each:

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(不适用于 factor),以及 Start End 对仅包含两个值的条件,每个 Tipo和 Gene,就像在您的数据集中一样。

你可以试试

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