个别数字(核苷酸)的分裂区间(基因组区域)

时间:2014-08-20 16:17:25

标签: r intervals regions

我想基于区域(逐个数字或核苷酸核苷酸)信息转换基于区域的数据框df

我的输入df

start  end  state  freq
 100   103   1nT    22
 100   103   3nT    34
 104   106   1nT    12
 104   106   3nT    16

我的预期输出:

position state freq
  100     1nT   22
  101     1nT   22
  102     1nT   22
  103     1nT   22
  100     3nT   34
  101     3nT   34
  102     3nT   34
  103     3nT   34
  104     1nT   12
  105     1nT   12
  106     1nT   12
  104     3nT   16
  105     3nT   16
  106     3nT   16

有什么想法吗?非常感谢你。

4 个答案:

答案 0 :(得分:2)

这是一种矢量化方法:

# load your data
df <- read.table(textConnection("start  end  state  freq
 100   103   1nT    22
 100   103   3nT    34
 104   106   1nT    12
 104   106   3nT    16"), header=TRUE)

# extract number of needed replications
n <- df$end - df$start + 1

# calculate position and replicate state/freq
res <- data.frame(position = rep(df$start - 1, n) + sequence(n),
                  state = rep(df$state, n),
                  freq = rep(df$freq, n))
res
#    position state freq
# 1       100   1nT   22
# 2       101   1nT   22
# 3       102   1nT   22
# 4       103   1nT   22
# 5       100   3nT   34
# 6       101   3nT   34
# 7       102   3nT   34
# 8       103   3nT   34
# 9       104   1nT   12
# 10      105   1nT   12
# 11      106   1nT   12
# 12      104   3nT   16
# 13      105   3nT   16
# 14      106   3nT   16

答案 1 :(得分:1)

这是一种方法......

构建数据

require(data.table)
fakedata <- data.table(start=c(100,100,104,104),
                       end=c(103,103,106,106),
                       state=c("1nT","3nT","1nT","3nT"),
                       freq=c(22,34,12,16))

执行计算

fakedata[ , dur := (end-start+1)]
outdata <- fakedata[ , lapply(.SD,function(x) rep(x,dur))]
outdata[ , position := (start-1)+1:.N, by=list(start,end,state)]

输出

    start end state freq dur position
 1:   100 103   1nT   22   4      100
 2:   100 103   1nT   22   4      101
 3:   100 103   1nT   22   4      102
 4:   100 103   1nT   22   4      103
 5:   100 103   3nT   34   4      100
 6:   100 103   3nT   34   4      101
 7:   100 103   3nT   34   4      102
 8:   100 103   3nT   34   4      103
 9:   104 106   1nT   12   3      104
10:   104 106   1nT   12   3      105
11:   104 106   1nT   12   3      106
12:   104 106   3nT   16   3      104
13:   104 106   3nT   16   3      105
14:   104 106   3nT   16   3      106

答案 2 :(得分:1)

这可以通过简单的apply命令来完成。

让我们按顺序构建:

  1. 您希望基于每一行执行操作,因此应该首先考虑按行应用(或for循环)。所以我们知道我们想要使用apply(data, 1, row.function)

  2. 想想你想要为一行做什么。您想为statefreq之间的每个数字重复startstop。 要获得start和stop之间的数字范围,我们可以使用冒号运算符start:stop。 现在,R将自动重复向量中的值,以匹配创建data.frame时最长的向量长度。因此,我们可以像这样从一行创建这个部分:

    data.frame(position=(row['start']:row['end']), state=row['state'], freq=row['freq'])
    
  3. 然后我们想把它们绑在一起,所以我们使用`do.call('rbind',result)。

  4. 现在把这些全部放在一起,我们有:

    do.call('rbind',        
      apply(data, 1, function(row) {
        data.frame(position=(row['start']:row['end']),
          state=row['state'], freq=row['freq'])
      }))
    
  5. 哪个会给你你想要的东西。希望这有助于教你如何在未来处理这样的问题!

答案 3 :(得分:0)

这是使用for循环的粗略实现。

    a = t(matrix(c(100, 103,  "1nT" ,   22,
    100,   103 ,  "3nT" ,   34,
    104,   106 ,  "1nT" ,   12,
    104,   106 ,  "3nT" ,   16), nrow = 4))
    a = data.frame(a, stringsAsFactor = F)

    colnames(a) = c("start",  "end" , "state",  "freq")
    a$start = as.numeric(as.character(a$start))
    a$end = as.numeric(as.character(a$end))

    n = dim(a)[1]
    res = NULL

    for (i in 1:n) {
      position = a$start[i]:a$end[i]
      state = rep(a$state[i], length(position))
      freq = rep(a$freq[i], length(position))
      temp = cbind.data.frame(position, state, freq)
      res = rbind(res, temp)
    }