按组和间隔坐标折叠data.frame

时间:2019-03-25 18:53:29

标签: r dataframe datatable dplyr aggregate

我有一个data.frame,它指定线性间隔(沿着染色体),其中每个间隔都分配给一个组:

df <- data.frame(chr = c(rep("1",5),rep("2",4),rep("3",5)),
                 start = c(seq(1,50,10),seq(1,40,10),seq(1,50,10)),
                 end = c(seq(10,50,10),seq(10,40,10),seq(10,50,10)),
                 group = c(c("g1.1","g1.1","g1.2","g1.3","g1.1"),c("g2.1","g2.2","g2.3","g2.2"),c("g3.1","g3.2","g3.2","g3.2","g3.3")),
                 stringsAsFactors = F)

我正在寻找一种通过dfchr折叠group的快速方法,以使{strong>连续沿chr的间隔分配给相同的group并对其startend的坐标进行相应的修改。

这是此示例的预期结果:

res.df <- data.frame(chr = c(rep("1",4),rep("2",4),rep("3",3)),
                     start = c(c(1,21,31,41),c(1,11,21,31),c(1,11,41)),
                     end = c(c(20,30,40,50),c(10,20,30,40),c(10,40,50)),
                     group = c("g1.1","g1.2","g1.3","g1.1","g2.1","g2.2","g2.3","g2.2","g3.1","g3.2","g3.3"),
                     stringsAsFactors = F)

2 个答案:

答案 0 :(得分:2)

编辑:要考虑到连续的需求,您可以使用与之前相同的方法,但是要基于连续的值添加一个额外的分组变量。

library(dplyr)

df  %>%
  group_by(chr, group, temp.grp = with(rle(group), rep(seq_along(lengths), lengths))) %>%
  summarise(start = min(start),
            end = max(end)) %>%
  arrange(chr, start) %>%
  select(chr, start, end, group)

# A tibble: 11 x 4
# Groups:   chr, group [9]
   chr   start   end group
   <chr> <dbl> <dbl> <chr>
 1 1         1    20 g1.1 
 2 1        21    30 g1.2 
 3 1        31    40 g1.3 
 4 1        41    50 g1.1 
 5 2         1    10 g2.1 
 6 2        11    20 g2.2 
 7 2        21    30 g2.3 
 8 2        31    40 g2.2 
 9 3         1    10 g3.1 
10 3        11    40 g3.2 
11 3        41    50 g3.3 

答案 1 :(得分:1)

另一种tidyverse方法可能是:

df %>%
 gather(var, val, -c(chr, group)) %>%
 group_by(chr, group) %>%
 filter(val == min(val) | val == max(val)) %>%
 spread(var, val)

  chr   group   end start
  <chr> <chr> <dbl> <dbl>
1 1     g1.1     20     1
2 1     g1.2     30    21
3 1     g1.3     50    31
4 2     g2.1     10     1
5 2     g2.2     20    11
6 2     g2.3     40    21
7 3     g3.1     10     1
8 3     g3.2     40    11
9 3     g3.3     50    41

或者:

df %>%
 group_by(chr, group) %>%
 summarise_all(funs(min, max)) %>%
 select(-end_min, -start_max)

  chr   group start_min end_max
  <chr> <chr>     <dbl>   <dbl>
1 1     g1.1          1      20
2 1     g1.2         21      30
3 1     g1.3         31      50
4 2     g2.1          1      10
5 2     g2.2         11      20
6 2     g2.3         21      40
7 3     g3.1          1      10
8 3     g3.2         11      40
9 3     g3.3         41      50

还使用rleid()中的data.table来更新帖子的解决方案是:

df %>%
 group_by(chr, group, group2 = rleid(group)) %>%
 summarise_all(funs(min, max)) %>%
 select(-end_min, -start_max)

   chr   group group2 start_min end_max
   <chr> <chr>  <int>     <dbl>   <dbl>
 1 1     g1.1       1         1      20
 2 1     g1.1       4        41      50
 3 1     g1.2       2        21      30
 4 1     g1.3       3        31      40
 5 2     g2.1       5         1      10
 6 2     g2.2       6        11      20
 7 2     g2.2       8        31      40
 8 2     g2.3       7        21      30
 9 3     g3.1       9         1      10
10 3     g3.2      10        11      40
11 3     g3.3      11        41      50