首页 > 解决方案 > R数据帧的行组的条件语句

问题描述

想象一下我有这个数据框:

position    coverage
   1           30
   2            2
   3            1
   4            8
   5            2
   6            3
   7            20
   8            40
   .             .
   .             .
  100            0
  101            2
  102            3
  103            4
  104            1
  105           40

我想得到那些至少有 4 个位置的覆盖率低于 10 的区域。

在这种情况下,我想要的输出是:

start      end
  2         6
 100       104 

我正在尝试一个 for 循环,但我不知道如何构建它来处理一组行而不是逐行。你知道我怎样才能实现这个输出吗?

标签: r

解决方案


我们可以使用rleidfrom data.table。根据'coverage'值小于10创建分组索引,子集'position'行数大于或等于4且all'coverage'小于10,然后使用'grp'得到'position'的firstand元素last

library(data.table)
setDT(df1)[, position[.N >=4 & all(coverage < 10)],
         .(grp = rleid(coverage < 10))][,
      .(start = first(V1), end = last(V1)), grp][, grp := NULL][]
#    start end
#1:     2   6
#2:   100 104

或与dplyr

library(dplyr)
df1 %>% 
   group_by(grp = rleid(coverage < 10)) %>% 
   filter(all(coverage < 10), n() >=4) %>% 
   group_by(grp) %>% 
   summarise(start = first(position), end = last(position)) %>% 
   select(-grp)

rlebase R

rl <- rle(df1$coverage < 10)
do.call(rbind, lapply(split(df1$position,
   rep(seq_along(rl$values), rl$lengths)), range)[rl$values & rl$lengths >= 4])

数据

df1 <- structure(list(position = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 100L, 
101L, 102L, 103L, 104L, 105L), coverage = c(30L, 2L, 1L, 8L, 
2L, 3L, 20L, 40L, 0L, 2L, 3L, 4L, 1L, 40L)), class = "data.frame", 
row.names = c(NA, 
-14L))

推荐阅读